C: scanf input single character and validation - c

I've encountered a problem when validating a single-char scanf input in C and I cannot find an existing solution that works...
The scenario is: a method is taking a single letter 'char' type input and then validating this input, if the criteria is not met, then pops an error message and re-enter, otherwise return this character value.
my code is:
char GetStuff(void)
{
char c;
scanf("%c", &c);
while(c != 'A' || c != 'P')
{
printf("invalid input, enter again (A for AM or P for PM): ");
scanf ("%c", &dtChar);
}
return c;
}
however, i got the infinite loop of error message no matter what input I type in. I read some other posts and guess it's the problem that %c specifier does no automatically get rid of the newline when I hit enter, and so far I have tried:
putting a white space before/after %c like:
scanf(" %c", &c);
write a separate method or include in this GetStuff method to clean the newline like:
void cleanBuffer(){
int n;
while((n = getchar()) != EOF && n != '\n' );
}
Can anyone help me with this problem please? Thank you in advance.

Please consider the following snippet:
#include <stdio.h>
#include <ctype.h>
char GetStuff(void)
{
char c;
do {
printf("Please enter A for AM or P for PM: ");
scanf ("%c", &c);
// clean input buffer (till the end of line)
while(getchar()!='\n');
} while(toupper(c) != 'A' && toupper(c) != 'P');
return c;
}
int main(void)
{
printf("Your input is'%c'\n", GetStuff());
return 0;
}
Note the points:
condition while(c != 'A' || c != 'P') will be always true (just because one character cannot be 'A' and 'P' at the same time), so use while(c != 'A' && c != 'P') instead
No need for two scanf if you use do..while loop
After entering a char with scanf it is recommended to clean all characters from buffer, e.g. with while(getchar()!='\n'); (this will clean all input including incorrect and redundant characters)
use toupper to avoid making 4 comparison (actually single c=toupper(c) inside loop can minimize your while as while(c != 'A' && c != 'P') )
UPDATE:
To add message "Invalid input" and adding some other useful improvement subjected befor... new code is as:
#include <stdio.h>
#include <ctype.h>
void CleanBuffer(){
int n;
while((n = getchar()) != EOF && n != '\n' );
}
char GetStuff(void)
{
char c;
do {
printf("Please enter A for AM or P for PM: ");
scanf (" %c", &c);
c = toupper(c); // here letter become uppercase
CleanBuffer();
} while( (c != 'A' && c != 'P')?printf("Invalid input! "):0 );
return c;
}
int main(void)
{
printf("You have entered: %c\n", GetStuff());
return 0;
}
Note: function will return 'A' or 'P' in uppercase, so if this is not needed change the code as in example before update (use two toupper and do not change c after scanf). Also you can use tolower as an option (of course with comparing to 'a' and 'p').

#include <stdio.h>
char GetStuff(void) {
char c;
scanf("%c", &c);
getchar();
while ((c != 'A') && (c != 'a') && (c != 'P') && (c != 'p')) {
printf("invalid input, enter again (A for AM or P for PM): ");
scanf ("%c", &c);
getchar();
}
return c;
}
int main(void) {
printf("Calling GetStuff()...\n");
char x = GetStuff();
printf("User entered %c\n", x);
return 0;
}
You are using while (c != 'A' || c != 'P') as your loop conditional, but this will always return true. What you meant to use is the && "and" operator, instead of the || "or" operator.
Also, call getchar() after your scanf statements, to capture the newline. This should work the way you want it to.

Inside loop you are taking input in dtChar but your loop condition checks variable c which is not updated in the loop, that is causing infinite loop
Also you would change your condition
while(c != 'A' || c != 'P')
to
while(c != 'A' && c != 'P')
If you want user to enter either 'A' or 'P'

