My C do while loop will not execute - c

My program assignment is to write a looping program that calculates USD to Euros. My code looks like this
#include <stdio.h>
int main(void)
{
double USD, euro;
char again;
do
{
printf("Please enter the amount of USD you want to convert to Euros> ");
scanf_s("%lf", &USD);
euro=USD * 0.73209;
printf("%4.2f USD equals %4.2f Euros.", USD, euro);
printf("Do you want to convert another amount (y/n)?");
scanf_s("%c", &again);
}
while (again == 'y' || again == 'Y');
return 0;
}
And when I run the program, it executes, allows my to enter a USD value, gives me the correct Euro value, then when prompt for y/n it just exits.

As other folks have explained, your problem is due to \n remaining in STDIN.
In order to skip it, just replace
scanf_s("%c", &again);
with
scanf_s(" %c", &again);
This is part of scanf's functionality:
White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.
http://msdn.microsoft.com/en-us/library/kwwtf9ch.aspx
For your first scanf,
scanf(" %lf", &USD);
may also help.

This is because that there are stray \r and or \n left in your input stream (stdin), which is read by scanf and gets out of the do while, replace your scanf_s line with
while((again = getchar()) != '\n' && again != EOF);
if you want to use scanf_s then you can do something like
do {scanf_s("%c", &again);}while(again == '\n' || again == '\r');
For more information about this check http://c-faq.com/stdio/gets_flush2.html

I think you must use strcmp() here.
while ( strcmp(again, 'y') == 0 || strcmp(again, 'Y') == 0 )
I'm about two weeks into learning C so sorry if it doesn't work!

Try this.
#include <stdio.h>
int main(void)
{
double USD, euro;
char again;
do
{
printf("Please enter the amount of USD you want to convert to Euros> ");
scanf_s("%lf", &USD);
getchar();
euro=USD * 0.73209;
printf("%4.2f USD equals %4.2f Euros.", USD, euro);
printf("Do you want to convert another amount (y/n)?");
again = getchar();
}
while (again == 'y' || again == 'Y');
return 0;
}
It is happening because scanf does not takes whitespace characters. like newline, space etc. when you were pressing enter 'USD' was taking the value and 'again' was taking the newline character. Hope this helps. :)

stdin (standard input) has one more character you are missing, right after you ask for the USD amount, that character don't simple goes way, as a matter of fact it's waiting for you to pull it out, and that's what you do with the last scanf. This happens because you told scanf (the first one) to read just a float (double) number and nothing else.
To see what's going on, you could check the value of the variable again as indiv said. Although it's preferable to print the ASCII value instead of the character itself, because you may not be able to really know for sure if it is an space, new line, tab or any other character of this kind.
instead try this:
printf("ASCII: %d, CHAR: %c\n", again, again);
Put that line right after the last scanf.
Either way, your problem is to find a way to discard that last character. One solution could be reading an string from stdin and then using atof() to convert that string into a decimal number.

change
scanf_s("%c", &again);
to
scanf_s("%c", &again, 1);

Related

scanf not working correclty in this c program

