我做了一个简单的C程序来读取.txt文件中的数据并将其打印到屏幕上。
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
为什么会出现分段错误以及它意味着什么?
答案 0 :(得分:0)
C printf()
,scanf()
,fscanf()
,实际上大多数字符串功能都适用于 null终止字符串。
在计算机编程中,以null结尾的字符串是一个字符串,存储为包含字符的数组,并以空字符(
'\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()
写入缓冲区的第4个字符,因此<{1}} 。
这只会覆盖堆栈中的一些局部变量。
错误很可能是由于将NULL
写入存储指向文件的指针的内存位置(NULL
),在下一次迭代时产生FILE *fp
,当我们再次尝试从文件中读取时。
为了说明这一点,这就是你的堆栈的样子:
Segmentation fault
| buffer[0] | buffer[1] | buffer[2] | fp | fp | fp | fp | ...
尝试将fscanf()
写入缓冲区,因此它从缓冲区的开头开始,并分别将1,2,3放在位置0,1,2中。但"123\0"
个字符恰好放在NULL
的一部分位置,从而破坏了指针。
答案 1 :(得分:0)
你的字符串缓冲区需要有'\ 0'字符的空格,表示字符串的结尾:字符串“123”实际上是['1','2','3','\ 0'] 。 fscanf
会自动添加'\ 0'。
答案 2 :(得分:0)
您的具体问题是c-strings是 nul-terminateded 字符数组。
换句话说,意味着3个字符串需要存储4个字节char
缓冲区:
------------------
| 1 | 2 | 3 | \0 |
------------------
所以
char buffer[3];
必须是
char buffer[4];
BTW这不是一个完全正确的解决方案,因为你必须声明你的数组足够大,以包含可以在文件中检索的最长字符串。
答案 3 :(得分: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是一个更好的解决方案