do-while loop "enter more (y/n)" - character issue - c

So I'm working on basic C skills, and I want to design a code which enters as many numbers as the user wants. Then, it should display the count of positive,negative & zero integers entered.
I've searched Google & StackOverflow. The code seems fine according to those programs.
It compiles & runs. But whenever I input anything after the prompt "enter more? y/n", it returns to the code..
Please have a look at the code below:
#include<stdio.h>
int main()
{
int no,count_neg=0,count_pos=0,count_zero=0;
char ch='y';
clrscr();
do
{
puts("Enter number");
scanf("%d",&no);
if (no>0)
count_pos++;
else if (no<0)
count_neg++;
else
count_zero++;
puts("want more? - y/n ");
scanf("%c",&ch);
}
while (ch=='y');
if (ch=='n')
{
printf("No of positives = %d",count_pos);
printf("No of negatives = %d",count_neg);
printf("No of zeros = %d",count_zero);
}
getch();
return 0;
}

The problem is with "scanf("%c", &ch);"
What happens actually is :
Suppose you enter 'y' as a choice and hit 'enter'(return), the return is a character and
its character value is 10(since its a new line character), thus the scanf takes the 'return'
as its input and continues.
Solution :
1. use getchar() before scanf()
// your code
getchar();
scanf();
//your code
getchar() takes the return value as its input, thus you are left with your actual value.
add '\n' to scnaf()
// code
scanf("\n%c", &ch);
//code
when scanf() encounters the '\n' character it skips it (google about scanf, to know how
and why ), thus stores the intended value inside 'ch'.

A "better" form for:
int main()
is:
int main(void)
clrscr is not standard C.
You ought to check the return-value of any function which might indicate "interesting status," such as a failure condition, and from which you can gracefully deal with the situation. In this case, scanf is such a function.
I believe that your first do ... while condition will become false because it will pick up the newline character following your first scanf call. You might want to read about getchar or getc, instead of using scanf for the task of checking whether or not to run the loop again. You can "eat" unwanted characters, including a newline.

Here, I have corrected the problem. The problem was this that the "enter" you press after each number is a character and is takenup by the scanf() as it is there to scan some characters. So I have added a getchar(); before the scanf();so the "enter" is taken up by getchar(); and scanf() is now free to take your input.
#include<stdio.h>
int main()
{
int no,count_neg=0,count_pos=0,count_zero=0;
char ch='y';
clrscr();
do
{
puts("Enter number");
scanf("%d",&no);
if(no>0)
count_pos++;
else if(no<0)
count_neg++;
else
count_zero++;
puts("want more? - y/n ");
getchar();//<---- add this here
scanf("%c",&ch);
}
while(ch=='y');
if(ch=='n')
{
printf("No of positives = %d",count_pos);
printf("No of negatives = %d",count_neg);
printf("No of zeros = %d",count_zero);
}
getch();
return 0;
}

To fix the input is to use a C String like this scanf("%s",...);
This might break if you input more than one character because scanf will keep reading until the user hits enter, and your ch variable is only enough space for one character.

I run your code in Online compiler. I am not sure about other compiler.
I slightly changed your code. i.e., first i read char then int. If i do not change the order, char variable holds int variable value. This is the reason ( ch variable holds values of no variable).
#include<stdio.h>
int main()
{
int no,count_neg=0,count_pos=0,count_zero=0;
char ch='y';
do
{
puts("Enter number");
scanf("%c",&ch);
scanf("%d",&no);
if(no>0)
count_pos++;
else if(no<0)
count_neg++;
else
count_zero++;
puts("want more? - y/n ");
}
while(ch=='y');
if(ch=='n')
{
printf("No of positives = %d",count_pos);
printf("No of negatives = %d",count_neg);
printf("No of zeros = %d",count_zero);
}
return 0;
}
EDIT:
whenever integer and char are read through keyboard. it stores int value and enter key value. so this is the reason.
You have to add
scanf("%d",&no);
you code
......
.....
fflush(stdin);
scanf("%c",&ch);

use:
ch = getche();
instead of:
scanf("%c", &ch);

Related

isdigit() and system("cls") produce infinite loop

