2017-05-15 60 views
-1

我做了一个简单的C程序来读取.txt文件中的数据并将其打印到屏幕上。为什么在这个C程序中发生了段错误?

FILE *fp = fopen("words.txt", "r"); 

char buffer[3]; 

while (fscanf(fp, "%s", buffer) != EOF) 
printf(" %s\n ", buffer); 

printf("\n"); 

word.txt里面只写了123个。现在,我运行程序时得到的输出是

123 
Segmentation fault 

为什么这个分段错误到来了,它意味着什么?

+2

'字符缓冲区[3];' - >' char buffer [4];','fscanf(fp,“%s”,buffer)' - >'fscanf(fp,“%3s”,buffer)' – BLUEPIXY

+3

您忘记了字符串的'\ 0' .txt内容将在您的程序中转换为“123 \ 0”。将缓冲区[3]更改为缓冲区[4]; –

+0

将缓冲区[3]更改为缓冲区[256],并停止bean计数(除非您在某些受RAM限制的嵌入式系统上)。 – ThingyWotsit

回答

1

Çprintf()scanf()fscanf(),实际上大部分的字符串功能也适用空结束的字符串

在计算机程序中,空终止字符串存储为一个包含字符的阵列,并用空字符('\0',在ASCII称为NUL)终止的字符串。

因此,当您的输入包含3个字符时,还必须为空字符保留空间。 在你的榜样,缓冲区应该是大小至少为4

为了防止用户错误,你总是可以使用限制输入的大小:

char buffer[16]; // An array of 16 for example 
scanf("%15s", buffer); // Must also reserve space for the null 

注意,Segmentation fault你得到的是不是由于fscanf()函数试图将NULL写入缓冲区的第4个字符。 这只会覆盖堆栈上的一些局部变量。

该错误是最有可能是由于写NULL到的指针文件存储的存储位置(FILE *fp),上而下一次迭代产生Segmentation fault,当我们试图从文件中再次读取。

来说明吧,这是你的筹码看起来的样子:

| buffer[0] | buffer[1] | buffer[2] | fp | fp | fp | fp | ... 

fscanf()尝试写"123\0"到缓冲区,因此它与缓冲器的起点开始,并在地方放1,2,3分别为0,1,2。但是NULL字符恰好放置在fp的一部分,因此破坏了指针。

+0

我总是很高兴听到批评,所以知道为什么downvote会很好。 –

0

你的字符串缓冲区需要有用于表示字符串结尾的'\ 0'字符的空间:字符串“123”实际上是['1','2','3','\ 0' ]。 fscanf将自动添加'\ 0'。

0

您的具体问题是零终止字符数组。

即换句话说意味着,3个字符字符串需要4个字节被存储char缓冲液:

------------------ 
| 1 | 2 | 3 | \0 | 
------------------ 

所以

char buffer[3]; 

必须是

char buffer[4]; 

顺便说一句,这是不一个完全正确的解决方案,因为你必须声明你的数组大到足以包含th可以在文件中检索最长的字符串。

0

这是因为NULL字符\0你的字符串不是3个字符长,但实际上是4个字符长。你的缓冲区太小

只是一个建议,使用的fscanf是不是最好的解决方案,我想用

#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    FILE *f = fopen("words.txt", "rb"); 
    fseek(f, 0, SEEK_END); 
    long fsize = ftell(f); 
    fseek(f, 0, SEEK_SET); //same as rewind(f);         

    char *string = malloc(fsize + 1); 
    fread(string, fsize, 1, f); 
    fclose(f); 

    string[fsize] = 0; 
    printf("%s\n", string); 
} 

FREAD是一个更好的解决方案

相关问题