Why does scanf ask for input in the very beginning? - c

I have a very simple program that simply asks for ones weight and converts it to the value of platinum. I am new to C so the mistake could be anywhere. But when I use scanf, it asks for input at the very beginning rather than following the sequence of code:
code:
#include <stdio.h>
int main(void)
{
float weight;
float value;
printf("Are you worth your weight in platinum?\n");
printf("Let's check it out.\n");
printf("Please enter your weight in pounds: ");
scanf("%f", &weight);
printf("%.2f\n", weight);
value = 1700.0 * weight * 14.5833;
printf("Your weight in platinum is worth $%.2f.\n", value);
printf("You are easily worth that! If platinum prices drop,\n");
printf("eat more to maintain your value.\n");
return 0;
}
Output:
123
Are you worth your weight in platinum?
Let's check it out.
Please enter your weight in pounds: 123.00
Your weight in platinum is worth $3049368.00.
You are easily worth that! If platinum prices drop,
eat more to maintain your value.
If you notice in the output the user has to enter input before the first line prints. Why is this?

I tried your program and it worked as you want for me. You might try flushing the stdout buffer before you scan for input.
fflush(stdout); // right before your scanf line.
The OS is free to postpone writing output buffers for efficiency. So, for instance, you write to the disk in blocks instead of one character at a time. fflush forces the buffer to be written. It's "endl" in C++ and fflush is the straight c version. I'm not certain that's what you're seeing.

Related

Having difficulty correctly inputting multiple integers at the same time using scanf()

So I have a coding project where I have to calculate the overall grade of a student in a class where they have 4 quizzes, 2 midterms, and 1 final exam. The quiz and exam are weighted 30% and the midterm 40%. I just help with 2 things:
My code doesn't want to start w/o having 4 individual input numbers (79 80 0 0).
When getting to the exam part of the code, it for some reason bypasses the needed user input and autos it to the 3rd number in the quiz coding.
I'm coding in c programming.
#include <stdio.h>
int main()
{
int testOne, testTwo;
float totTest, percTest, testPoint;
printf("Enter you test grades:\n");
scanf("%d%d\n",&testOne,&testTwo);
totTest=testOne+testTwo;
printf("Your total grade points is: %.1f\n", totTest);
testPoint=200;
percTest=(totTest*.40)/testPoint *100;
printf("Your percentage is %.1f%\n", percTest);
int quizOne, quizTwo, quizThree, quizFour;
float totQuiz, percQuiz, quizPoint;
printf("Enter you quiz grades:\n");
scanf("%d%d%d%d\n", &quizOne, &quizTwo, &quizThree, &quizFour);
totQuiz=quizOne+quizTwo+quizThree+quizFour;
printf("Your total quiz grade is %.1f\n", totQuiz);
quizPoint=400;
percQuiz=(totQuiz*.30)/quizPoint *100;
printf("Your quiz percentage is %.1f%\n", percQuiz);
int examOne, examPoint; <This is the code that automatically messes up>
float percExam, finGrade;
printf("Enter your exam grade\n");
scanf(" %d\n", &examOne);
examPoint=100;
percExam=(examOne*.30)/examPoint *100;
printf("Your final exam grade is %.1f\n", percExam);
finGrade=(percExam+percQuiz+percTest);
printf("Your overall grade is %.1f%\n", finGrade);
return 0;
}
Your problems have nothing to do with the logic of your program, nothing to do with computing grades, and everything to do with: scanf. scanf is simultaneously the most useful-looking, and the most actually useless, function in the C library when it comes to introductory C programming.
Here are three simple rules for using scanf in introductory C programming:
Use only one of the following four input formats: "%d", "%s", "%f", "%lf". If you simply must read individual characters, you can add a fifth: " %c" (but make sure you always use that extra space). Use these in isolation, one at a time, without combining them or adding any other characters.
Always check the return value of scanf. If it does not return 1, print an error message and exit: if(scanf(...) != 1) {printf("input error!\n"); exit(1); }
If you want to do something fancier, that you can't accomplish with the limited number of formats allowed by rule 1, then it's time to learn how to use something better than scanf.
In particular, don't try to read multiple numbers at once using formats like %d%d. And don't use \n in scanf format statements, either — it doesn't do what you think, and it's probably causing you problems.

Simple C program not calculating correctly

