2013-06-21 42 views
1

我发送的格式如下,从一个程序到另一个:number lastname firstname middlei ID GPA使用memcopy的奇怪结果

接收程序看到正确的字符串,并将该字符串存储到缓冲区中。该字符串被标记并且在switch语句中使用的数字。下面显示了相应的案例代码。

tok = strtok(arg, " "); 
printf("the first token is %s\n", tok); 
memcpy(ptr->student.lname, tok, 10); 
tok = strtok(NULL, " "); 
memcpy(ptr->student.fname, tok, 10); 
tok = strtok(NULL, " "); 
ptr->student.initial = *tok; 
tok = strtok(NULL, " "); 
sscanf(tok, "%lu", &ptr->student.SID); 
tok = strtok(NULL, " "); 
sscanf(tok, "%f", &ptr->student.GPA); 
// few more pointer and location initializations... 
printf("lu %s %s %c %f\n", ptr->student.SID, ptr->student.lname, 
    ptr->student.fname, ptr->student.initial, ptr->student.GPA); 

输入字符串是:5 lastnamereallylong,firstnamereallylong,X,1234,4.0

其中前程序缩短到:5 lastnamere firstnamer X 1234 4.0

第二个程序的输出如下:

the first tok is lastnamere 
1234 lastnamereXfirstnamer firstnamer X 4.000000 

是否有人可以帮助我这里发生了什么?我可以理解不正确使用memcopy,但我不认为这会改变原始信息的顺序。

回答

2

这里发生了什么是未定义的行为:您正在告诉memcpy要复制任何令牌的前10个字符,但是当令牌长度超过10个字符时,表示该字符串不会为空封端的。传递这样的字符串到printf("%s", ...)是未定义的行为。

要解决此问题,您应该通过设置ptr->student.lname[9] = '\0'来强制终止,如果您希望保留固定长度的字符串,或者使用strdup来允许可变长度的字符串。

最后,使用strtok有一个线程安全的替代方案 - 您可以使用strtok_r

+0

使用strncpy()而不是memcpy() – John3136

+0

谢谢你们。我把数组的名字加长了一个,所以我可以添加终止字符。 – user1362058