How to only allow specific Input in C - c

My Code:
#include<stdio.h>
char checkInput0(void);
int main() {
char output;
output = checkInput0();
printf("The output is %c", output);
}
char checkInput0(void){
char option0 = '\0',check0;
char c;
do{
printf("Please enter your choice: ");
if(scanf("%c %c",option0, &c) != 'A' || c != 'B' ){
while((check0 = getchar()) != 0 && check0 != '\n' && check0 != EOF);
printf("[ERR] Please enter A or B.\n");
}else{
break;
}
}while(1);
return option0;
}
I would like to only allow the user to input only "A" or "B" and if anything else would be entered I would like to reprompt the user with the following message: [ERR] Please enter A or B.\n
I have written a funktion which worked with numbers but I can't get the one above (checkInput0) to work, what have I done wrong

scanf does not return c, it returns the number of variables successfully set. Comparing that to 'A' is pretty pointless.
Change your scanf call to scanf("%c %c", &option0, &c): currently the behaviour is undefined: the variable arguments need to be pointer types.
x != 'A' || x != 'B' is 1 for any value of x.
Consider moving scanf outside the if conditional: checking the return value of scanf explicitly. On the third point, did you want &&?
Also be careful with ace code that writes c on one side of an operator, and reads it on the other. It's fine in this instance since || is a sequencing point, but you are quite close to undefined behaviour here.

Related

User input with scanf using while loop

I'm having a problem with multiple characters while using a while loop. I'm writing a code that would direct the user to a new function based on the input of either "y" or "n". When I scanf for one character it works fine; however, when the user types in multiple characters the while loop repeats.
#include <stdio.h>
int main()
{
char x;
printf("type in letter n or y\n");
scanf("%c", &x);
while (x!= 'Y' && x!='N' && x!= 'n' && x!='y')
{
printf("Invalid, please type Y/N to continue: \n");
scanf(" %c", &x);
}
if (x== 'Y' || x == 'y')
{
printf("y works");
}
if (x =='N' || x =='n')
{
printf("n works");
}
}
For example, if I type in hoyp, it would say "Invalid, ..." 2 times and then the "y works" would be written on the third line. How can the code be changed so that the invalid would only be said once, and the user must input again to allow the program to continue?
This is how scanf behaves. It keeps reading in all the characters you've entered. You can accept a string as input first using fgets and extract and check only its first character. fgets allows you to specify the exact number of characters to be read. I have first declared a char array of size 4096. This will work when the input is up to 4095 characters. You can adjust the size as per your needs.
#include <stdio.h>
int main()
{
char x, buffer[4096];
printf("type in letter n or y\n");
fgets(buffer, 4096, stdin);
x = buffer[0];
while (x!= 'Y' && x!='N' && x!= 'n' && x!='y')
{
printf("Invalid, please type Y/N to continue: \n");
fgets(buffer, 4096, stdin);
x = buffer[0];
}
if (x== 'Y' || x == 'y')
{
printf("y works");
}
if (x =='N' || x =='n')
{
printf("n works");
}
}
Here is my approach to the problem:
I have used fgets() instead of scanf(). See why
here.
I have used the suggestion by users jamesdlin and M.M in this question to solve the repeated printing issue when the input is more than one character or if the input is empty. I encourage you to read the whole thread to know more about this issue.
(Optional) Used some extra headers for better code readability in the loop conditions. I think the fgets() could be used in the condition of the while() but I got used to the pattern I have written below.
Edit: added a condition to reject inputs with length > 1. Previously, inputs that starts with 'y' or 'n' will be accepted (and are interpreted as 'y' or 'n' respectively) regardless of their length.
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
void clearInput();
int main()
{
// allocate space for 'Y' or 'N' + '\n' + the terminator '\0'
// only single inputs will be accepted
char _inputbuff[3];
char choice;
bool isValidInput = false;
while(!isValidInput) {
printf("Please enter your input[y/n]: ");
// use fgets() instead of scanf
// this only stores the first 2 characters of the input
fgets(_inputbuff, sizeof(_inputbuff), stdin);
// don't accept empty input to prevent hanging input
if(_inputbuff[0] == '\n') {
printf("Empty input\n");
// go back to the top of the loop
continue;
}
// input is non-empty
// if the allocated space for the newline does not
// contain '\n', reject the input
if(_inputbuff[1] != '\n') {
printf("Input is more than one char.\n");
clearInput();
continue;
}
choice = _inputbuff[0];
// printf("The input is %c\n", choice);
// convert the input to uppercase for a 'cleaner' code
// during input validation
choice = toupper(choice);
// the input is not 'Y' or 'N'
if(choice != 'Y' && choice != 'N') {
printf("Please choose from Y or N only.\n");
// go back to the top of the loop
continue;
}
// the input is 'Y' or 'N', terminate the loop
isValidInput = true;
}
// conditions for 'Y' or 'N'
if(choice == 'Y') {
printf("The input is Yes.\n");
return 0;
}
if(choice == 'N') {
printf("The input is No.\n");
return 0;
}
}
void clearInput() {
int _clear;
// clear input stream to prevent repeated printing of invalid inputs
while ((_clear = getchar()) != '\n' && _clear != EOF ) { }
}
(This is my first time answering a question and it has been a while since I have used C so feel free to give suggestions/corrections regarding my answer. Thanks!)

