我在使用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);
}
答案 0 :(得分:1)
字符串begin
不足以容纳sscanf
将读取和其\0
终止符的四个字符。如果将\0
写入atm
(取决于字符串在内存中的位置),则会修改atm
。从sscanf manpage开始,关于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。