Another possible solution. As others mentioned the condition was to be done with &&. Anyway the big problem is how to remove what's left on the console input line. Since the console works by lines, we remove everything up to the next '\n'. If the user already left something on the input line before calling GetStuff(), it would be useful to add a call to SkipRestOfTheLine() before the while loop.
In general I suggest to start with a while(1) loop, before making it nicer (such as in the cleanBuffer() you posted).
#include <stdlib.h>
#include <stdio.h>
void SkipRestOfTheLine(void)
{
while (1) {
int c = fgetc(stdin);
if (c == EOF || c == '\n')
break;
}
}
char GetStuff(void)
{
while (1) {
int c = fgetc(stdin);
if (c == EOF)
exit(EXIT_FAILURE); // Deal with this case in an appropriate way
if (c == 'A' || c == 'P')
return c;
printf("invalid input, enter again (A for AM or P for PM): ");
SkipRestOfTheLine();
}
}
int main(void)
{
char c = GetStuff();
return 0;
}

try this,
char GetStuff(void)
{
char c;
scanf("%c", &c);
while (((c != 'A') || (c != 'a')) && ((c != 'P') || (c != 'p'))==1)
{
printf("invalid input, enter again (A for AM or P for PM): ");
scanf ("%c", &dtChar);
}
return c;
}
I hope this works, some time because of not given proper bracket it is stuck in the loop.

#include <stdio.h>
int main(){
char c;
do{
printf("invalid input, enter again (A for AM or P for PM): ");
scanf ("%s", &c);
}while ((c != 'A') && (c != 'P'));
return 0;
}

Related

How to restrict to a one letter input?

I realised that if the input is a word starting with 'y' or 'n', it will escape the loop. How can I restrict the loop such that it will continue looping unless the input is a single character?
do
{
printf("Do you want to try again? (Y/N): ");
fflush(stdin);
scanf("%c", &repeat);
repeat = toupper(repeat);
if (repeat != 'Y' && repeat != 'N')
printf("Invalid answer. Please enter 'Y' or 'N'.\n\n");
} while (repeat != 'N' && repeat != 'Y');
like this:
#include <stdio.h>
#include <ctype.h>
int main(void){
char repeat[3] = {0};//3 : one character + one character + NUL
do{
printf("Do you want to try again? (Y/N): ");fflush(stdout);
if(EOF==scanf("%2s", repeat)){ *repeat = 'N'; break; }
*repeat = toupper(*repeat);
if (repeat[1] || *repeat != 'Y' && *repeat != 'N'){//repeat[1] != '\0'..
printf("Invalid answer. Please enter 'Y' or 'N'.\n\n");
scanf("%*[^\n]");scanf("%*c");//clear upto newline
*repeat = 0;
}
} while (*repeat != 'N' && *repeat != 'Y');
puts("Bye!");//try agein or see ya, bye
return 0;
}
First fflush(stdin); does not make sense except in Microsoft's world.
Then, the scanf family function returns a value which is the number of input token successfully decoded and that return value should always be controlled. And %c should be used with caution because it can return a blank character (space or newline) remaining in buffer while %s only return printable characters. With those remarks you code could become:
repeat = '\0';
do
{
char dummy[2], inp[2];
printf("Do you want to try again? (Y/N): ");
// fflush(stdin);
if (1 == scanf("%1s%1s", inp,dummy) repeat = toupper(inp[0]);
if (repeat != 'Y' && repeat != 'N')
printf("Invalid answer. Please enter 'Y' or 'N'.\n\n");
} while (repeat != 'N' && repeat != 'Y');
Alternatively to using scanf() one can use fgets() to read a line and then do the parsing one self:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char repeat = '\0';
do
{
int input_valid = 0; /* Be pessimistic. */
char line[3] = {0};
puts("Do you want to try again? (Y/N):");
do /* On-time loop, to break out on parsing error. */
{
if (NULL == fgets(line, sizeof line, stdin))
{
break; /* Either fgets() failed or EOF was read. Start over ... */
}
if (line[1] != '\0' && line[1] != '\n')
{
break; /* There was more then one character read. Start over ... */
}
line[0] = toupper(line[0]);
if (line[0] != 'Y' && line[0] != 'N')
{
break; /* Something else but Y or N was read. Start over ... */
}
input_valid = 1;
} while (0);
if (input_valid == 0)
{
int c;
do /* Flush rest of input. if any. */
{
c = getc(stdin);
} while (EOF != c && '\n' != c);
fprintf(stderr, "Invalid answer. Please enter 'Y' or 'N'.\n\n");
}
else
{
repeat = line[0];
}
} while ('\0' == repeat);
printf("The user entered: '%c'\n", repeat); /* Will only print either Y or N. */
return EXIT_SUCCESS;
}

