C 中的 Scanf 文本溢出

Scanf text overflow in C

我刚开始学习 C。这是我正在试验的一些示例代码。它只是为了获得一个用户名。如果我为第一个需要字符的答案输入一个字符串,第一个字母将保存到 middleInitial,但随后的 scanf 将读取并保存被忽略的字符串的其余部分。这意味着输入 "Jacob" 然后输入 "Pat Smith" 将导致输出 "Your name is 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);

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

根据代码:

scanf(" %c", &middleInitial);

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

例如:您输入了 "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);

我对在 C 中使用字符串 (char*) 有一些建议。 首先,正如 sumithdev 所说,在输入任何信息之前使用 fflush(stdin) 清理输入流缓冲区。 其次,尽量使用统一的风格来存储所有的字符串数据。例如,您的 middleInitial 也可以定义为 char 数组,但长度可以为 2(middleInitial[0] 将是一个字符,而 middleInitial[1] 将是一个‘\0’)。 最后的建议——尝试使用健壮的函数来防止内存冲突和数据丢失。 对于代码:

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

我看到潜在的问题:

a) 一般情况下,用户的名字或姓氏可以超过一个单词,但 %s 在 scanf 中读取字符直到 space;

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 %s\n", 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