【发布时间】:2014-07-14 14:08:04
【问题描述】:
我有以下结构和填充它的代码:
typedef struct {
char name[CONTACT_NAME_SIZE];
char surname[CONTACT_SURNAME_SIZE];
char address[CONTACT_ADDRESS_SIZE];
char phoneNumber[CONTACT_PHONENUMBER_SIZE];
} Contact;
...
char buffer[1024];
char phonebookItem[50];
printf("Name (max %d characters): ", CONTACT_NAME_SIZE);
fgets(buffer, sizeof(buffer), stdin);
memcpy(phonebookItem, buffer, sizeof(phonebookContacts[id].name));
strcpy(phonebookContacts[id].name, phonebookItem);
printf("Surname (max %d characters): ", CONTACT_SURNAME_SIZE);
fgets(buffer, sizeof(buffer), stdin);
memcpy(phonebookItem, buffer, sizeof(phonebookContacts[id].surname));
strcpy(phonebookContacts[id].surname, phonebookItem);
printf("Address (max %d characters): ", CONTACT_ADDRESS_SIZE);
fgets(buffer, sizeof(buffer), stdin);
memcpy(phonebookItem, buffer, sizeof(phonebookContacts[id].address));
strcpy(phonebookContacts[id].address, phonebookItem);
printf("Phone number (max %d characters): ", CONTACT_PHONENUMBER_SIZE);
fgets(buffer, sizeof(buffer), stdin);
memcpy(phonebookItem, buffer, sizeof(phonebookContacts[id].name));
strcpy(phonebookContacts[id].phoneNumber, phonebookItem);
问题是当我为第一个字段输入数据时,一切正常。但是当我为下一个字段输入数据时,我输入的所有内容(第一个和第二个输入)都会写入第一个字段,依此类推...
例子:
Name (max 10 characters): 123456789*123456789
phonebookContacts[id].name = 123456789* -> OK
Surname (max 15 characters): 123456789*123456789*
phonebookContacts[id].name = 123456789*123456789*12345
phonebookContacts[id].surname = 123456789*12345
为什么会被覆盖?
【问题讨论】:
-
如果用户输入太多输入,像这样使用
memcpy()将导致未定义的行为,因为您的字符串将未终止,但除此之外,它不会按照您的要求执行。您的代码中还有一些其他错误,可能从糟糕的内存管理到试图错误地打印这些东西。没有足够的信息进行诊断。 -
你为什么还要使用 memcpy?
-
我使用 memcpy 是因为我尝试了几种方法来做我想做的事,只有 memcpy 有效(它“只是”覆盖了所有内容)。我需要将字符串从缓冲区复制到结构字段,但我必须管理对太长字符串的保护。
-
...并且您“管理对太长字符串的保护”是错误的。如果没有终止,
memcpy不会终止您的字符串。确保在覆盖后在每个覆盖缓冲区的最后一个位置插入一个零字节(ASCII NUL 字符),例如surname[CONTACT_SURNAME_SIZE - 1] = 0; -
您总是可以采取激进的步骤,实际检查输入 before 的长度以尝试复制它,如果太长则简单地拒绝它。这可能比默默地截断输入更好(如果你拒绝了一半的地址,你将如何成功地给某人发邮件?)即使用户故意选择不遵守说明。