How to use loops in terms of input (in C language)?

I've been trying to get this code to work but the loop does not seem to work? I am very new to C and I sort of get confused with the syntax of this language. However my loop is not functioning like how I want it to be. I want the if and else statement to work but no matter what input (right or wrong) it always outputs "thank you".
#include <stdio.h>
#include <stdlib.h>
int confirm()
{
char c;
printf("Confirm (y/n): ");
scanf("%c", &c);
while (scanf("%c", &c))
{
if (c = 'Y' && 'y' && 'N' && 'n')
{
printf("\nthank you");
break;
}
else
{
printf("\nInput not recognised, try again. \n");
printf("\nConfirm (y/n): ");
scanf("%c", &c);
}
}
}
int main(int argc, char* agrv[])
{
confirm();
return 0;
}
it won't ask to enter another output when the output is incorrect. It just keeps ending from the if statement, thus the loop is not running?
Please help.
There's nothing wrong with your loop - it's the if statement that's wrong.
This code compiles, but it does not do what you want it to do:
if (c = 'Y' && 'y' && 'N' && 'n')
= is an assignment; you need == to do a comparison
&& means "AND"; you need ||, which means an "OR"
You combine logical expressions, not constants with && or ||
The condition should be
if (c == 'Y' || c == 'y' || c == 'N' || c == 'n')
Also note that when you read single characters with %c, your program "sees" all characters, including whitespace. This is a problem, because the '\n' left over in the buffer will be passed to your program before Y or N. To fix this, add a space before %c to your format string:
scanf(" %c", &c)
// ^
// |
// Here
Your code also ignores the first character that it reads. I think this is not intentional, so remove the call of scanf before the loop. You should also remove the second scanf from the loop, leaving the only call to scanf in the loop header.
int confirm()
{
char c;
printf("Confirm (y/n): ");
//scanf("%c", &c);// <---------- needless
while (scanf("%c", &c)) //<----while loop will do `scanf("%c",&c)`, so previous line should be remove.
{
if (c == 'Y' || c == 'y' || c == 'N' || c == 'n')// <- &&(AND); ||(OR). Also, be careful that don't be lazy, [c == 'Y' || 'y' || 'N' || 'n'] can't to communicate with computer
{
printf("\nthank you");
break;
}
else
{
printf("\nInput not recognised, try again. \n");
printf("\nConfirm (y/n): ");
scanf("%c", &c);
}
}
}

C programming getchar()

I have two problems writing my code. The first problem I have is getting my getchar() to work if the user enters no text and just hits enter. I need to print an error if they do so and prompt the user to reenter the text in a loop until they do enter text. Is there any way to do so because everything I have tried has failed.
Here is the code I have for that section:
printf("Enter a text message: ");
while((c=getchar()) != '\n' && c != EOF)
{
text[i]= c;
i++;
}
I am new to C so I am limited on ideas to fix my dilemma. As you can see I am setting the input equal to an array. This leads to my second problem, I need to limit the input to no more than 100 characters. But, instead of giving the user an error I need to just chop off the extra characters and just read the first 100.
The simplest solution to your problem is to use fgets. We can give limit to the input so that it doesn't read the extra characters after the given limit.
Refer this sample code. Here I am printing the string if the user is not pressing Enter key:
#include <stdio.h>
int main()
{
char str[100];
fgets(str, 100, stdin);
if(str[0] != '\n')
{
puts(str);
}
return 0;
}
#include <stdio.h>
#define MAXSIZE 100
int main() {
char text[MAXSIZE+1]; // one extra for terminating null character
int i = 0;
int c;
while (1) {
printf("Enter a text message: ");
i = 0;
while ((c = getchar()) != '\n' && c != '\r' && c != EOF) {
if (i < MAXSIZE) {
text[i]= c;
i++;
}
}
if (i > 0 || c == EOF)
break;
printf("Empty string not allowed.\n");
}
text[i] = '\0';
printf("You entered: %s\n", text);
return 0;
}
Test code to detect non-compliant system:
#include <stdio.h>
int main() {
int c;
printf("Just hit enter: ");
c = getchar();
if (c == '\r')
printf("\\r detected!!!\n");
else if (c == '\n')
printf("\\n detected.\n");
else
printf("Yikes!!!\n");
return 0;
}
First of all getchar() can take only one character an input. It cannot take more than one character.
char c;
int total_characters_entered = 0;
do
{
printf ("Enter a text message: ");
c = getchar();
if (c != '\n')
{
total_characters_entered++;
}
} while (total_characters_entered <= 100);
I have written some code that will iterate in while loop until user has entered 100 characters excluding "Simple Enter without any text"
Please let me know if it does not satisfy your requirement. We will work on that.

