扫描 C 语言中的文本溢出



我刚刚开始学习C。这是我正在试验的一些示例代码。它只是为了获取用户名。如果我为第一个需要字符的答案输入一个字符串,第一个字母将保存到middleInitial,但随后的扫描会读取并保存字符串的其余部分,而不是忽略其余部分。这意味着输入"Jacob"然后输入"Pat Smith"将导致输出"你的名字是acob J Pat"为什么会这样?

char middleInitial; 
printf("What is your middle initial?");
scanf(" %c", &middleInitial);
char firstName[30], lastName[30];
printf("What is your name? ");
scanf(" %s %s", firstName, lastName);
printf("Your name is %s %c %s", firstName, middleInitial, lastName);

我对 C 中的字符串 (char*) 用法有一些建议。首先,正如 sumithdev 所说,在输入任何信息之前,使用 fflush(stdin) 清理输入流缓冲区。其次,尝试使用统一的样式来存储所有字符串数据。例如,你的 middleInitial 也可以定义为 char 数组,但长度可能为 2(middleInitial[0] 将是一个字符,middleInitial[1] 将是一个 '\0')。最后一个建议 - 尝试使用强大的函数来防止内存违规和数据丢失。对于代码:

scanf(" %s %s", firstName, lastName);

我看到潜在的问题:

a)一般用户的名字或姓氏可以有多个单词,但一个%s在scanf中读取字符直到空格;

b) 名字或姓氏可以大于 29 个字母和 30 个数组元素不足以存储输入,这将导致运行时问题;

c)当您想更改输入名称不同部分的顺序或添加一些检查时,您将在代码中进行大量硬修改。

请考虑以下版本:

char middleInitial[2]; 
char firstName[30], lastName[30];
// asking for middle part
printf("What is your middle initial? ");
fflush(stdin); // delet all previous inputs
scanf("%1s", middleInitial); // wait new inputs and take only 1 character
// asking for first part
printf("What is your first name? ");
fflush(stdin);
scanf("%29s", firstName); // wait new inputs and take not more than 29 characters
// asking for last part
printf("What is your last name? ");
fflush(stdin);
scanf("%29s", lastName); // wait new inputs and take up to 29 characters
// output result
printf("Your name is %s %s %sn", firstName, middleInitial, lastName);

并且还尝试使用 fgets 而不是 scanf。例如:

fflush(stdin);
fgets(firstName, 30, stdin); // this allows input of strings with spaces
// but adds 'new line' (n) in the end of string

根据代码:

scanf(" %c", &middleInitial);

middleInitial获取输入的唯一第一个字符。

例如:yout 输入"Jacob",然后输入"John Smith":

middleInitial = J
firstName = acob
lastName = John

您应该尝试:

char middleInitial;
char str[30];
printf("What is your middle name?");
scanf(" %c", &middleInitial); // get "J"
scanf(" %s", &str);  // get "acob"
char firstName[30], lastName[30];
printf("What is your name? ");
scanf(" %s %s", firstName, lastName);
printf("Your name is %s %c %s", firstName, middleInitial, lastName);

原因是第一个scanf未获取的剩余字符保留在STDIN缓冲区中,然后由后续scanf影响。 在阅读firstnamelastname之前flush STDIN。由于fflush不是删除 STDIN 缓冲区中不需要的字符的可靠方法,因此此处介绍了手动操作方法。

最新更新