So, I'm completely new to programming, and I'm learning to program C. I'm trying to write a simple program in C to calculate commission as follows
#include<stdio.h>
int main()
{
float fRate, fSales_Price, fCost, fCommission;
printf("\nEnter your commission rate: ");
scanf("%.2f",&fRate);
printf("\nEnter the price of the item sold: ");
scanf("%.2f", &fSales_Price);
printf("\nEnter the original cost of the item: ");
scanf("%.2f", &fCost);
fCommission = (fRate / 100) * (fSales_Price - fCost);
printf("\nYour commission is: %.2f", fCommission);
}
Whenever I try to run it, two things happen. First, if I try to enter any decimals into the program, e.g. if I said the rate was 12.5, it immediately skips the other inputs and completes the program, saying commission is 0.00. If I ignore decimals, the program runs fine until the end, when I still get commission as 0.00. Any suggestions?
Your format specifier is wrong, you must use compiler warnings if you do, then you wouldn't be asking this, because that format specifier is invalid, you cannot limit the number of decimal places with scanf() it's been discussed in many questions on SO, more importantly you don't need to, and it wouldn't be meaningful, so just remove the .2 from your format specifier, and instead, check that scanf() succeeded before using the values.
"%.2f" is an illegal format string for scanf, so your code causes undefined behaviour. The correct format string is "%f".
Also you should check the result of scanf. If scanf fails, the bad data is not consumed from the input and so subsequent scanfs fail too (this is why you see the other inputs skipped).
For example:
if ( 1 != scanf("%f", &fRate) )
{
printf("Invalid input for fRate.\n");
exit(EXIT_FAILURE);
}
"%.2f" is not a valid format for scanf. See scanf() manual page for details.
The easiest format to use is "%f".
Also, it's a good practice to check the return value of scanf so you know when the operation was successful.
if ( scanf("%f", &fRate) != 1 )
{
// Error reading the data.
// Deal with the error.
}

Placement of function to restart loop in C

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;
}

C programming elementary problem

#include <stdio.h>
#include <math.h>
int main (void)
{
float inches;
printf("Enter the number of inches\n");
scanf("%f\n",&inches);
float feet;
float cm;
float yards;
float meter;
feet = 12 * inches;
cm = 2.54 * inches;
yards = 36 * inches;
meter = 39.37 * inches;
printf("Amount in feet: %f\n", &feet);
printf("Amount in cm: %f\n", &cm);
printf("Amount in yards: %f\n", &yards);
printf("Amount in meters: %f\n", &meter);
getchar();
return 0;
}
I'm using Dev c++
Is the problem i'm problem I'm working on in C. Basically enter in a number in inches then print amount in cm,yards,meters and feet. This is giving me 0.0000 or something for all of them or actually the time it is up. I can't keep the screen up and I thought that was the purpose of getchar() but I must have been mistaken. Any help is great. Thanks!
EDIT 1
What about as far as keeping dev c++ on the screen instead of closing out after I put stuff in? I am also having to put 2 values in before it returns in anything when the screen pops up? Why??
Two problems:
The usual problem with using scanf(), in that it leaves the newline after the number unread and the following read operation (the getchar() here) reads it.
You shouldn't pass pointers to printf(), but the actual values.
You're trying to print the addresses of your floats as floats, you just want to say this:
printf("Amount in feet: %f\n", feet);
Note the lack of an address (&) operator on feet. You want to apply similar changes to your other printf calls.
With printf, you don't give it the address of the float values, you just give it the values. Remove the &s from the printf calls.
You need the address in scanf because the function modifies the variables that you pass in, but printf just needs the values. As it is, the printf is essentially reinterpreting the pointers as floats, which is why you get the garbage values displayed.
About I can't keep the screen up, it's a common problem to everyone trying to execute a console program in a graphical environment directly from the IDE, in particular Dev-C++. The problem is that there's no console for I/O, then one is provided but just for the time the program is running, and since programs are fast, if you do not add a pause after your last input and output, you won't have the time to read the output.
Many MS Windows Dev-C++ users add an horrorific system("pause"). I always suggest that, if Dev-C++ is not able to provide a console for I/O with the option "keep it opened even after the program ends", then it is better you open a shell (cmd or powershell on windows) and run your program directly from there.
About the input problem, unluckly scanf-ing has several buffering problem since the input that is not recognized for the given format is not discarded and is ready for the next reading. E.g.
scanf("%f", &aFloat);
scanf("%f", &theNextFloat); // in your case you have the extra getchar();
won't stop for the second scanf if you write 1.25 4.5 as first input, since the 4.5 is already available for the next scanf. In your case it was a newline that was left in the buffer and since getchar has found it, it does not need to wait for input. You could use a
while( getchar() != EOF ) ; instead, and then to exit you need to hit Ctrl-D.

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