I have wrote a small code to get value from Fahrenheit to Celsius. I wanted to keep inputting data until I press any other key than 'y'. But this loop doesn't work that way and stops after one iteration.
#include <stdio.h>
int main()
{
char ch='y';
int far, cen;
do {
printf("again\n");
scanf("%d",&far);
//cen = (5.0/9.0)*(far-32);//integer division will truncate to zero so we can make 5/9 to 5.0 / 9.0
cen = (5*(far-32))/9;//or this way we can use this formula
printf("\n%d\t%d",far, cen);
printf("ch=%c",ch);
scanf("%c",&ch);
}while(ch == 'y');
return 0;
}
What is the problem here?
P.S
I added a line and made a new code like this
#include <stdio.h>
int main()
{
char ch='y';
int far, cen;
do {
printf("again\n");
scanf("%d",&far);//here we press carriage return. this value is in stdin
//cen = (5.0/9.0)*(far-32);//integer division will truncate to zero so we can make 5/9 to 5.0 / 9.0
cen = (5*(far-32))/9;//or this way we can use this formula
printf("\n%d\t%d",far, cen);
scanf("%c",&ch);//putting a space before %c makes the newline to be consumed and now it will work well
if((ch == '\r')|| (ch == '\n'))
printf("1\n");
printf("ch=%c",ch);//this takes the carriage return in stdin buffer
}while(ch == 'y');
return 0;
}
I need to know carriage return here is \r or \n?
When the value for scanf("%d",&far); is entered and press enter, the scanf stores the carriage return in the buffer. When it encounters the second scanf in the code scanf("%c",&ch); it takes the carriage return present in the buffer as the input to 'ch'. So it doesn't wait for the user input.
Please have a look at the post here
As indicated in one of the reply the solution is to put a space in scanf
scanf(" %c",&ch);
You should always check the return value of scanf. Your first use of scanf may fail if the user does not enter a valid integer, in which case, you are using far without initialising it (which is undefined behaviour). scanf returns the number of items that were successfully scanned. If you are requesting scanf to scan one integer, then it should return 1 if it successfully managed to scan an integer.
int scanresult = scanf("%d", &far);
if (scanresult != 1)
{
puts("Invalid input or unexpected end of input");
return 1;
}
In addition, the %c conversion specifier is unique in that it does not cause scanf to gobble up any preceding whitespace unlike the other conversion specifiers. To force scanf to gobble up the whitespace (such as linefeeds, carriage returns, spaces, tabs etc), simply put a space character before the %c, e.g.
scanresult = scanf(" %c", &ch);
For scanf, the space character is actually a directive to parse and skip all whitespace.
This is because of the previous newline character remaining in the buffer. You can simply replace scanf by this line:
while((ch = getchar()) == '\n');
You'll be needing the same technique in combination with ungetc() in many occasions.
Add fflush() function, just above scanf("%c", &ch). Because buffer of CONSOLE INPUT stores characters that not returned to program. Which is ENTER pressed in previous scanf:
#include <stdio.h>
int main() {
char ch='y';
int far, cen;
do {
printf("again\n");
scanf("%d",&far);
//cen = (5.0/9.0)*(far-32);//integer division will truncate to zero so we can make 5/9 to 5.0 / 9.0
cen = (5*(far-32))/9;//or this way we can use this formula
printf("\n%d\t%d",far, cen);
printf("ch=%c",ch);
scanf("%c",&ch); // This scanf will be ignored, because loads last
// character from buffer that can be recognized
// by scanf which is pressed "ENTER" from previous scanf
printf("%d", ch) // Shows 10, which is ASCII code of newline
fflush(stdin); // Clear buffer
scanf("%c",&ch); // Now it will prompt you to type your character.
// printf("%c"ch); //Without fflush, it must show 10, which is \n code
}while(ch == 'y');
return 0;
}
if after Y you press "space" or "return" this is the character you will find in %C

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.

scanf anomaly with %c and %s related behaviour

