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);
Related
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 3 years ago.
So I'm learning how to use the while and for loops in C but this code won't seem to work. the scanf statement seems to be getting ignored and the loop just repeats itself without requiring me to input 'Y' for it to repeat. Here's the code:
void showCommission();
void main() {
char keepGoing='y';
while(keepGoing=='y') {
showCommission();
printf("Do you want to calculate another?\n");
scanf("%c",&keepGoing);
}
}
void showCommission() {
float sales,commission;
const float COM_RATE=0.10;
printf("Enter the amount of sales\n");
scanf("%f",&sales);
commission=sales*COM_RATE;
printf("The commission is $%f.\n",commission);
}
Here's what running the code gives me:
Enter the amount of sales
5000
The commission is $500.000000.
Do you want to calclulate another?
...Program finished with exit code 10
Press ENTER to exit console.
it never prompts me to enter y and the code just exits for some reason.
The problem you're encountering is that the call to scanf to read in a value using the %c format will accept a newline character as valid input!
This, combined with the fact that the scanf("%f",&sales); call reads in a float value but does not 'consume' the following newline, will leave that newline character in the input buffer, for the subsequent call to read a value for keepGoing. Thus, you will have a value for keepGoing that is not y and the program will terminate.
There are several ways around this. The simplest, perhaps, is to add a space character before the %c field, which will instruct the scanf function to skip all 'whitespace' characters (which includes the newline) when 'scanning' for the input character:
scanf(" %c", &keepGoing); // Added space before %c will skip any 'leftover' newline!
You've got a few problems. First, you need to check your scanf return values; if stdin is closed without providing y, scanf will constantly return -1 without rewriting keepGoing (making the loop infinite).
The other problem is early exit; %c suppresses the normal scanf whitespace skipping behavior, so your scanf's in main are always trying to read whatever followed the float you just parsed to populate sales (usually whitespace or a newline of some sort), so when you enter:
1.12
y
the %c reads the newline after the 2, not the y, and the loop exits immediately.
A simple fix would be to change:
scanf("%c",&keepGoing);
to:
if (scanf(" %c", &keepGoing) != 1) break;
The leading space will reenable whitespace skipping so it consumes all whitespace before it tries to read the next character, and whenever it fails to read a character at all, it will end the loop, rather than running forever. A similar check should probably be added for your other scanf.
This is due to the newline (enter keystroke) leftover from non-chars input.
scanf("%f",&sales);
For example, if i enter 500 for the amount of sales, the program will read 500\n, where the \n is your enter keystroke. However, scanf("%f",&sales) will only read float value. Therefore the \n is leftover in your input buffer. Then, when the program try to run scanf("%c",&keepGoing), it consume the leftover \n and it will treat as you pressed enter keystroke and skipped the input.
The issue can be fixed by consuming the leftover \n.
void showCommission() {
float sales,commission;
char consumeNewLine;
const float COM_RATE=0.10;
printf("Enter the amount of sales\n");
scanf("%f",&sales);
scanf("%c",&consumeNewLine);
commission=sales*COM_RATE;
printf("The commission is $%f.\n",commission);
}
This is a menu driven program asking for user's choice.
Why are if conditions not executed?
Output is attached.
Creating a program asking for user's input:
void main()
{
float a,b,ans=0;char ch,choice;
choice='y';
while(choice=='Y'||choice=='y')
{
printf("Enter two numbers \n");
scanf("%f %f",&a,&b);
printf("1.+for Addition\n");
printf("2.-for subtraction \n");
printf("3.*for multiplication \n ");
printf("4./for Division \n");
printf("Enter your choice of operation \n");
scanf("%c",&ch);
if(ch=='+')
ans=a+b;
else if (ch=='-')
ans=a-b;
else if(ch=='*')
ans=a*b;
else if(ch=='/')
ans=a/b;
else
{
printf("wrong choice entered\n");
}
printf("Answer is %f \n",ans);
printf("Do you want to coninue (Y/N)\n");
scanf("%c",&choice);
}
printf("program Terminated\n");
}
Output:
/* Enter two numbers
1010
22
1.+for Addition
2.-for subtraction
3.*for multiplication
4./for Division
Enter your choice of operation
wrong choice entered
Answer is 0.000000
Do you want to coninue (Y/N)
n
program Terminated
*/
The above is the output screen.
It doesn't perform operations.
When you input first 2 numbers, they are placed into variables a and b. BUT after entering those 2 numbers, you pressed enter. Computer sees that as new input and place it in first next appropriate variable that requires input. In this case it's your variable ch, and instead of +,-./ or *, ch has value of "new line". If you try to write value of ch on standard output as an integer, it will write number 10. It's ASCII character of new line. Simply adding getchar() after inputting first 2 numbers will collect that new line sign, and your next scanf will work properly.
By the way, you have same problem with your last input scanf("%c",&choice); because pressing enter after previous operation decision, will also cause your program not to work properly. Do the same thing for this part, or simply leave blank character before %c.
Try the following
scanf(" %c",&ch);
^^
and
scanf(" %c",&ch);
^^
Otherwise a next character is read that can be a white space character.
Take into account that according to the C Standard function main without parameters shall be declared like
int main( void )
scanf() does not consume trailing newlines. The skipped scanf() receives the newline from the previous line typed by the user and terminates without receiving more input as you would expect...
scanf() is a bit cumbersome with newlines. A possible solution would be to use fgets() to get a line from the console and then employ sscanf() to parse the received string.
Another, more targeted, solution would be to use " %c" in the format string of the last scanf() call. The %c format specifier does not consume leading whitespace on its own, which is why it gets the remaining newline, rather than a character typed by the user.
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);
This question already has an answer here:
Does scanf() take '\n' as input leftover from previous scanf()?
(1 answer)
Closed 9 years ago.
Im trying to make a basic C console application calculator. Yet when i execute it the second scanf command is skipped and the third is run instead. This is a problem as here i need to get operation of the user +, -, *, or /. How do i stop this from happening?
float num1;
char sign;
float num2;
float total;
printf("~~~ Calculator ~~~\n");
printf("Please enter the first number: ");
scanf("%f", &num1);//Get value of num1 from user
printf("\nNow please enter the operation , either +, -, *, or / : ");
scanf("%c", &sign);//Get value of sign from user
printf("\n\nFinaly enter the second number: ");
scanf("%f", &num2);
Edit: Actually after trying various suggestions it seams a space before the %c was the correct way and cleanest way of fixing things. Thanks for the help.
Put a blank character before %c so it will consume the new line character like this:
scanf(" %c", &sign);//Get value of sign from user
After you hit enter, the first scanf consumes the actual number and leaves the \n. The latter is consumed in the next scanf.
scanf("%f\n", &order)
Do that in order to consume the \n you are entering.
As #JonathanLeffler mentioned, it's better approach to use " %c" (Note the space) in the next line in order to consume the newline character.
After the program asking for the first number you enter a number the you hit return. So the the number is stored in the variable num1. But the new line character '\n' still in the buffer you need to clear the buffer before the second scanf is executed Otherwise the signe variable will accept that '\n' as an input because it's a character and it will not prompt for an input.
You should always clear the buffer before asking to input a char
int c;
do {
c = getchar(); // clearing the buffer
} while (c!='\n' && c!=EOF);
printf("\nNow please enter the operation , either +, -, *, or / : ");
scanf("%c", &sign);//Get value of sign from user
Now it shouold work
Actually, this happens because there is still a value in the stdin stream of the program.
An easy solution would be using:
fix: DON'T USE -> fflush(stdin);
Consume the newline char by using scanf("%f\n")...
before the second call to scanf...
Best!
I've put together a simple currency converter program from code I've edited from the web and a switch statement that I've put in. When I ran the program in Visual Studio:
printf("Would you like to make another conversion? y/n\n");
fflush(stdin);
scanf("%c",&marker);
would wait for input and then either go back to the start of the while statement or exit the console window. Now if I run this is Xcode on a mac "Would you like to make another conversion..." is printed but doesn't wait for an input, it just goes straight back to the while loop.
Am I putting the printf("Would you like...etc section in the right place? Or is there a better way of getting loops to run again after they take input from a user? Do I need to do anything with a 'bool' statement. We've not got that far in class yet.
Full code is shown below:
#include <stdio.h>
int main ()
{
int choice;
float money;
float total;
char marker='y';
printf("\n\nCURRENCY CONVERSION\n");
printf("***Rates correct as of 26 NOV 12***\n");
printf("------------------------------------\n");
printf("1. Australian Dollar (AUD) 1.533=1 GBP\n");
printf("2. Euro (EUR) 1.235=1 GBP\n");
printf("3. Indian Rupee (INR) 89.494=1 GBP\n");
printf("4. Japanese Yen (JPY) 131.473=1 GBP\n");
printf("5. US Dollar (USD) 1.602=1 GBP\n");
printf("Enter the number for the currency to convert...");
while(marker!='n')
{
printf("\n\nWhat would you like to convert your money to? (1-5): ");
scanf("%d",&choice);
printf("\n\nHow much money do you want to convert? (GBP): ");
scanf("%f",&money);
switch(choice) {
case 1:
total = money * 1.533;
printf("\n\nYou will have %.2f Australian Dollars \n\n", total);
break;
case 2:
total = money * 1.235;
printf("\n\nYou will have %.2f Euros \n\n", total);
break;
case 3:
total = money * 89.494;
printf("\n\nYou will have %.2f Indian Rupees \n\n",total);
break;
case 4:
total = money * 131.473;
printf("\n\nYou will have %.2f Japanese Yen \n\n", total);
break;
case 5:
total = money * 1.602;
printf("\n\nYou will have %.2f US Dollars \n\n", total);
break;
default:
printf("You did not choose a correct option\n");
}
printf("Would you like to make another conversion? y/n\n");
fflush(stdin);
scanf("%c",&marker);
}
return 0;
}
Many thanks for any comments of input received.
Your problem is likely that the scanf("%c", &marker); is reading a newline left over by a previous input.
Note that fflush(stdin) invokes undefined behaviour. The C standard says of fflush():
If stream points to an output stream or an update stream in which the most recent operation was not input, fflush() shall cause any unwritten data for that stream to be written to the file.
If that operation clears the input queue in Visual Studio or on Windows, then you've just learned the hard way that extensions to the standard on one platform do not always work on other platforms. In particular, fflush(stdin) does not clear queued characters waiting to be read.
Note that you could have helped your debugging efforts by printing the erroneous input as part of the error message.
You should also be testing each scanf() call:
if (scanf("%c", &marker) != 1)
...EOF or other problem...
if (scanf("%f", money) != 1)
...EOF or maybe a letter instead of a number...
Stylistically, it is best to include a break; after the code after the default: label in the switch.
Also, you should really avoid repeating the conversion rates in the strings that are printed in the menu and in the case statements. Similarly with currency names. Maybe you haven't covered arrays and structures yet, but in the long term, that is a recipe for problems (if only wasted recompilations because the rates have changed; but allowing them to be read from a file, or a web site, is another major exercise).
This isn't anything to do with the loop. It's about your calls to scanf.
What's happening is that stdin is buffered. scanf will only cause the program to halt and wait for input if there isn't enough pending data in the buffer. When you do this:
scanf("%f", &f);
...then the program will halt until you type a line of text. Say you type:
1\n
The 1 is read into the variable f... but the newline remains in the buffer.
This means that your call to:
scanf("%c", &c);
...will return immediately, because there's enough data in the buffer to complete the call. The program will only stop and wait for more data when it runs out of buffer.
Windows doesn't do buffering like this, which is why you weren't observing the behaviour there.
There are about a million solutions to this, ranging from changing the way stdin is buffered to using a text-based UI library like ncurses. Given that by default stdin is line-buffered --- data is read a line at a time, terminated with newlines --- the simplest is simply to make sure that each call to scanf() consumes a complete line of text. That means that the buffer will be empty each time you call scanf. For example:
scanf("%f\n", &f);
...and:
scanf("%c\n", &c);
BE AWARE that if the user enters input that doesn't match this format string, such as 1 2 for the first or ab for the second, scanf will leave the variable uninitialised. So you absolutely have to check the return parameter.
if (scanf("%f\n", &f") != 1)
error("Oh noes!");
Otherwise your program will go horribly, horribly wrong.
As an aside: you haven't done it in this program, but just so you're aware, scanf("%s") should not be used. For anything.
You can do an infinite loop(eg. while(true){} ), and in your switch statement have a case for choice 'n' that breaks the loop (eg. break;)
Also, case 1 , case 2, etc... I would scan them as chars instead of integers. (eg. case '1':, case '2':, etc...)
I am not sure what I just said is going to work but that is my initial thought. Hope it helps :)
If you don't want to deal with flushing buffers, you can define a char buffer[1024] and use fgets with sscanf:
printf("\n\nWhat would you like to convert your money to? (1-5): ");
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer, "%d", &choice);
and the while loop can include your menu:
while (1) {
printf("\n\nCURRENCY CONVERSION\n");
printf("***Rates correct as of 26 NOV 12***\n");
/* ... */
printf("Would you like to make another conversion? y/n\n");
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer, "%c", &marker);
if (marker == '\n')
break;
}