我正在学习C语言中的文件管理。我编写了这段代码,但是输出不是我期望的。
#include <stdio.h>
int main(int argc, char * argv[]){
int i;
char str[12];
FILE *fp;
fp = fopen("Names.dat", "w+");
for(i = 1; i < argc; i++){
fprintf(fp, "%s ", argv[i]);
}
rewind(fp);
fscanf(fp,"%[^\n]", str);
printf("%s", str);
return 0;
}
我将其编译并按如下方式运行
gcc test.c
a abcdefghijklmnopqrstuvwxyz
输出如下:
abcdefghijklmnopqrstuvwxyz
我认为它只会输出前12个字母。
在思考过程中我哪里出错了?
答案 0 :(得分:2)
fscanf(fp,"%[^\n]", str);
尝试从 str 开始读取字符并将其写入内存,直到遇到'\ n'或EOF,而与 str 长度无关。 em>
所以,
char str[12]; ... fscanf(fp,"%[^\n]", str);
从文件中读取27个字符的字符串“ abcdefghijklmnopqrstuvwxyz”,将写入&str [0] 中的28个字符,并且行为未指定(可能是崩溃)。
包含比指定更多字符的数组
否,str[12]
允许空结尾字符多存储11个字符,仅此而已。
要从文件中读取最多11个字符,请执行以下操作:
fscanf(fp,"%11[^\n]", str);
这样做,编译和执行:
pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra m.c
pi@raspberrypi:/tmp $ ./a.out abcdefghijklmnopqrstuvwxyz
abcdefghijkpi@raspberrypi:/tmp $
和 valgrind 下:
pi@raspberrypi:/tmp $ valgrind ./a.out abcdefghijklmnopqrstuvwxyz
==10408== Memcheck, a memory error detector
==10408== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10408== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==10408== Command: ./a.out abcdefghijklmnopqrstuvwxyz
==10408==
abcdefghijk==10408==
==10408== HEAP SUMMARY:
==10408== in use at exit: 352 bytes in 1 blocks
==10408== total heap usage: 3 allocs, 2 frees, 5,472 bytes allocated
==10408==
==10408== LEAK SUMMARY:
==10408== definitely lost: 0 bytes in 0 blocks
==10408== indirectly lost: 0 bytes in 0 blocks
==10408== possibly lost: 0 bytes in 0 blocks
==10408== still reachable: 352 bytes in 1 blocks
==10408== suppressed: 0 bytes in 0 blocks
==10408== Rerun with --leak-check=full to see details of leaked memory
==10408==
==10408== For counts of detected and suppressed errors, rerun with: -v
==10408== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
P.S。在使用 puts 的printf printf("%s\n", str);
中添加\ n以获得更易读的结果:
pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra m.c
pi@raspberrypi:/tmp $ ./a.out abcdefghijklmnopqrstuvwxyz
abcdefghijk
pi@raspberrypi:/tmp $
P.S。当然要从文件中读取12个字符
char str[13];
...
fscanf(fp,"%12[^\n]", str);
答案 1 :(得分:0)
即使您分配了大小为12的数组,这也不意味着您无法超出其范围进行写入(或读取)。
fscanf
期望将指针作为第三个参数,并且指针不具有有关长度的信息,因为fscanf
无法知道您分配了多少内存,这是调用者的责任。
C在访问内存时非常自由;)