How to fix - unexpected output using getchar() and do-while - c

I am trying to make a simple code that will read a char from input and execute "Correct" or "Incorrect input" and run the code again until the correct input is entered. First of all it does not work for capital X. The other issue that I want to fix is that after the incorrect input I have to press enter to get the "Enter x" message, instead of getting in immediately after the incorrect input message.
#include <stdio.h>
int main()
{
do
{
printf("Enter x\n");
if (getchar()=='x'|| getchar()=='X')
{
printf("Entered char is X\n");
return 0;
}
else
{
printf("Input incorrect! Please try again!!!\n");
}
}
while (getchar()!='x' || getchar()!='X');
return 0;
}

You need to store the input in a variable, otherwise you keep asking for input several times in a row, for each getchar call.
For weird historic reasons, getchar actually returns an int, since the value EOF that can be returned from it is an int. So the variable must be int.
And finally, each time the user hits enter, a invisible line feed character \n is appended to the input stream. This character does you no good, so you should discard it with an extra read.
#include <stdio.h>
int main (void)
{
int input;
do
{
printf("Enter x\n");
input = getchar();
getchar(); // extra getchar to chew up line feed from stdin
if (input=='x'|| input=='X')
{
printf("Entered char is X\n");
}
else
{
printf("Input incorrect! Please try again!!!\n");
}
} while (input!='x' && input!='X');
return 0;
}
Please note that the opposite of input=='x'|| input=='X' is input!='x' && input!='X' (De Morgan's laws). "If input is not 'x' and input is not 'X' then loop".

When you hit the ENTER key the newline character \n is placed in input buffer. You need to consume that newline character in order to read the next character.
Also you are reading two time, which is unnecessary in this case. So your code should be like this
#include <stdio.h>
int main()
{
char inp;
do
{
printf("Enter x\n");
inp = getchar();
getchar(); // reading the newline character '\n'
if (inp == 'x'|| inp =='X')
{
printf("Entered char is X\n");
return 0;
}
else
{
printf("Input incorrect! Please try again!!!\n");
}
}
while (inp !='x' || inp !='X');
return 0;
}
p.s There is no need to put condition checking in while loop, since you are returning in if condition. while(true) would work fine. Thanks #bruno for pointing that out.

In your code:
if (getchar()=='x'|| getchar()=='X')
getchar() is called twice.
Instead, you should write it this way:
char c = getchar();
if (c=='x'|| c=='X')
for the second part, if your goal is print the message on a new line, then just simply change your printf to:
printf("\nInput incorrect! Please try again!!!\n");

Related

want to call fgets() multiple times based on users need

User enters '1' or '0' choice to continue getting string using fgets(). So when the user enters the choice, fgets reads it from console. I am storing it in another variable. But fgets gets the choice and stores it in messages. I have tried using fflush(stdin) after receiving the choice. Please help me out.
int main() {
int choice=1;
char *message;
int i=0;
while (choice == 1) {
fflush(stdout);
printf("Enter the message: ");
fflush(stdout);
message = fgets(message,200,stdin);
while (message[i]!='\n') {
i++;
}
message[i] = '\0';
send_message(message);
printf("\nType '1' to continue or '0' to quit: ");
scanf("%d",&choice);
fflush(stdin);
}
}
It looks like you're trying to scanf() to read the user's input -- this is inherently dangerous. (See https://www.reddit.com/r/learnprogramming/comments/1d0w4x/c_scanf_d_but_error_if_user_enters_a_character/).
I'd recommend either using %s for your format string, or better yet, build a subroutine to do safe input and parse it the old-fashioned way, such as something along these lines:
/* getsafe() - Generic input using the preferred input method rather than gets() */
#include <stdio.h>
#include <string.h>
char *getsafe(char *inpstr,int inpsiz) {
char *seachr; /* Result of search via strchr() */
if (inpstr==NULL) {
return(NULL);
}
if (fgets(inpstr,inpsiz,stdin)==NULL) {
return(NULL);
}
seachr=strchr(inpstr,'\n');
if (seachr!=NULL) *seachr=0;
return(inpstr);
}
That way you can specify the buffer length and provide a string (array of characters) of sufficient length as to prevent buffer overruns (security issue), and then parse the [0] position in that array for your answer.
#define ANSSIZ 80 /* Maximum allowed size of user answer */
char usrans[ANSSIZ]; /* User Answer */
printf("Enter 'y' or 'n': ");
getsafe(usrans, ANSSIZ-1);
There's a lot of problems with this - It probably belongs on Code Review
However, here is a critique on some of the major problems
int main() {
int choice=1;
char *message; // This is a pointer, but is not malloc'ed. You might want "char message[200]" instead?
int i=0; // This is the only time "i" is set to 0. It needs to be reset at the start of the loop
while (choice == 1) {
fflush(stdout); // No need for this
printf("Enter the message: ");
fflush(stdout);
message = fgets(message,200,stdin);
while (message[i]!='\n') { // Why not use strlen?
i++; // "i" can keep growing forever if there is no newline (if someone entered 199 characters before pressing enter)
}
message[i] = '\0'; // fgets does this for you - The past loop was pointless
send_message(message);
printf("\nType 'y' to continue or 'n' to quit: "); // You forgot to flush here!
scanf("%d",&choice); // I don't think this will result in a 0 or 1 output... %d is for a digit, and you're asking the user for y or n.
fflush(stdin); // This is invalid and unneeded - You can't flush stdin
}
}

check input program gets stuck in an infinte loop

I'm trying to create a program that asks to type something and check if it is an integer. If it is an integer, then print "the integer is ...". Else, print "try again" and waits for another input. However, the program prints an infinite number of "try again" if you type in a character. Here's the source code:
#include <stdio.h>
#include <stdbool.h>
int main()
{
int inp;
bool t = 1;
printf("type an integer\n");
while (t) {
if (scanf("%i", &inp) == 1) {
printf("The integer is %i", inp);
t = 0;
} else {
printf("try again");
scanf("%i", &inp);
}
}
}
OP's code fail to consume the offending non-numeric input. It remains in stdin, for the next input function. As it is unfortunately just another scanf("%i", &inp) which fails the same way - infinite loop.
After attempting to read an int, read the rest of the line.
#include <stdio.h>
#include <stdbool.h>
int main() {
int inp;
int scan_count;
printf("Type an integer\n");
do {
scan_count = scanf("%i", &inp); // 1, 0, or EOF
// consume rest of line
int ch;
while ((ch == fgetchar()) != '\n' && ch != EOF) {
;
}
} while (scan_count == 0);
if (scan_count == 1) {
printf("The integer is %i\n", inp);
} else {
puts("End of file or error");
}
}
An even better approach would read the line of user input with fgets(). Example
When you entered a char, the variable inp in scanf("%d", &inp) would get null, since the input that doesn't match the format string. And the character you input would remain in the buffer, so that's the reason both your scanf would not stop.
A simplest way to fix this is modify your second scanf("%i", &inp); to scanf("%c", &c); (don't forget to declare a char c in your main function).
check here while(t) its in an infinite loop because you have to set a condition for t something like while(t==1) or while(t>1) or (t<1) something like that. saying while(t) means that t can be anything and it will continue to run.
There is nothing in to break the while loop.
consider getting rid of the boolean, and simply using a while (1) loop with a break. Also you should be using "%d" to indicate an integer in scanf/printf. And there is no need for the scanf call in the else, since your program would loop back and call scanf again anyway.
#include <stdio.h>
int main() {
int inp = 0;
printf("type an integer\n");
while (1) {
if (scanf("%d", &inp) == 1) {
printf("The integer is %d", inp);
break;
}
else {
printf("try again");
}
}
return 0;
}
I hope this helped.

C program stops after first the first recursive call

I've tried to use character data type to compare in variable reply if equal to y it will continue calling the function recursion(), however, it did only 1 recursion() call and the program terminated. This only work if I use the int data type, as the variable to compare. Please anyone can let me know why this happen?
#include <stdio.h>
void recursion()
{
char reply;
printf("Continue?:");
reply=getchar();
if(reply=='y')
{
printf("Continued\n");
recursion();
}
}
int main()
{
recursion();
return(0);
}
output:
Laptop1:User1$ ./recur
Continue?:y
Continued
Continue?:Laptop1:User1$
getchar() will read newline character if it is, and it will prevent it from continueing.
Try this:
#include <stdio.h>
int getchar2()
{
int c;
do
{
c = getchar();
} while (c == '\n'); /* ignore newline characters */
return c;
}
void recursion()
{
int reply;
printf("Continue?:");
reply=getchar2();
if(reply=='y')
{
printf("Continued\n");
recursion();
}
}
int main()
{
recursion();
return(0);
}
The problem is that when end-users enter 'y' in the terminal, they press Enter. This inserts another character into the stream - '\n'. That is the character that the next call to getchar() would return, ending the chain of calls due to
if(reply=='y')
condition evaluating to "false".
You can fix the problem in several ways - for example, by using scanf:
if (scanf(" %c", &reply) == 1 && reply == 'y')
// ^
// Note the space above
Adding a space character in front of %c ensures that scanf skips whitespace characters before reading the character into reply variable.

While input is not a number, goes into Infinite loop

I'm just a beginner and am trying to make a a program that asks for a number and if a letter is input, it says "that's not a number" and asks for a number again, until a number is input.
However, my program keeps going into an infinite loop with the current code. Any help would be appreciated to fix this. Also, I would also like the program to say "please input something" if nothing is input, but don't know how to do this. Thanks.
#include <stdio.h>
int main()
{
float i;
printf("enter a number");
while(scanf("%f", &i) != 1)
{
puts("That is not a number.");
scanf("%f", &i);
}
}
You need to clear the bad input from stdin after your scanf fails:
#include <stdio.h>
int main()
{
float i;
char trash[1024];
while (1)
{
printf("Please enter a number: ");
fflush(stdout);
if (1 == scanf("%f", &i))
break;
/* scanf failed: clear the bad input from stdin */
if (NULL == fgets(trash, sizeof(trash), stdin)) /* NOTE: assumes 1 entry per line and no line longer than 1023 characters */
exit((fprintf(stderr, "Unexpected EOF or error!\n"), 1));
puts("That is not a number.");
}
printf("You entered: %f!\n", i);
return 0;
}
As an alternative to the fgets() to clear the line, you could call scanf("%1023s", trash), which would only suck in the next whitespace delimited series of characters. This would allow you to handle multiple entries on a single line with mistakes intermixed, for example.
Your program goes into infinite loop because after the invalid input, (scanf("%d", &i) != 1)condition being TRUE, the invalid input which is left in the input buffer is not consumed, it's still in the buffer. So the same invalid input is read over and over again.
To avoid, once scanf() fails, you need to flush out all the input buffer contains before calling next scanf().
Maybe inside the while loop, calling getchar() until a newline or EOF will help. Also, the second scanf() can be removed, IMHO.
After your non numeric[More precisely input which doesn't match the formating of scanf()] input you need to clear the stdin. If not the same input will be read till stdin get cleaned or you terminate the program. A reference answer can be found on this question
Quoted
On success, the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file.
Reason for infinite loop : Since you don't clear stdin, same values will be read by scanf() and always full fill while condition resulting in a infinite loop.
Use following edited code :
#include <stdio.h>
int main()
{
float i;
char c;
printf("enter a number");
while(scanf("%f", &i) != 1)
{
puts("That is not a number.");
scanf("%f", &i);
while ((c = getchar()) != '\n' && c != EOF); // Flush stdin
}
}
Your code is taking input of a number. Thats why if you even give input a letter, it will take the ASCII value of the letter, which is a valid number. And Further more please take a character as an input. Here I have modified your code which should work
#include <stdio.h>
int main()
{
char i;
printf("enter a number");
while(1)
{
scanf("%c",&i);
if (c >=48 && c <= 57) // here ascii value of numbers between 0-9 is 48-57 respectively
{
puts("That is a number.");
break;
}
else
{
puts("That is not a number.");
scanf("%c",&i);
}
}
}

Data Validation in C

I was trying out a simple program in C for validating user data. The program is supposed to identify whether a user entered character is a number, alphabet or a special character.
Somehow , the code identifies every kind of input character as a number. I have appended the code below, I'd be grateful if someone could kindly point out where I'm going wrong ?
//Program to take input from the user and determine whether it is character, number, or a special character
#include<stdio.h>
#include<conio.h>
#include<string.h>
char ch;
int main()
{
clrscr();
printf("Enter a character \n");
scanf("%c \n",ch);
if ((ch>='A'&& ch<='Z')||(ch>='a'&& ch<='z') )
{
printf("The character entered is an alphabet \n" );
}
else if ((ch>=0)&&(ch<=9))
{
printf("Character entered is an number \n");
}
else
{
printf("Character entered is a special character");
}
return 0;
}
scanf accepts a pointer as the argument for %c. In other words,
scanf("%c \n",ch);
should be written as:
scanf("%c\n",&ch);
Without the reference operator (&), scanf receives the value of ch. In this case, the value is garbage, because ch is unset.* Referencing ch gives scanf a pointer to ch, not ch itself, so scanf can modify the value of ch by dereferencing the pointer (using the dereference operator, *).
There's also the issue with digit checking that Himadri mentioned.
* This is actually undefined behaviour.
Oh, Arun very silly mistake.
In your second condition in else if you have to right 0 and 9 in single quotation mark.
So, your code will be -
if ((ch>='A'&& ch<='Z')||(ch>='a'&& ch<='z') )
{
printf("The character entered is an alphabet \n" );
}
else if ((ch>='0')&&(ch<='9'))
{
printf("Character entered is an number \n");
}
else
{
printf("Character entered is a special character");
}
May be this is the only mistake. Now, it should work.
A few comments on style:
conio.h and clrscr() are non-standard.
Global variables are bad (char ch). Declaring them non-static is also bad.
Always check the return value of scanf. This will help you catch input format errors.
In this case, as we need to just a single character, getchar is more appropriate.
This is how I would've written this program:
#include <stdio.h>
#include <ctype.h>
int main()
{
int ch; /* We use an int because it lets us check for EOF */
printf("Enter a character: ");
fflush(stdout); /* Remember to flush the output stream */
ch = getchar();
if (ch == EOF)
{
printf("end-of-file or input-error\n");
return 1;
}
if (isalpha(ch))
printf("The character entered is an alphabet\n" );
else if (isdigit(ch))
printf("Character entered is an number\n");
else
printf("Character entered is a special character\n");
return 0;
}

Resources