2013-06-21 3 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 첫 번째 프로그램으로 단축

:

the first tok is lastnamere 
1234 lastnamereXfirstnamer firstnamer X 4.000000 

누군가가 나에게 그림을 도와 주시겠습니까 다음과 같이 5 lastnamere firstnamer X 1234 4.0

두 번째 프로그램의 출력은 여기서 무슨 일이 일어나고있는거야? 내가 정확히 memcopy을 사용하지 않는 것을 이해할 수는 있었지만 원래 정보의 순서가 바뀌지는 않을 것이라고 생각했습니다.

답변

2

여기에 정의되지 않은 동작이 있습니다 : memcpy에 토큰이 무엇이든간에 처음 10자를 복사하라고 말하고 있지만 토큰 길이가 10자를 넘으면 문자열이 null이 아님을 의미합니다 - 끝났다. 이러한 문자열을 printf("%s", ...)으로 전달하는 것은 정의되지 않은 동작입니다.

이 문제를 해결하려면 고정 길이 문자열을 유지하려는 경우 ptr->student.lname[9] = '\0'을 설정하여 강제 종료하거나 strdup을 사용하여 가변 길이 문자열을 허용해야합니다.

마지막으로 strtok을 사용하는 스레드로부터 안전한 대안이 있습니다. strtok_r을 사용할 수 있습니다.

+0

memcpy() 대신 strncpy()를 사용하십시오. – John3136

+0

여러분 께 감사드립니다. 배열 이름을 하나씩 길어서 종결 문자를 추가 할 수있었습니다. – user1362058