Counting input characters in C

I have just started learning C, been reading a C textbook by Keringhan and Ritchie. There was this example in the textbook, counting characters from user input. Here's the code:
#include <stdio.h>
main()
{
long nc;
nc = 0;
while(getchar() != EOF) {
if (getchar() != 'q')
++nc;
else
break;
}
printf("%ld\n", nc);
}
The problem is, when I execute the code, if I input only one character per line, when I input "q" to break, it doesn't do so. I have to type some word per line, only after that it will break the loop. Also, it only counts the half of the characters of the word. I.e. if I input
a
b
russia
it will only print '5' as final result.
Could you please explain to me why is this happening?
This works, but only when you finish off with an Enter. So, this will count the characters until the first "q" appears. That is just how getchar() and getc(stdin) work.
#include <stdio.h>
int main() {
char c = 0;
long count = 0;
short int count_linebreak = 1; // or 0
while((c = getchar()) != EOF) {
if(c != 'q' && (count_linebreak || (!count_linebreak && c != '\n'))) {
++count;
}else if(c == 'q') {
printf("Quit\n");
break;
}
}
printf("Count: %ld\n",count);
return 0;
}
A StackOverflow question about reading stdin before enter
C read stdin buffer before it is submit

Printing Uppercase/Lowercase letters

I'm doing a program that is asking the user to enter a stream of characters and printing out the number of uppercase and lowercase letters. I'm trying to do it with a function, but having some trouble printing it..for every character input im entering im getting 0, 0
Would appreciate your help to understand what am I doing wrong:
#include <stdio.h>
#include <ctype.h>
int case_letters(int ch);
int main(void)
{
int x;
printf("please enter a some characters, and ctrl + d to see result\n");
case_letters(x);
return 0;
}
int case_letters(int ch)
{
int numOfUpper = 0;
int numOfLower = 0;
while ((ch = getchar()) != EOF)
{
if ((ch = isdigit(ch)) || ch == '\n')
{
printf("please enter a valid character\n");
continue;
}
else if ((ch = isupper(ch)))
{
numOfUpper++;
}
else if ((ch = islower(ch)))
{
numOfLower++;
}
}
return printf("%d, %d", numOfUpper, numOfLower);
}
All of your if statements assign different value to ch and do not check ch's value.
For example, if you enter a correct char, this
if ((ch = isdigit(ch)) || ch == '\n')
will assign 0 to ch, because isdigit(ch) will return 0. I guess you need
if ( isdigit(ch) || ch == '\n')
Same for islower and isupper.
if ((ch = isdigit(ch)) || ch == '\n')
^-- assignment, not equality test.
You're trashing the value of ch with the return value of isdigit(), and isupper(), and islower(), so that the original user-entered value is destroyed as soon as you do the isdigit test.
Try
if (isdigit(ch) || ch == '\n')
else if (isupper(ch))
else if (islower(ch))
instead. No need to preserve the iswhatever values.

Resources