2013-06-21 4 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, чтобы скопировать первые десять символов любого маркера, но когда токен имеет более десяти символов, это означает, что строка не будет равна нулю -завершённый. Передача таких строк в printf("%s", ...) - это неопределенное поведение.

Чтобы устранить эту проблему, вы должны либо принудительно завершить установку, установив ptr->student.lname[9] = '\0', если хотите остаться с фиксированной длиной строки, либо использовать strdup, чтобы разрешить строки переменной длины.

И, наконец, существует альтернативная альтернатива использованию strtok - вы можете использовать strtok_r.

+0

Используйте strncpy() вместо memcpy() – John3136

+0

Благодарю вас, ребята. Я увеличил массив для имен на один, чтобы добавить конечный символ. – user1362058