1

我正在将格式如下的字符串从一个程序发送到另一个程序:number lastname firstname middlei ID GPA.

接收程序看到正确的字符串,并将该字符串存储到缓冲区中。字符串被标记化,并且数字在 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正确,但我认为这不会改变原始信息的顺序。

4

1 回答 1

2

这里发生的是未定义的行为:您memcpy要复制令牌的前十个字符,但是当令牌的长度超过十个字符时,这意味着字符串不会以空值结尾。将此类字符串传递给printf("%s", ...)未定义的行为。

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

最后,还有一个线程安全的替代方案strtok——你可以使用strtok_r.

于 2013-06-21T01:02:54.007 回答