getchar not working properly after using scanf in C

I am writing this code:
int b;
char c;
scanf("%d", &b);
while((c = getchar()) != EOF) {
if(c >= 9 || c < 0) {
printf("Invalid number!\n");
exit(0);
}
}
When I assign b, automatically c is equal to b.
For example, if my input for b is 10, it automatically goes into the if-statement and exits the code.
Does anyone know why?
Finding problems and solving them
You have plenty of errors in the code that are listed below.
The getchar(3) says:
getchar() is equivalent to getc(stdin).
The prototype of getc() is:
int getc(FILE *stream);
That is, the getchar() returns an integer (from unsigned char cast). Thus, we need to change the type from char to int to accept its return value correctly.
Note that EOF is not a valid unsigned char. It expands to signed int -1.
Never ignore the return value of the scanf(3). It returns the number of correctly passed arguments. In this case, to make the code reliable, we should put:
if (scanf("%d", &b) != 1) {
fprintf(stderr, "Value must be an integer.\n");
return EXIT_FAILURE;
}
There is a semantic error in the condition:
if (c >= 9 || c < 0)
^^____________ logically, 9 is a valid one digit number
so removing '=' from here makes more sense
One notable thing is that the condition and the type of the comparator – both should be changed. See the next step.
The fixed loop should look like:
while ((c = getchar()) != EOF) {
if (c == '\n') // Since c = getchar() can be '\n' too
continue; // so, better ignore
if (c >= '0' && c <= '9') // Change the loop like this
printf("Valid number %d %c.\n", c, c);
else
printf("Invalid number.\n");
}
Sample test case output
1
10 // --- Note: 10 are two chars for two getchars
Valid number 49 1.
Valid number 48 0.
3
Valid number 51 3.
9
Valid number 57 9.
-
Invalid number.
a
Invalid number.
<
Invalid number.
.
Invalid number.

Read single key input from keyboard and evaluate it

