包含比指定更多字符的数组

时间:2019-03-03 13:24:45

标签: c file

我正在学习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个字母。

在思考过程中我哪里出错了?

2 个答案:

答案 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在访问内存时非常自由;)