我正在做套接字编程以进行医院指导。 我正在尝试读取这样的文本文件
1 Kavi card 0 0 0
2 Anparasanesan gene 0 0 0
3 Thilak card 0 0 0
4 Akilanesan immu 0 0 0
5 Aravinthanesan derm 0 0 0
6 Akalya derm 0 0 0
7 Vishvapriya derm 0 0 0
8 Kavinga immu 0 0 0
9 Anjalie andr 0 0 0
10 Tom andr 0 0 0
但是当我阅读该文件时,它的输出为:
1 Kavi cardgenecardimmudermdermdermimmuandrandr
2 Anparasanesan genecardimmudermdermdermimmuandrandr
3 Thilak cardimmudermdermdermimmuandrandr
4 Akilanesan immudermdermdermimmuandrandr
5 Aravinthanesan dermdermdermimmuandrandr
6 Akalya dermdermimmuandrandr
7 Vishvapriya dermimmuandrandr
8 Kavinga immuandrandr
9 Anjalie andrandr
10 Tom andr
这是我的代码段
char line[MAXCHAR];
int x = 0;
while (fgets(line, sizeof(line), fp)){
sscanf(line,"%d\t%s\t%s\t%d\t%d\t%d",&dno,&dname,&dspl,&ti1,&ti2,&ti3);
id[x]=dno;
strncpy(name[x], dname, 50);
strncpy(spl[x], dspl, 4);
times[x][0]=ti1;
times[x][1]=ti2;
times[x][2]=ti3;
x++;
}
int z=0;
for(z=0;z<10;z++)
{
snprintf(line, sizeof(line),"%d\t%s\t%s\n",id[z],name[z],spl[z]);
n = strlen(line);
Writen(sockfd,line,n);
}
答案 0 :(得分:2)
让我们看看其中一个问题。
邪恶的strncpy
代码将strncpy
与magic number 4一起使用。这不能确保spl[x]
是 string ,因为字符可能缺少最后一个 null字符。
strncpy(spl[x], dspl, 4); // Avoid code like this
后来的代码尝试使用"%s"
和spl[z]
打印 string 并得到“ cardgene ...”而不是预期的“ card”。如果spl[z]
不是字符串,则结果为未定义行为(UB)-可能发生任何事情。
// Alternative: could limit output with
snprintf(line, sizeof(line),"%.*s\n",(int) (sizeof spl[z]), spl[z]);
如何解决?
请勿使用sscanf(line,"%s",&dspl);
,因为它没有宽度限制,或者未知dspl
的大小与line
相同。我希望
char dspl[4+1];
sscanf(line,"%4s", dspl);
比起未经测试,使用strncpy()
更好地确保源字符串和目标数组足够。
char spl[X_N][4+1];
char dspl[sizeof spl[0]];
// strncpy(spl[x], dspl, 4);
strcpy(spl[x], dspl);
其他修复程序包括确保sscanf()
已按预期完成。一种简单的方法使用" %n"
来记录扫描偏移量(如果扫描偏移量太远了),然后寻找额外的垃圾。删除了不必要的"\t"
。
// Insure dname is at least 50+1, dspl is 4+1 or as big as the line
char dname[sizeof line];
char dspl[sizeof line];
// sscanf(line,"%d\t%s\t%s\t%d\t%d\t%d",&dno,&dname,&dspl,&ti1,&ti2,&ti3);
int n = 0;
sscanf(line,"%d%50s%4s%d%d%d %n",&dno,dname,dspl,&ti1,&ti2,&ti3, &n);
if (n==0 || line[n]) {
puts("Bad Input"); // Handle bad input in some fashion
exit(RETURN_FAILURE);
}