I want to read one keyboard input - and depending whether it is valid or not proceed with the operation or do something else. If it's invalid the input should be repeated.
At this point I'm aware already scanf is not the tool of my desire, but that here would be the default-code (if scanf would work as intended):
char val;
int incorrect = 0;
printf("Do you wish to proceed?: <Yy/Nn>");
do
{
incorrect = 0;
scanf(" %c", &val); //Changed to " %c" alread from "%c"
//getchar(); //Tried already, doesn't solve the problem
if (!(val == 'y' || val == 'Y' || val == 'n' || val == 'N'))
{
printf("Invalide Input!\n");
incorrect = 1;
}
} while (incorrect);
The problem is if instead of a one-character input there is a longer input the error-message will be repeated by the number of the characters.
Also, if instead of for instance 'n' the input is "nasdlfjas" it is still considered as a valid input.
Changing the scanf to val = getchar(); if (kind != EOF) (with or without the EOF-part) as suggested here doesn't change the behavior. But the Error-message is added right after the question.
The "GetStuff()" from this solution suffers from the same problem. The error-output is multiple and one single correct character in the whole input determines the result.
This variant however is doing better, but evaluates the result on the first character of the entire string.
Other variants which include a while((c = getchar()) != EOF); which is the preferred variant to use getchar have similar issues of going through the loop-body before the input of the character (and therefore printing the error).
I decided to read a string instead of a character and then just evaluate the result by dealing with the string itself. Something like:
do{
int c, line_length = 0;
int i = 0;
while ((c = getchar()) != EOF && c != '\n' && line_length < MAX_LINE - 1)
{
sentence[i++] = c;
line_length++;
}
// String Stuff
if (!(val == 'y' || val == 'Y' || val == 'n' || val == 'N'))
{
printf("Invalide Input!\n");
incorrect = 1;
}
} while (incorrect);
But again there will "Invalide Input!" be printed before entering anything.
What exactly would be the proper way to evaluate just the input of a single character?

Scanning character caused problem in devC

So my code does the following:
Ask what's the option
If option is 1: Scan some numbers
If option is 2: Print those numbers
After each option, ask if user wanted to continue choosing (Y/N)
This is my main code
while(yesnocheck==1)
{
printf("What's your option?: ");
scanf("%d",&b);
switch(b){
case 1:
printf("How many numbers?: ");
scanf(" %d",&n);
a=(struct sv*)malloc(n*sizeof(struct sv));
for(int i=0;i<n;i++)
scanf("%d",&((a+i)->num));
break;
case 2:
for(int i=0;i<n;i++)
printf("%d\n",(a+i)->num);
break;
}
yesnocheck==yesnochecker();
}
And this is the yesnochecker function:
int yesnochecker()
{
char yesorno;
printf("Do you want to continue? (Y/N)");
while(scanf("%s",&yesorno))
{
if(yesorno=='Y')
return 1;
if(yesorno='N')
return 0;
printf("*Wrong input. Please reenter (Y/N): ");
}
}
So on dev C++, my code won't run correctly. After it's done option 1, when I enter "Y" then choose option 2, case 2 will display some weird numbers. However it works well on online C compilers.
And then, when I change the char yesorno in yesnochecker() function to char yesorno[2] and treat it as a string, the code does work.
Can someone shed some light?
It is a bad idea to read a char c with scanf("%s", &c);. "%s" requires a buffer to store a string. The only string which fits into a char is an empty string (consisting only of a terminator '\0' – not very useful). Every string with 1 character requires 2 chars of storage – 1 for the character, 1 for the terminator ('\0'). Providing a char for storage is Undefined Behavior.
So, the first hint was to use the proper formatter instead – "%c".
This is better as it removes the Undefined Behavior. However, it doesn't solve another problem as the following sample shows:
#include <stdio.h>
int cont()
{
char c; do {
printf("Continue (y/n): ");
scanf("%c", &c);
printf("Input %c\n", c);
} while (c != 'y' && c != 'n');
return c == 'y';
}
int main()
{
int i = 0;
do {
printf("Loop iteration %d.\n", ++i);
} while (cont());
/* done */
return 0;
}
Output:
Loop iteration 1.
Continue (y/n): y↵
Input 'y'
Loop iteration 2.
Continue (y/n):
Input '
'
Continue (y/n): n↵
Input 'n'
Live Demo on ideone
WTH?
The scanf("%c") consumes one character from input. The other character (inserted for the ENTER key) stays in input buffer until next call of any input function.
Too bad, without ENTER it is hard to confirm input on console.
A possible solution is to read characters until the ENTER key is received (or input fails for any reasons). (And, btw., getc() or fgetc() can be used as well to read a single character.):
#include <stdio.h>
int cont()
{
int c;
do {
int d;
printf("Continue (y/n): ");
if ((c = fgetc(stdin)) < 0) {
fprintf(stderr, "Input failed!\n"); return 0;
}
printf("Input '%c'\n", c);
for (d = c; d != '\n';) {
if ((d = fgetc(stdin)) < 0) {
fprintf(stderr, "Input failed!\n"); return 0;
}
}
} while (c != 'y' && c != 'n');
return c == 'y';
}
int main()
{
int i = 0;
do {
printf("Loop iteration %d.\n", ++i);
} while (cont());
/* done */
return 0;
}
Output:
Loop iteration 1.
Continue (y/n): y↵
Input 'y'
Loop iteration 2.
Continue (y/n): Hello↵
Input 'H'
Continue (y/n): n↵
Input 'n'
Live Demo on ideone
Please, note, that I changed the type for the read character to int. This is because getc()/fgetc() return an int which is capable to store any of the 256 possible char values as well as -1 which is returned in case of failing.
However, it isn't any problem to compare an int with a character constant (e.g. 'y'). In C, the type of character constants is just int (SO: Type of character constant).