I need to use scanf to get a character and a string which would store the user's answer. (yes/no)
The code below skips scanf("%c", &elem).
while ( !strcmp ("yes", option))
{
printf("enter the elements \n\n");
elem=getchar();
printf("you have entered %c\n",elem);
enqueue(st, elem);
printf("please enter yes or no ");
scanf("%s[^\n]",option);
}
./out
enter the elements
a
you have entered a
enqueue elem= a
please enter yes or no yes
enter the elements
you have entered
enqueue elem=
You don't have any scanf("%c", &elem) in your code... btw the problem is with the enter for scanf. When you get an input by scanf, an enter character stays in the input buffer which will be read by your getchar() function in the second round. one simple way to solve it is to add a dummy getchar after your scanf line:
while ( !strcmp ("yes",option))
{
printf("enter the elements \n\n");
elem=getchar();
printf("you have entered %c\n",elem);
enqueue(st,elem);
printf("please enter yes or no ");
scanf("%s[^\n]",option);
getchar();
}
You can find more information about how to clear your input buffer here: How to clear input buffer in C?
I can recommend you consider two things:
For getting only a character, I personally found it much more easier to use getch and getche function in Windows, and equivalent of them for GCC-compatible environments. You can find samples of it online or on this line [What is Equivalent to getch() & getche() in Linux?
Always flush the input buffer after you read your input to prevent any similar problems to happen.
The input functions check the input buffer, which you can find at 0xb8000000, and check the first input there. If the buffer is empty, they wait for the user to enter the input, otherwise, they check the first element in the buffer and then examine that to what they expect to read. If they succeed, they read it and remove it from buffer. Otherwise, they fail to give you your input and depending on the function, the result is different.
For Example, consider the following line:
scanf("%d %d %f", &a, &b &c);
and give the input as:
a 2 4
The scanf will return 0, which means it reads zero inputs so 'a', 2, and 4 remains in your buffer. So your buffer looks like: [a, 2, 4]. As a result if you add the following line:
scanf("%c", &ch);
scanf will try to get a character from the buffer, and it reads character 'a' and put it in variable ch. So it doesn't get any input from user. And you end up with having 2 and 4 on your buffer again.
When you are pressing Enter/Return key to enter the element then a \n character is also passed to the buffer along with the element. This \n is read by your getchar on next call.
To consume this \n place this line after the getchar();
int ch;
while((ch = getchar()) != EOF && ch != '\n');
Take care mixing scanf() format specifiers "%c", "%s" and "%[]".
Correct usage of "%[^\n]": there is no s. If leading whitespace in not wanted to be saved, include a leading space as in " %[^\n]"
char option[100];
// scanf("%s[^\n]", option);
scanf(" %[^\n]", option);
// or better
scanf(" %99[^\n]", option);
// or pedantic
switch (scanf(" %99[^\n]", option)) {
case EOF: HandleEOForIOError(); break;
case 0: HandleNoData(); break; // might not be possible here.
case 1: HandleSuccess();
Correct usage of "%c". If leading whitespace in not wanted to be save, include a leading space as in " %c". This may be the case in OP's code so the preceding inputs Enter or '\n' is consumed.
char elem;
scanf(" %c", &elem);
Correct usage of "%s". Leading whitespace is not saved with or without a leading space.
char option[100];
scanf("%99s", option);
// Following works the same.
scanf(" %99s", option);

Broken Do/While Loop

char again;
do {
counter = 0;
while (counter < 3) {
printf("Please enter a number: ");
scanf("%d", &num);
counter++;
sum += num;
}
if (counter == 3) {
printf("Would you like to continue? [Y]Yes [N]No:");
scanf("%c", &again);
}
}while (again == 'Y');
I can't seem to figure out why this won't work. If i enter Y it breaks, if I enter N it breaks. I need to loop until the user enters "N" to exit the program and no other letter.
Change the scanf call to:
scanf(" %c", &again);
The trick is in the space before the %c: it instructs the scanf function to ignore any whitespace character before returning your N or Y. Otherwise you will be reading the return carriages from the previous scanf calls.
From man 3p scanf (the POSIX one):
A directive composed of one or more white-space characters shall be executed by reading input until no more valid input can be read, or up to the
first byte which is not a white-space character, which remains unread.
That is a complex function. I recommend reading the man page with care: it can do much more than most people think.
The problem is that the scanf("%c", &again) reads the newline after the last number, which is why the loop always breaks. It's also why people shun scanf() in favour of fgets() plus sscanf(); you tend to get better diagnostics and fewer nasty gotchas like this.
How could you have debugged this for yourself?
You could have printed the data that is read as it is read — add:
printf("Read: %d\n", again);
after the scanf(). Also, you should be checking each scanf() call to ensure you are getting the data you expect:
if (scanf("%c", &again) != 1)
...oops — error handling...

C code hangs during operation

I'm just starting to learn the C programming language. I've written this simple piece of code that converts the USD to Euros. Only problem is that once the input of the USD is entered, the program just hangs. I'm using a while loop to ask the user whether or not they want to redo the operation, so my guess is that the syntax of the code is causing an eternal loop, but I'm not for sure.
Here's my code:
#include<stdio.h>
#define conv 0.787033 //conversion factor of USD to Euro found www.ex.com//
int main(void)
{
float USD, EURO;
char cont = 'y';
while (cont == 'Y' || cont == 'y')
{
printf("Please enter the amount of United States ");
printf("Dollars you wish to convert to Euros\n");
scanf("%f\n", &USD);
EURO = USD * conv;
printf("%.2f dollars is %.2f Euros\n", USD, EURO);
printf("Do you wish to convert another dollar amount (Y/N)?\n");
scanf("%c\n", &cont);
}
return(0);
}
remove the \n from your scanf
EDIT:
The above change should not work.
When reading input using scanf, the input is read after the return key is pressed but the newline generated by the return key is not consumed by scanf, which means the next time you read from standard input there will be a newline ready to be read.
One way to avoid is to use fgets to read the input as a string and then extract what you want using sscanf.
Another way to consume the newline would be to scanf("%c%*c",&cont);. The %*c will read the newline from the buffer and discard it.
C faq on problems with scanf
the \n inside scanf require the user to press another extra "ENTER" (Line Feed) in order to continue. Remove it or you press Enter a few time, it will continue
Avoid scanf()
It's best to use fgets(3) and then sscanf(3) because it is invariably the case that an interactive program knows when a line of input is expected.
So, the usual sane-scanf design pattern does make the program a bit more complex but will also make it more flexible and more predictable, try something like changing...
scanf(...)
to
char space[100];
fgets(space, sizeof space, stdin);
sscanf(space, " %f", &USD);

Resources