1

我在读取字符串时遇到问题sscanf。我已经简化了代码以专注于问题。下面是整个代码中的一个函数,它应该打开一个文件并读取一些东西。却sscanf表现得很奇怪。例如,我声明了一个名为atmcontent的字符串'ATOM'。在它为空之后,sscanf它打印这个字符串作为while。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);
 }
4

1 回答 1

1

该字符串begin不够大,无法容纳sscanf将要读取的四个字符及其终止\0符。如果\0写入atm(取决于字符串在内存中的位置),atm将被修改。从sscanf 手册页,关于s指令:

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

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

#include<stdio.h>

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. 由于(在我的机器上)atom从 开始begin+16,读取 16 个字符会在begin处放置一个空终止符begin+16,这是 的第一个字符atm,所以现在atm长度为 0。

于 2013-05-16T17:09:01.263 回答