Working of scanf and checking if input is int

I wanted to check whether input given is integer input or not. I did not wanted to store input in a string. After seeing several questions on stackoverflow and by hit and trial, I have created following code
while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
printf("Please enter an integer only : ");
if(a == '\n')
scanf("%c",&a);
else
{
while(a != '\n')
scanf("%c",&a);
}
}
It works but according to my understanding, the following should have also worked
while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
printf("Please enter an integer only : ");
while(a != '\n')
scanf("%c",&a);
}
Can someone please tell me why above did not worked ?? Also if someone has better solution please give it also.
Note :I am considering 12qwe also as an invalid input. I just want integers.
The problem with
while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
printf("Please enter an integer only : ");
while(a != '\n')
scanf("%c",&a);
}
is that if a happens to contain '\n' before the scan, and the scan fails, the inner while loop doesn't run at all. So
if the scan failed trying to parse an int from the input stream because the input was e.g. "ab c\n", the offending input remains in the input stream, the next scanf in the outer while loop control fails parsing an int again, a remains '\n', repeat.
if an input error occurred before reading a character from the stream into a, the scanf in the outer loop control fails because of a corrupted stream, repeat.
In the other version,
while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
printf("Please enter an integer only : ");
if(a == '\n')
scanf("%c",&a);
else
{
while(a != '\n')
scanf("%c",&a);
}
}
you make at least some progress as long as there is input to be read from the stream, since whatever a contains, you read at least one character from the input stream before attempting the next parsing of an int. It will also result in an infinite loop if the input stream is corrupted/closed/ends prematurely, e.g. if you redirect stdin from an empty file. You can have that loop also output multiple "Please enter an integer only : " messages by giving input like `"a\nb\nc\nd\n".
So you should check whether scanf encountered the end of the stream or some other read error before converting anything from the input, and abort in that case:
int reads;
while(((reads = scanf("%d%c", &num, &a)) != 2 && reads != EOF) || a != '\n')
{
printf("Please enter an integer only : ");
// read at least one character until the next newline
do {
reads = scanf("%c", &a);
}while(reads != EOF && a != '\n');
}
This is a wrong way to do. You can rather read the input using fgets() and then parse your string for integer ASCII range.
fgets(s, 1024, stdin)
for (i=0; s[i] ! = '\0';i++) {
if( s[i] <'0' && s[i] >'9')
// not an integer<br>
You can also use standard functions like isalnum, isalpha etc.
it works……
while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
printf("Please enter an integer only : ");
do{
scanf("%c",&a);
}while(a != '\n');
}

Resources