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
提取。在阅读 firstname
和 lastname
之前 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
我刚开始学习 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
提取。在阅读 firstname
和 lastname
之前 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