I was at first having trouble with a scanf() function being skipped, but I fixed that by adding in a space before %c in the scanf() function.
When trying to ask for input from the user as to whether the screen should be cleared, the scanf(" %c", cClear); conversion specifier gives an infinite loop, it is expecting a character, but responds to input as if not a character.
I believe it may have something to do with my input buffer.
I tried to use fflush(stdin) to no avail, I also used printf("%d", (int) cClear); to see the output, which was zero.
One other problem I have is trying to check user input for a digit.
I use:
if (isdigit(iSelection) == 0) {
printf("\nPlease select a valid numerical value.\n");
continue;
to check user input and restart the while loop, but anytime a character is entered and not an integer, I get an infinite loop.
My goal is to give the user the option to clear the screen after each calculation, and to also check input for being a digit.
Any help is appreciated.
//excluding code prior to main() and function definitions
int main(void) {
int iSelection = -1;
double foperand1 = 0, foperand2 = 0;
int ioperand1 = 0, ioperand2 = 0;
char cClear = '\0';
while (iSelection) {
printf("\n\nTHE CALCULATOR\n");
printf("\nCalculator menu:\n");
printf("\n1\tAddition");
printf("\n2\tSubtraction");
printf("\n3\tMultiplication");
printf("\n4\tDivision");
printf("\n5\tModulus (Integers only)");
printf("\n6\tTest if Prime (Integers only)");
printf("\n7\tFactorial (Integers only)");
printf("\n8\tPower");
printf("\n9\tSquare Root");
printf("\n0\tExit\n");
printf("\nPlease enter your selection: ");
scanf("%d", &iSelection);
//here we check for if input was a digit
if (isdigit(iSelection) == 0) {
printf("\nPlease select a valid numerical value.\n");
continue;
switch(iSelection) {
case 0:
break;
case 1:
printf("\nEnter the two numbers to add seperated by a space: ");
scanf("%lf %lf", &foperand1, &foperand2);
printf("\n%.5lf + %.5lf = %.5lf\n", foperand1, foperand2, addNumbers(foperand1, foperand2));
break;
}
//here we ask the user if they want to clear the screen
fflush(stdin)
if (iSelection != 0) {
printf("\nDo you want to clear the screen? ('y' or 'n'): ");
scanf("%c", cClear);
//printf("%d", (int) cClear); //used this to help debug
//scanf("%d", iSelection);
if (cClear == 'y')
system("cls");
}
}
printf("\nExiting\n");
return 0;
}
one error I get is "system" is declared implicitely. Could it possibly be the windows operating system not recognizing the pre defined function call?
Thanks to the people who commented to help me figure this out.
I had forgotten to add the (&) to the scanf() function call for the system"cls" function call, as well as didn't include the correct library (stdlib.h).
I was also able to make the program stop skipping the scanf() function by adding a space to the " %c" conversion specifier.
scanf Getting Skipped
I was able to make the isdigit() function work by changing the variable 'iSelection' to a character, but then I also had to change my case values to characters, not integers.

getchar() not working in c

getchar() is not working in the below program, can anyone help me to solve this out. I tried scanf() function in place of getchar() then also it is not working.
I am not able to figure out the root cause of the issue, can anyone please help me.
#include<stdio.h>
int main()
{
int x, n=0, p=0,z=0,i=0;
char ch;
do
{
printf("\nEnter a number : ");
scanf("%d",&x);
if (x<0)
n++;
else if (x>0)
p++;
else
z++;
printf("\nAny more number want to enter : Y , N ? ");
ch = getchar();
i++;
}while(ch=='y'||ch=='Y');
printf("\nTotal numbers entered : %d\n",i);
printf("Total Negative Number : %d\n",n);
printf("Total Positive number : %d\n",p);
printf("Total Zero : %d\n",z);
return 0 ;
}
The code has been copied from the book of "Yashvant Kanetkar"
I think, in your code, the problem is with the leftover \n from
scanf("%d",&x);
You can change that scanning statement to
scanf("%d%*c",&x);
to eat up the newline. Then the next getchar() will wait for the user input, as expected.
That said, the return type of getchar() is int. You can check the man page for details. So, the returned value may not fit into a char always. Suggest changing ch to int from char.
Finally, the recommended signature of main() is int main(void).
That's because scanf() left the trailing newline in input.
I suggest replacing this:
ch = getchar();
With:
scanf(" %c", &ch);
Note the leading space in the format string. It is needed to force scanf() to ignore every whitespace character until a non-whitespace is read. This is generally more robust than consuming a single char in the previous scanf() because it ignores any number of blanks.
When the user inputs x and presses enter,the new line character is left in the input stream after scanf() operation.Then when try you to read a char using getchar() it reads the same new line character.In short ch gets the value of newline character.You can use a loop to ignore newline character.
ch=getchar();
while(ch=='\n')
ch=getchar();
When you using scanf getchar etc. everything you entered stored as a string (char sequence) in stdin (standard input), then the program uses what is needed and leaves the remains in stdin.
For example: 456 is {'4','5','6','\0'}, 4tf is {'4','t','f','\0'} with scanf("%d",&x); you ask the program to read an integer in the first case will read 456 and leave {'\0'} in stdin and in the second will read 4 and leave {''t','f',\0'}.
After the scanf you should use the fflush(stdin) in order to clear the input stream.
Replacing ch = getchar(); with scanf(" %c", &ch); worked just fine for me!
But using fflush(stdin) after scanf didn't work.
My suggestion for you is to define a Macro like:
#define __GETCHAR__ if (getchar()=='\n') getchar();
Then you can use it like:
printf("\nAny more number want to enter : Y , N ? ");
__GETCHAR__;
I agree that it is not the best option, but it is a little bit more elegant.
Add one more line ch = getchar();
between scanf("%d",&x); and ch = getchar();
then your code work correctly.
Because when you take input from user, in this time you press a new line \n after the integer value then the variable ch store this new line by this line of code ch = getchar(); and that's why you program crash because condition can not work correctly.
Because we know that a new line \n is also a char that's why you code crash.
So, for skip this new line \n add one more time ch = getchar();
like,
ch = getchar(); // this line of code skip your new line when you press enter key after taking input.
ch = getchar(); // this line store your char input
or
scanf("%d",&x);
ch = getchar(); // this line of code skip your new line when you press enter key after taking input.
pieces of code work correctly.

How to enter a letter to quit a program in C

I am new to C programming. I have been writing this code to add numbers and I just need help with this one thing. When I type the letter 'q', the program should quit and give me the sum. How am I supposed to do that? It is currently the number 0 to close the program.
#include <stdio.h>
int main()
{
printf("Sum Calculator\n");
printf("==============\n");
printf("Enter the numbers you would like to calculate the sum of.\n");
printf("When done, type '0' to output the results and quit.\n");
float sum,num;
do
{
printf("Enter a number:");
scanf("%f",&num);
sum+=num;
}
while (num!=0);
printf("The sum of the numbers is %.6f\n",sum);
return 0;
}
One approach would be to change your scanf line to:
if ( 1 != scanf("%f",&num) )
break;
This will exit the loop if they enter anything which is not recognizable as a number.
Whether or not you take this approach, it is still a good idea to check the return value of scanf and take appropriate action if failed. As you have it now, if they enter some text instead of a number then your program goes into an infinite loop since the scanf continually fails without consuming input.
It's actually not as straightforward as you'd think it would be. One approach is to check the value returned by scanf, which returns the number of arguments correctly read, and if the number wasn't successfully read, try another scanf to look for the quit character:
bool quit = false;
do
{
printf("Enter a number:");
int numArgsRead = scanf("%f",&num);
if(numArgsRead == 1)
{
sum+=num;
}
else // scan for number failed
{
char c;
scanf("%c",&c);
if(c == 'q') quit = true;
}
}
while (!quit);
If you want your program to ignore other inputs (like another letter wouldn't quit) it gets more complicated.
The first solution would be to read the input as a character string, compare it to your character and then convert it to a number later. However, it has many issues such as buffer overflows and the like. So I'm not recommending it.
There is however a better solution for this:
char quit;
do
{
printf("Enter a number:");
quit=getchar();
ungetc(quit, stdin);
if(scanf("%f", &num))
sum+=num;
}
while (quit!='q')
ungetc pushes back the character on the input so it allows you to "peek" at the console input and check for a specific value.
You can replace it with a different character but in this case it is probably the easiest solution that fits exactly what you asked. It won't try to add numbers when the input is incorrect and will quit only with q.
#Shura
scan the user input as a string.
check string[0] for the exit condition. q in your case
If exit condition is met, break
If exit condition is not met, use atof() to convert the string to double
atof() reference http://www.cplusplus.com/reference/cstdlib/atof/

Infinite loop code in C

In the below program I try to input a number between 1 to 100 but if I enter a 'character' or "string" ( like s or sova ) during the execution time of scanf() statement it creates a infinite loop. so I try to do .... when I input a string or a character it shown me a message like "wrong value entered. enter again" and it will enter again...
Thanx;
#include<stdio.h>
int main()
{
int a;
scanf("%d",&a);
while(!(a>=1&&a<=100))
{
printf("wrong value entered. enter again\n");
scanf("%d",&a);
}
printf("you enter %d. Thanxz",a);
return 0;
}
You need to check the return value of scanf
If the user has not entered a integer, you need to eat the input. The scanf function will continually say not a integer, try again. So if scanf returns 0 you need to deal with it
When you use scanf you are working with buffered input, this means that when you enter a value say "123" and press ENTER then "123" plus the ending character (ENTER) will all be added to the buffer. scanf then removes 123 since %d specifies that an integer should be read but if a user enters something invalid like a string instead then the buffer will not be emptied.
A better way to read input from the keyboard is to use fgets() where you specify a max length to read. Once you have the input you can use sscanf() to retrieve the numeric value from it. The ENTER till then not irritate your input.
char buffer[128];
fgets( buffer, 128, stdin );
sscanf( buffer, "%d", &a );
Also always check return values from functions as a rule of thumb so that you can do appropriate action if the function fails.
If the return value from scanf is not equal to the number of item you like the user to input, read all characters of the input buffer until there is a '\n'. But instead of copying a whole loop over and over again to the places in your code where the user should input something, you could wrap the loop in a function like this:
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
void input(const char *format,...)
{
va_list ap;
int r;
/* number of items [to read] */
int noi=0;
for(r=0;r<strlen(format)-1;r++)
{
if(format[r]=='%')
{
if(format[r+1]!='%')
noi++;
else
r++;
}
}
do
{
va_start(ap,format);
r=vscanf(format,ap);
va_end(ap);
if(r!=noi)
{
switch(r)
{
case EOF:
case 0:
printf("All wrong, try again!\n");
break;
default:
printf("Unexpected value after item no %d!\n",r);
}
while(getc(stdin)!='\n');
}
else
break;
} while(1);
}
Hope that helps,
Jan
Try this.
#include <stdio.h>
#define FLUSH while (getchar() != '\n') // macro to eat invalid input
int main (void) {
int a = 0;
printf ("Enter an integer: ");
scanf("%d", &a);
while (a < 1 || a > 100) {
FLUSH;
printf("Invalid input. Please try again: ");
scanf("%d",&a);
}
printf("You entered %d.\nThanks!\n", a);
return 0;
}
Your code shows several coding habits that need to be changed:
Include (void) in the parameter list of main().
Leave spaces on either side of binary operators: while(!(a>=1&&a<=100)) is needlessly ugly and hard to read.
Simplify your logical expressions. Why use (! (a>=1 && a<=100)) when it means the same thing as (a < 1 || a > 100), and the latter is so much easier to read?
Prompt for user input when needed. Don't have the cursor just sit at a blank line with no indication to the user about what to do.
Use proper grammar and capitalization in your prompts. There's no reason to be lazy in your programming.

Why does my program loop without receiving any new input?

I am trying to make is so that my program will start over once the answer is given. It just won't function again once I run it once. I want to make it functional to where the user doesn't have to start the program up again. Thanks!
#include <stdio.h>
#include <math.h>
int main()
{
float firstnum, secondnum, answer;
char function;
printf("\nHello and welcome to my calculator!\n"); //Intro
start: //Area to loop to when program completes
printf("\nPlease input the function you would like to use. These include +, -, *, /.\n"); //Asking for function input
scanf("%c", &function); //Receiving Function Input
printf("\nNow please input the two variables.\n"); //Asking for variables
scanf("%f", &firstnum);
scanf("%f", &secondnum); //Receiving Input for Variables
if (function == '+') //Doing calculation
{
answer = firstnum+secondnum;
}
else if (function == '-')
{
answer = firstnum-secondnum;
}
else if (function == '*')
{
answer = firstnum*secondnum;
}
else if (function == '/')
{
answer = firstnum/secondnum;
}
else
{
printf("Sorry that was an incorrect function. The correct inputs are +, -, *, /."); //If they don't follow the directions
}
printf("Your answer is %f \n", answer); //Answer
goto start; //Loop
return 0;
}
It's the [enter] key. Your first scanf is reading the enter key you pressed to terminate the previous iteration.
So you need to add another scanf("%c", &function); or getchar(); just before the goto to eat the newline.
When reading in numbers, scanf will eat any initial whitespace; but when reading characters, it won't. It gives you the very next byte in the stream.
A better way, perhaps, would be to tell `scanf` where to expect all the newlines. This way you don't need that *weird* mystery line that doesn't appear to do anything but isn't commented (!); because that's gonna cause problems when you play with this code again months from now.
//scanf("%c\n", &function); /* read a character followed by newline DOESN'T WORK */
...
//scanf("%f\n", &secondnum); /* read a number followed by newline DOESN'T WORK */
This way, trailing newlines are consumed. Which is, I think, the more intuitive behavior (from the User side).
Nope. Doesn't work. Wish it did, cause I'd look less foolish.
I'm not upset by the goto. It's nice to see an old friend. This is an appropriate use of it if ever there was one. It is exactly equivalent to the while form. So you should certainly be aware that most people will prefer to see while(1) because it tells you more about what's going on than label:. But for an infinite loop in a function smaller than a screen, why not? Have fun. No baby seals will be harmed. :)
This is why you use loops. (And try not to use goto for this).
#include <stdio.h>
#include <math.h>
int main() {
float firstnum, secondnum, answer;
char function, buffer[2];
while(1) {
printf("\nHello and welcome to my calculator!\n");
printf("\nPlease input the function you would like to use. These include +, -, *, /.\n");
scanf("%s", &buffer);
function = buffer[0];
printf("\nNow please input the two variables.\n");
scanf("%f", &firstnum);
scanf("%f", &secondnum);
if (function == '+') answer = firstnum+secondnum;
else if (function == '-') answer = firstnum-secondnum;
else if (function == '*') answer = firstnum*secondnum;
else if (function == '/') answer = firstnum/secondnum;
else printf("Sorry that was an incorrect function. The correct inputs are +, -, *, /.");
printf("Your answer is %f \n", answer);
}
return 0;
}
This should go in an infinite loop, so use an input from the user to break; the loop to exit the program
Note : I have replaced the scanf %c with %s indicating an input of a string & used a buffer.
scanf("%s",&buffer); function = buffer[0];
(Updated as per discussion in comments)
One "best practise" regarding scanf is to check it's return value. In regards to the return value of scanf, I suggest reading this scanf manual carefully and answering the following questions:
int x = scanf("%d", &foo); What do you suppose x will be if I enter "fubar\n" as input?
Where do you suppose the 'f' from "fubar\n" will go?
If it remains in stdin, would you expect a second scanf("%d", &foo); to be successful?
int x = scanf("%d", &foo); What do you suppose x will be if I run this code on Windows and press CTRL+Z to send EOF to stdin?
Would it be safe to use foo if x is less than 1? Why not?
int x = scanf("%d %d", &foo, &bar); What would you expect x to be if I enter "123 456\n" as input?
Do you suppose the '\n' will still be on stdin? What value would char_variable hold following scanf("%c", &char_variable);?
EOF can be sent through stdin in Windows by CTRL+Z, and in Linux and friends by CTRL+D, in addition to using pipes and redirection to redirect input from other programs and files.
By using code like int function; for (function = getchar(); function >= 0 && isspace(function); function = getchar()); assert(function >= 0); or char function; assert(scanf("%*[ \n]%c", &function) == 1); you can discard leading whitespace before assigning to function.

Resources