I've been creating a program requesting the user to input a char value, but if they enter more than one character it will move onto the next function and break the program. I've added in the second method which gets run when multiple inputs are entered.
-
Make the character buffer larger; you don't need to use it all. Memory's cheap. An array of, say, 100 characters is nothing. – Carcigenicate Feb 18 '17 at 18:03
-
I've tried this but it then returns an infinite loop of a validation check from a different function. – Luke Feb 18 '17 at 18:05
-
why use a string when you want a char? – Support Ukraine Feb 18 '17 at 18:07
-
what is the exact input that makes it fail? And what exactly do you mean by `break the program`? – Support Ukraine Feb 18 '17 at 18:08
-
I've added the second method above, when I type multiple charecters for example "yg" rather than just "y" it returns an infinite loop of please try again, enter a value between 1 and 10: – Luke Feb 18 '17 at 18:12
-
1@Luke : Yiur problem is not one of limiting teh number iof characters written to `cInput`; `%1s` does that already. Your problem is one of leaving unprocessed characters in the input buffer. – Clifford Feb 18 '17 at 18:15
-
How exactly would I resolve that? – Luke Feb 18 '17 at 18:16
-
empty the buffer after scanf - see http://stackoverflow.com/questions/7898215/how-to-clear-input-buffer-in-c – Support Ukraine Feb 18 '17 at 18:17
-
try Change `scanf("%1s", &cInput);` to `scanf("%1s%*[^\n]", cInput);` – BLUEPIXY Feb 18 '17 at 18:19
-
@Luke : I'm typing an answer - be patient! – Clifford Feb 18 '17 at 18:19
-
@4386427 this now works a lot better, but for example if the data inputted is "yvnkjdsnjksfd" or "nfdnsezf" it will still go ahead with the loop as the first letters are "y" or "n", how can I get around this? – Luke Feb 18 '17 at 18:22
-
@Luke : You have to fix the buffered character issue for the `getValue()` function too. scanf format specifiers can get somewhat arcane, which is why I prefer the solution suggested in my answer. – Clifford Feb 18 '17 at 18:42
-
Declaring `nValue` static appears to serve no purpose. – Clifford Feb 18 '17 at 18:44
-
I've flushed the buffer a different way but for example if the data inputted is "yvnkjdsnjksfd" or "nfdnsezf" it will still go ahead with the loop as the first letters are "y" or "n", how can I get around this? – Luke Feb 18 '17 at 18:54
-
@Luke : Arguably that is OK - if it is not desirable, then you will have to explicitly check for excessive input. That is check for `"y\n"` rather then just `y`. I'll update my answer. – Clifford Feb 18 '17 at 19:13
-
@Clifford let me know when done so, thanks – Luke Feb 18 '17 at 19:22
-
@Luke : SO tells you when an answer has been edited. – Clifford Feb 18 '17 at 19:31
-
Hello, I am new to C and don't understand your code too well. I was wondering if there was a way of checking for a new line in the if( toupper(cInput) == 'Y' ) { nAnswer = 1; } – Luke Feb 18 '17 at 19:41
-
@Luke : Since you are referring to the code in *my answer* you should post the comment in the comments to *my answer*. If you address me in comments to *your question* you need to reference me by `@clifford` otherwise I will not get a notification of your comment. – Clifford Feb 19 '17 at 11:19
-
@Luke : Anyhow when stdin is from the standard console (default), `scanf()` does not return until there is a newline buffered, so it is implicit that one is present. If you checked in the character test you would have to input two characters and test both, and would still have to flush the buffer (conditionally) not to mention adding the check to the `'N'` test as well; so I see little benefit is doing it that way. – Clifford Feb 19 '17 at 11:27
-
@Luke : In answer to your comment I have updated the answer to include explanatory comments in the code fragment for reading a single character and added an explanatory paragraph. Understanding my code is probably a better solution to your lack of comprehension and experience than re-writing the code the way you would have done it - that way may not advance your understanding or even result in working code. – Clifford Feb 19 '17 at 11:45
-
Note that comments such as `// Variable Declarations` and `// Code starts here ` serve little purpose. For a start - we can see that they are variable declarations, but also it encourages the practice of placing all variable declarations in one block, which is ill-advised and unnecessary. There is a common misconception in C that all declarations must appear at the start of a function, and since C99 they need not even appear they the start of a statement block - see for example the declaration of `converted` in my `getValue()` implementation. – Clifford Feb 19 '17 at 11:50
-
this statement: `scanf("%1s", &cInput);` will not work as expected. This is because referencing just an array name result in the address of the array, and the statement is asking for the address of the address of the array. Suggest removing the `&` – user3629249 Feb 19 '17 at 17:40
-
for ease of readability and understanding, 1) separate code blocks (for, if, else, while, do...while, switch, case, default) via a single blank line. 2) separate functions via 2 or 3 blank lines (be consistent) – user3629249 Feb 19 '17 at 17:42
-
regarding this kind of line: `if(cInput[0] == 'Y' || cInput[0] == 'y')` suggest `#include
` then writing: `if( toupper( cInput[0] ) == 'Y' ) – user3629249 Feb 19 '17 at 17:45
2 Answers
Your problem is not one of limiting the number of characters written to cInput
; the format specifier %1s
does that already. Your problem is one of leaving unprocessed characters in the input buffer. You need to remove all characters from the buffer if subsequent input will not handle them. For example if you leave a alphabetic character in then buffer but later read with %d
, the function will return immediately (because there is implicitly a newline also buffered), but the character will remain buffered because it is not a decimal. This will continue indefinitely if you never clear the buffer.
For a single character, you can check the character is not a newline, and then repeatedly get characters until a newline is found, as follows:
scanf("%c", &cInput ) ;
while( cInout != '\n' && getchar() != '\n' ) { } // flush buffered line
If you want to be sure the user only enters a single character, then you could modify the above thus:
scanf("%c", &cInput ) ; // Get a single character
if( cInput != '\n' && // If the input is not "empty",
getchar() != '\n' ) // but the first character entered was not
// immediately followed by a newline...
{
// Flush to the end of the entered line
while( getchar() != '\n' ) { }
// Invalidate the input to force retry
cInput = 0 ;
}
At least one character will be buffered - a newline at least. A valid answer will have two characters one in cInput
and a newline. The if(...)
condition above reads the second character if there is one (using short-circuit evaluation of cInput
), and checks that it is the end of the input (newline). If it is not, it reads all buffered characters then invalidates cInput
(in case say "No-way\n"
were entered for example, so that cinput
contained 'N'
.
For numeric input, you simply read characters until the newline is found:
scanf("%d", &nValue);
while( getchar() != '\n' ) { } // flush buffered line
If trailing non-numeric characters should render the entire input invalid, you need to check that the following character is a newline.
int converted = scanf("%d", &nValue);
if( converted == 0 || getchar() != '\n' )
{
valid_input = false ;
while( getchar() != '\n' ) { } // flush buffered line
}
Note that there are other possible solutions. This is my preferred solution.
When applied to your functions (with other simplifications):
int intAskUser(void)
{
char cInput = 0 ;
while( cInput != 'N' && cInput != 'Y' )
{
printf("Do you want to enter a value? Y or N\n");
scanf("%c", &cInput ) ;
if( cInput != '\n' && getchar() != '\n' )
{
while( getchar() != '\n' ) { } // flush buffered line
cInput = 0 ;
}
else
{
cInput = toupper(cInput) ;
}
}
// Return answer code 0 to 1
return (cInput == 'N') ? 0 : 1 ;
}
int getValue(int nLower, int nUpper)
{
assert( nLower < nUpper ) ; // precondition check
int nValue = 0 ;
bool valid_input = false ;
while( !valid_input )
{
printf("Enter a value between %d and %d: ", nLower, nUpper ) ;
int converted = scanf("%d", &nValue);
if( converted == 0 || getchar() != '\n' )
{
valid_input = false ;
while( getchar() != '\n' ) { } // flush buffered line
}
valid_input = nValue >= nLower &&
nValue <= nUpper ;
if( !valid_input )
{
printf( "Please try again. " );
}
}
printf("Value: %d", nValue);
return nValue;
}
Note that toupper()
requires ctype.h
to be included, and the type bool
requires stdbool.h
.

- 88,407
- 13
- 85
- 165
If I understand your question correctly, you want the function to return if the user input is any of
y
followed by newlineY
followed by newlinen
followed by newlineN
followed by newline
In all other cases you want to stay in the function and get new user input (e.g. nYnhhh
followed by newline shall not return).
To my knowledge there is no standard function that can achieve that, so you have to write your own code.
When doing that there are two things to remember:
- You must read at least 2 chars in order to check for "too long" input strings.
- After unsuccessful inputs you need to empty the input buffer before reading new input. An unsuccessful input is one that doesn't have
\n
as last char.
Finally I recommend you use fgets()
instead of scanf()
as it is much easier to use. Don't use gets()
though - it's dangerously vulnerable to buffer overrun.
Your code could look like:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int AskUser(void)
{
char input[3] = {'\0'}; // Make room for a string of 2 chars + terminating null
int c;
int len;
printf("Do you want to enter a value? Y or N\n");
do
{
if (!fgets(input, 3, stdin))
{
printf("Input error");
exit(1);
}
len = strlen(input);
if (len)
{
if (input[len-1] != '\n') // Check whether last char is a newline
{
// It isn't so empty the input buffer
while ((c = getchar()) != '\n' && c != EOF) { }
}
}
if (len == 2) // Check for exactly 2 chars in input
{
if(toupper(input[0]) == 'Y' && input[1] == '\n')
{
return 1;
}
if(toupper(input[0]) == 'N' && input[1] == '\n')
{
return 0;
}
}
printf("Please enter a valid input, Y or N: \n");
} while(1);
}
int main(void) {
printf("Answer is %d\n", AskUser());
return 0;
}

- 27,591
- 48
- 66
- 103

- 42,271
- 4
- 38
- 63