简体   繁体   English

C语言中的scanf文本溢出

[英]Scanf text overflow in C

I have just started learning C. Here is some sample code I was experimenting with. 我刚刚开始学习C。这是我正在尝试的一些示例代码。 It is just meant to get a users name. 它只是为了获得用户名。 If I enter a string for the first answer which is expecting a char, the first letter is saved to middleInitial, but instead of the rest of the string being ignored is read and saved by the subsequent scanf. 如果我为期望答案的第一个答案输入一个字符串,则第一个字母将保存到middleInitial中,但是随后的scanf会读取并保存该字符串的其余部分,而不是被忽略。 This means that entering "Jacob" and then "Pat Smith" would result in the output of "Your name is acob J Pat" Why is this happening? 这意味着输入“ 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);

The reason is the remaining characters which are not fetched by the first scanf stay in the STDIN buffer which are then fectehed by the subsequent scanf . 原因是未被​​第一个scanf取回的其余字符留在STDIN缓冲区中,然后由后续的scanf flush STDIN before you read firstname and lastname . 在读取firstnamelastname之前先flush STDIN。 Since fflush is not a reliable way of deleting unwanted characters in the STDIN buffer a manual way of doing it is explained here . 由于fflush并不是删除STDIN缓冲区中不需要字符的可靠方法,因此在这里说明一种手动方法。

According to the code: 根据代码:

scanf(" %c", &middleInitial);

middleInitial get the only first character of your input. middleInitial获取输入的唯一第一个字符。

For example: yout inputed "Jacob" and then "John Smith": 例如:您输入了“ Jacob”,然后输入了“ John Smith”:

middleInitial = J
firstName = acob
lastName = John

You should try: 你应该试试:

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);

I have some advices for string (char*) usage in C. First, as sumithdev said, use fflush(stdin) to clean input stream buffer before input any piece of information. 我对C中的字符串(char *)用法有一些建议。首先,如sumithdev所说,在输入任何信息之前,请使用fflush(stdin)清理输入流缓冲区。 Second, try to use uniform style for storing all string data. 其次,尝试使用统一的样式来存储所有字符串数据。 For example, your middleInitial also can be defined as array of char but may me length of 2 (middleInitial[0] will be a character, and middleInitial[1] will be a '\\0'). 例如,您的middleInitial也可以定义为char数组,但长度可以为2(middleInitial [0]将是一个字符,middleInitial [1]将是一个'\\ 0')。 And the last advice – try to use robust functions to prevent memory violation and data lost. 最后一条建议–尝试使用功能强大的功能来防止内存冲突和数据丢失。 For code: 对于代码:

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

I see potential problems: 我看到了潜在的问题:

a) in general first name or last name of user can be more than one word, but one %s in scanf read characters until space; a)通常,用户的名字或姓氏可以超过一个单词,但是scanf中一个%s会读取字符直到空格;

b) first name or last name can be greater than 29 letters and 30 elements of array would be not enough to store input, this will lead to runtime problems; b)名字或姓氏可以大于29个字母,并且数组的30个元素不足以存储输入,这将导致运行时问题;

c) when you want to change the order for input different parts of name or add some check, you will have lots of hard modification in your code. c)当您想更改名称的不同部分的输入顺序或添加一些检查时,您的代码将进行大量的修改。

Consider the following version: 考虑以下版本:

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);

And also try to use fgets instead of scanf. 并且也尝试使用fgets代替scanf。 For example: 例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM