Weird issue with Output in C - c

#include <stdio.h>
struct agent
{
char name[30];
int age;
} list[20];
main()
{
struct agent getData();
char ch;
int i = 0;
int j;
puts("1. Enter More");
puts("2. Display");
puts("3. Exit");
while ((ch = getchar()) < '3')
{
if (ch == '1')
{
list[i++] = getData();
}
else if (ch == '2')
{
for (j = 0; j < i; j++)
{
puts(list[j].name);
printf("%d\n", list[j].age);
}
}
puts("1. Enter More");
puts("2. Display");
puts("3. Exit");
}
}
struct agent getData(
{
struct agent tmp;
puts("Enter name");
scanf(" %s",tmp.name);
puts("Enter age");
scanf("%d",&tmp.age);
return tmp;
}
OUTPUT:
1. Enter More
2. Display
3. Exit
1
Enter name
ace
Enter age
23
1. Enter More
2. Display
3. Exit
1. Enter More
2. Display
3. Exit
3
why are these statements
"1. Enter More
2. Display
3. Exit "
getting repeated??

getData() does not consume the newline char after your input. Thus, it is consumed on the next getchar() invocation. Since \n is "less than" the ascii-value of the int literal '3', but is neither '1' or '2', your menu prints again.
You can address this a number of ways, including having getData() consume the entire line, including the newline, or make the loop in main considerably smarter. Either way, make sure you know what you're testing valid data against '3'.

You're comparing an char like a int.
try this:
while (ch=getchar())!='3')

You need to skip trailing newline from previous scanf
which get consumed as input for the next getchar
Use:
int c;
while((c=getchar())!='\n' && c != EOF ); //eats newline came from scanf
after last scanf call

why are these statements "1. Enter More 2. Display 3. Exit " getting repeated??
Because of the newline character left behind by scanf in getdata() after pressing Enter.
Try this to eat up all the '\n'.
while ((ch=getchar()) != '3') {
while((ch=getchar())!='\n' && ch != EOF ); //to eatup the newline
if (ch == '1')
....

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

o count character entered through stdin first time it works for continuing the execution it is not readig the character

this code gives the output correctly for the first time but it is not reading the character for the second time execution scanf("%c"&op) is not reading the character for continuing the execution i tried with getchar(); and scanf(" %C",&op); but still it is not reading the input............................................................................
int main()
{
//declaring local variable
char op;
//do while for user interaction
do
{
//function call
count();
//asking if user want to continue execution
printf("\nDo you want to continue(Y/y):");
scanf(" %c",&op);
}while( op == 'Y' || op == 'y');
return 0;
}
int count()
{
char ch;
int word_count = 0, line_count = 0, char_count = 0;
//asking user for the input
puts("enter the sentence:");
//Loop to fetch the input
while( (ch =getchar()) != EOF)
{
//To count the number of characters
char_count++;
//If entered char is new line
if (ch == '\n')
{
//To count the number of lines in input
line_count++;
}
//To check if the entered input is space or tab or next line
if(ch == ' ' || ch == '\t' || ch == '\n' )
{
//Word count
word_count++;
//Get the char
ch = getchar();
//To check if the enter char is space or tab or new line
if(ch == ' ' || ch == '\t' || ch == '\n' )
{
//If the entrered char is space or tab or new line
word_count--;
}
//Returing the character to input stream
ungetc(ch,stdin);
}
}
//Printiong the number of char,word,line count
printf("\n");
printf("Line count\t: %d\n", line_count);
printf("Word count\t: %d\n", word_count);
printf("Character count\t: %d", char_count);
return 0;
}
For reading the character of the user's choice for continuation after you signaled EOF on the sentence input, you have to call clearerr(stdin) before the scanf(" %c",&op).
The clearerr function clears the end-of-file and error indicators for the stream …
Note that with your given scanf(" %c",&op), the newline character entered after y will be read as part of the next sentence, increasing the line count by one. To avoid this for the case where the user enters only a single choice character, you could use scanf(" %c%*c", &op). To handle also cases where the users enters more (e. g. yes), you could instead getchar() in a loop until \n or EOF.

C: Nested do while loop not looping correctly

This code is supposed to -
Count the number of characters from input sequence.
Repeat the action until user exits the program.
Use nested do-while loop to achieve this purpose.
But the inner loop is executed only once.
Why?
#include <stdio.h>
int main ()
{
int x;
char i, ans;
i = '\0';
do
{
i = '\0';
x=0;
printf("\nEnter sequence of character:");
do
{
i = getchar();
x++;
}
while(i!='\n');
printf("\nNumber of characters entered is: %d", --x);
printf("\nMore sequences (Y/N) ?");
ans = getchar();
}
while(ans =='Y' || ans == 'y');
After you read the answer yes/no (the line with ans = getchar();), you'll read an "y" and a "\n". You'll consume the "y" and process it, but the next iteration when you read i = getchar();, i will consume the remaining "\n", so will break that do-while loop.
Although it's not my favourite solution, a simple workaround is this:
#include <stdio.h>
int main ()
{
int x;
char i, ans;
i = '\0';
do
{
i = '\0';
x=0;
printf("\nEnter sequence of character:");
do
{
i = getchar();
x++;
}
while(i!='\n');
printf("\nNumber of characters entered is: %d", --x);
printf("\nMore sequences (Y/N) ?");
ans = getchar();
getchar();
}
while(ans =='Y' || ans == 'y');
}
So just consume that extra "\n". This will work only if you type "y" followed by "\n" in terminal. If you type any extra characters, you'll have undefined behaviour.
Note: In your version, try to type: "y1234" then enter when prompted if you want to input again. You'll see that in fact the nested do-while loop works and will count the 4 characters after "y".
What happened:
getchar is a macro that gets a character from stdin.
The delimiter ('\n' in this case) is counted as a separate
character that remains in the buffer and is retrieved the next time
getchar() is called.
This causes inner loop to exit.
What could be done:
Insert the following after ans = getchar();
i = getchar();
if(i != '\n')
ungetc(i,stdin);
New code explained:
ungetc(int x,FILE *stream) pushes a character back into input stream.
stdin is the standard input stream defined in <stdio.h>.
We are reading a character and putting it back if it is not '\n'.
Not exactly sure, but I think that when the user presses enter to finish the 1st input character the input buffer keeps then enter button as the \n character. Try adding if(i == '\n') getChar(); after the x++;.

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

Program looping two times (printing statement twice)

I'm trying to make a simple program for which the user is supposed to enter character 'a'. It is supposed to loop until 'a' is input. I have one statement printed if there is no input which works correctly. There is another statement if an incorrect letter or number is input, but the problem is that this causes the program to loop more than once and it prints the statements multiple times. Any help in fixing this is appreciated.
#include <stdio.h>
int main()
{
char input;
int i, len,num;
len = 1;
do
{
puts("Please enter alphabet 'a': ");
scanf("%c", &input);
for(i=0; i<len; i++)
{
if(isalpha(input)==0)
{
printf("Please input something.\n");
continue;
}
if(input == 'A' || input == 'a')
{
printf("Congratulations! You successfully input letter 'a'.");
return(0);
}
else
{
printf("That's not letter 'a'.");
}
}
}
while(1);
}
The problem is that after entering the character, you press newline and this is send to the input buffer. Now the next time scanf() is called, it reads the value from the buffer which is '\n' and scanf() thus stores this to input. Now this can be easily solved by the method pointed by #Gopi, but there is a better way. This is the code.
#include <stdio.h>
#include<ctype.h>
int main()
{
char input,ch;
do
{
puts("Please enter alphabet 'a': ");
scanf("%c", &input);
while( input!='\n' && (ch=getchar())!='\n' && ch!= EOF); // look here
if(isalpha(input)==0)
{
printf("Please input something.\n");
continue;
}
if(input == 'A' || input == 'a')
{
printf("Congratulations! You successfully input letter 'a'.");
return(0);
}
else
{
printf("That's not letter 'a'.");
}
}
while(1);
}
Now with the statement while((ch=getchar())!='\n' && ch!= EOF);, all the characters like '\n' are just flushed and not stored to input and thus solves the problem.
Also note that you don't need the for loop here, its useless for this code ( unless this is not your original code and there are other parts in it ).
There is a newline character in the buffer after the first input which is not flushed and that is being picked up by the %c in the second iteration.
Change your scanf() to
scanf(" %c", &input);
Note the space before %c which gobbles the newline character

Resources