sscanf函数更改另一个字符串的内容

我在使用sscanf读取字符串时遇到问题。 我已经愚弄了代码以专注于问题。 下面是整个代码中的一个函数,它应该打开一个文件并读取一些内容。 但是sscanf表现得很奇怪。 例如,我声明一个名为atm的字符串,其内容为'ATOM' 。 在sscanf之前,它将此字符串作为ATOM打印,而在它之后为空。 可能是什么问题呢? 我认为它必须是分配问题,但我找不到它。 我尝试了其他主题的一些建议,比如用其他东西替换%s ,但它没有帮助。

  void Get (struct protein p, int mode, int type) { FILE *fd; //input file char name[100]="1CMA"; //array for input file name char string[600]; //the array where each line of the data file is stored when reading char atm[100]="ATOM"; char begin[4]; int index1 =0; fd = fopen(name, "r"); // open the input file if(fd==NULL) { printf("Error: can't open file.\n"); return 1; } if( type==0 ) { //pdb file type if( mode==0 ) { while( fgets(string, 600, fd)!=NULL ) { printf("1 %s\n",atm); sscanf (string, "%4s", begin ); printf("2 %s \n",atm); } } } fclose(fd); free(fd); free(name); } 

字符串begin不足以容纳sscanf将读取的四个字符及其\0终止符。 如果将\0写入atm (取决于字符串在内存中的位置),则会修改atm 。 从sscanf联机帮助页 ,关于s指令:

s匹配一系列非空白字符; 下一个指针必须是一个指向字符数组的指针,该指针足够长以容纳输入序列和终止空字节(’\ 0’),这是自动添加的。 输入字符串在空白处或最大字段宽度处停止,以先发生者为准。

我能够在我的机器上重现这种行为,尽管字符串在内存中的确切位置有点不同。 但是,通过打印字符串的地址,可以很容易地确定发生了什么。 这是一个最小的例子:

 #include int main() { char begin[2]; char atm[100]="ATOM"; printf("begin: %p\n", begin); printf("begin+16: %p\n", begin+16); printf("atom: %p\n", atm); printf("1 %s\n",atm); sscanf("AAAABBBBCCCCDDDD", "%16s", begin); printf("2 %s \n",atm); return 0; } 

这会产生输出:

 $ ./a.out begin: 0x7fffffffe120 begin+16: 0x7fffffffe130 atom: 0x7fffffffe130 1 ATOM 2 

我打印了指针的值,以确定溢出到atm的字符串有多大。 因为(在我的机器上) atombegin+16 ,读取十六个字符到begin将一个空终止符放在begin+16 ,这是atm的第一个字符,所以现在atm长度为0。