I'm writing a basic C program that will convert either Celsius or Fahrenheit to the other.
I have a scanf statement where the user enters the temperature they want to convert, and then a printf statement asking for whether that temperature was in c or f.
when I compile, the scanf asking for char c or f is instead grabbing the \n from the previous scanf. according to my debugger.
the code looks like this:
int celcius(void){
double originalTemp = 0;
double newTemp;
char format;
printf ("enter a temperature: ");
scanf ("%lf",&originalTemp); //what is the original temp?
printf ("enter c if in celcius, enter f if in ferenheit: "); //enter c or f
scanf("%c", &format); //why do I need to do this twice??, this one grabs \n
scanf("%c", &format); //this one will pick up c or f
if (format == 'c'){
newTemp = originalTemp*1.8+32;
printf("%.2lf degrees Farenheit\n", newTemp);
} //convert the Celcius to Ferenheit
else if (format == 'f'){
newTemp = (originalTemp-32)/1.8;
printf("%.2lf degrees Celcius\n", newTemp);
} //convert the Ferenheit to Celcuis
else {
printf ("ERROR try again.\n");
} //error if it isn't f or c
return 0;
}
am I missing something? I know thatscanf looks in the input stream for the next char in this case, but why is \n still in the input stream at this point?
and is there a "proper" way to fix this other than get char?
Space in the format string matches whitespace, so you can just match away/skip the cr/lf;
printf ("enter c if in celcius, enter f if in ferenheit: "); //enter c or f
scanf(" %c", &format); // get next non white space character, note the space
if (format == 'c'){
The rule is to write a getchar() after every integer/float/double input if you take char/string inputs later. This getchar() flushes out the \n from the input buffer which is leftover by taking the integer/float/double input.
So just write a getchar(); after scanf ("%lf",&originalTemp); and you'll be fine.
Related
Just started learning C and tried to make a calculator to test myself. I thought it would be a fun challenge to make it so:
the program prints an error message to the user if the input(s) is not a number
the user can input a number again, without shutting down the program
What I've learned in C so far is:
printf, scanf
data types
if statements
loops
functions
My question is, is it possible to accomplish the task with the knowledge mentioned above. If it is, what is that solution? (I've been stuck on this for quite a while now, so I hope me giving up on doing it myself is acceptable). If it's not, what do I need to learn to be able to do it?
Here's my code
#include <stdio.h>
float num1;
float num2;
float answer;
char operation;
int isNumber; //1 means true, 0 means false
char restart;
int main ()
{
printf ("Please enter the first number: ");
isNumber = scanf("%f", &num1);
while (isNumber == 0)
{
printf("Please enter a valid number: ");
isNumber = scanf("%f", &num1);
}
//This just keeps reapeating the printf message.
//Also, I just wrote the code for the first input.
//If it doesn't work for this one, no point in writing it for other inputs.
printf ("Please enter an operation: ");
scanf (" %c", &operation);
printf ("Please enter the second number: ");
scanf ("%f", &num2);
if (operation == '+')
{
answer = num1 + num2;
}
else if (operation == '-')
{
answer = num1 - num2;
}
else if (operation == '*')
{
answer = num1 * num2;
}
else if (operation == '/')
{
while (num2 == 0)
{
printf ("Cannot divide by 0. ");
printf ("Please enter another number\n");
scanf ("%f", &num2);
}
answer = num1 / num2;
}
printf ("\nThe answer is: %f", answer);
printf ("\n\nEnter 1 to do another calculation. Enter anything else to quit: ");
scanf(" %c", &restart);
if(restart == '1')
main();
else
return 0;
}
scanf() only reads input that matches the format specifier (in your case this is %f). Characters that do not match the format specifier causes scanf() to stop scanning and causes scanf() to leave the invalid characters in the stdin buffer.
In your while loop if a invalid character is entered it will get stuck in the stdin buffer. This invalid character will then get read by the next scanf() call in the loop, which will also leave it in the stdin buffer. This will continue, again and again, resulting in an infinite loop.
As you might be able to tell scanf() is a unreliable and quick - yet not very robust way to take input.
To fix it you could use a hacky solution like this:
while ((scanf("%f", &num1)) != 1)
{
printf("Please enter a valid number: ");
int c;
while((c = getchar()) != '\n' && c != EOF);
}
// while loop "eats up" any characters
// that scanf has left in stdin buffer
Instead of scanf() i reccomend you get familiar with a function such as fgets() to take input. Then you can use a function like sscanf() to parse the input to see if it is a float.
As a beginner, while you are learning C, it is fine to use scanf(). But as you delve deeper into C and write more complicated pieces of software you must consider using safer and more robust alternatives to unreliable functions like scanf().
To well handle user input, consider dropping all scanf() calls. To read a line of user input, use fgets().
How to check for non-number inputs
Create a helper function.
Read a line of text into a buffer and parse with sscanf() or strod(). sscanf() is OK and used below. strod() is better, yet some corner cases are beyond what a learner may appreciate.
#define LINE_LENGTH_MAX 400
// Return 1 on success, EOF on end-of-file, 0 on failure
int read_double(double *dest, const char *prompt) {
if (prompt) {
fputs(prompt, stdout);
}
char buffer[LINE_LENGTH_MAX + 1];
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
return EOF;
}
int n = 0;
sscanf(buffer, "%f %n", dest, &n);
if (n == 0) {
// Scanning failed
return 0;
}
if (dest[n]) {
// Yet there was extra junk at the end
return 0;
}
return 1;
}
More advance code would used strtod() and detect lines longer than LINE_LENGTH_MAX.
Writing code to accept user input such as P0 x1 y1 to store in a nested structure as a point, and the same with two other points. However when inputting with scanf() and checking printf(), I am not getting the right numbers, like scanf() is reading something else, advice would be great, thanks!
float x, x2, y, y2;
char Q, input;
nested triangle;
scanf("%c", &input);
if (input == 'Q' || input =='q')
return;
else
{
scanf(" %c %f%f",&input, &triangle.P0.x, &triangle.P0.y);
printf("points are\n%f \n%f \n", triangle.P0.x, triangle.P0.y);
}
scanf("%c", &input);
if (input == 'Q' || input =='q')
return;
else
{
scanf(" %c %f%f",&input, &triangle.P1.x, &triangle.P1.y);
printf("points are\n %f \n%f \n",input, triangle.P1.x, triangle.P1.y);
}
If you write scanf("%c", &input);, then this will read in a new line from a previous input into input. This is usually not what you intend.
Therefore, write scanf(" %c", &input); (note the blank before the %c) to skip white spaces.
Note further that %c will just read in one character; if you intend to read in P0, you need a string, e.g. char[3] and format specifier %s.
I'm struggling with what seems a trivial problem in C inputting data from the keyboard, but I'm a C noob (with some background in Java, though)
What I need: I need to type an int value from the keyboard (then press Enter), then I need the user to press Enter only without inputting anything, and then to type another int (and press Enter one more time).
What I can do:
int a = 0;
int b = 0;
scanf("%d", &a);
skip_line_cool_function();
scanf("%d", &b);
printf("You have just entered: &d and &d", a, b);
As you can see, I don't know how to skip the line.
What I have tried: scanf entering a dummy C-string, but, as you know, when you enter nothing, it patiently waits for at least something to be entered.
What I Googled: I suspect that fgets can do the job, but honestly, I didn't understand how to use it in my case.
/* Read first integer */
do {
if(!fgets(buffer, sizeof buffer, stdin)) break;
} while( last_character_of(buffer) != '\n');
/* Read next integer */
If you are this much rigid about the UI that the user will only press a single enter then why not do this?
int a = 0;
int b = 0;
scanf("%d", &a);
getchar(); /* this will get the enter pressed after entering a */
getchar(); /* this will get the enter for the blank line */
scanf("%d", &b);
printf("You have just entered: &d and &b", a, b);
Also the code snippet you've posted will result into compile error. printf() will need integer format specifier %d to work properly. Use this:
printf("You have just entered: %d and %d", a, b);
char c;
int i;
for(i=0;i<5;i++)
{
printf("Enter a character : ");`
scanf("%c",&c);
}
getch();
The above code doesn't work properly.It is getting input for only 3 times. I am not able to find solution for it.Please help with it.Thanks in advance !!
This is because of the new-line character \n left behind by the previous scanf is read by the scanf in the next iteration. Place a space before the %c specifier to consume the \n
scanf(" %c",&c);
^Notice the space
char c is a single character variable.
In your code, your are reading time and time again characters and storing it into c, effectively overwriting it each time. If you would like to input multiple characters, consider using a character array likewise:
#include <stdio.h>
int
main (void)
{
char c[5];
int counter;
for (counter = 0; counter < 5; counter++)
{
printf ("Enter a character: ");
scanf ("%c\n", &c[i]);
}
printf ("The string you input is %s\n", c);
return 0;
}
Suppose you enter a, b and c on the screen then it is actually taking 5 inputs
Input 1: a
Input 2: \n
Input 3: b
Input 4: \n
Input 5: \n
The newline is also taken as input
This question already has answers here:
Simple C scanf does not work? [duplicate]
(5 answers)
Closed 9 years ago.
I have written a simple program to exchange currency and able to buy a beer.
But there something in program and I don't know why, it auto skips the third input data -> end program.
Here my code :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ex_rate_into_vnd = 20000; //! Exchange Rate
int beer = 7000; //! Local price of a beer
float in_c = 0; //! Input amount of money
float out_c = 2; //! Amount of currency to exchange !
float choice; //! Switch mode
char buy; //! Deal or not
//! Introduction
printf ("||---------------------------------------------------||\n");
printf ("|| Currency Exchange Machine beta ||\n");
printf ("||---------------------------------------------------||\n");
printf ("Please choose your option:\n");
printf("\t 1.Exchange VND to dollar\n");
printf("\t 2.Exchange Dollar to VND\n");
do
{
printf("Your choice: ",choice);
scanf("%f",&choice);
} while( choice != 1 && choice != 2);
printf ("Please enter amount of money:");
scanf("%f",&in_c);
if (choice == 1 )
{
out_c = in_c / ex_rate_into_vnd;
printf ("Your amount of money: %.2f",out_c);
}
else
{
out_c = in_c * ex_rate_into_vnd;
printf ("Your amount of money: %.0f",out_c);
}
//! End of Exchanging
printf ("\nWould you like to buy a beer (y/n) ?",buy);
scanf("%c", &buy);
if (buy == 'y')
{
if (out_c >= 7000)
{
out_c = out_c - 7000;
printf("Transactions success !\n");
printf("Your amount: %2.f",out_c);
}
}
printf ("\nWhy Stop ?");
return 0;
}
You have at least one \n between the latest float entry and the char you want to read. You need to get rid of that first.
See also all answers in getchar after scanf category
Change
scanf("%c", &buy);
to
scanf(" %c", &buy);
// ^space
Because the newline character is still in the input buffer after you enter a number and press ENTER in the second scanf.
Instead of scanf("%c", &buy);
1.use space before %c
scanf(" %c",&buy); //space before %c
^
this skips reading of white space (including newlines).
2.or Use getchar(); before scanf("%c", &buy); statement
getchar(); //this hold the newline
scanf("%c", &buy);
3.or use two times getchar();
getchar();
buy=getchar();
//here getchar returns int , it would be better if you declare buy with integer type.
In GCC usage of fflush(stdin); is discouaraged. please avoid using it.
I was wondering why you made 'choice' a float, not an int
Also, consider using a switch-case
that way, you won't have to do the whole do-while loop.
Also, in the line
printf ("\nWould you like to buy a beer (y/n) ?",buy);
Why did u add that?
Here is what I would have done :
printf("Your choice?\n>");
scanf("%d", &choice);
switch(choice)
{
case 1 :
{
out_c = in_c / ex_rate_into_vnd;
printf ("Your amount of money: %.2f",out_c);
}
case 2:
{
out_c = in_c * ex_rate_into_vnd;
printf ("Your amount of money: %.0f",out_c);
}
default :
printf("\nThere has been an error\n"):
reloadprogram(); /* Reloadprogram() is simply to make this go back to the asking thing :) */
}
}
EDIT: also, where it says if( <somevariable> >= 7000), change 7000 to beer, so that way, if u change beer, you won't have to change this :)
Put a fflush(stdin) to clear the input before the last scanf
The program doesn't skip the third input data, it just scans the newline you press after the second input. To fix this, type scanf("%*c%c", &buy); instead of scanf("%c", &buy);. This little %*c scans and ignores the the character read from the input.
you can remove the buy variable from the printf call, it's unneeded
printf ("\nWould you like to buy a beer (y/n) ?",buy);
And replace char buy by char buy[2]; . because a sting is always terminated by /0.
You can also add a memset (buy, 0, sizeof(buy)), to be sure that memory is reset before you start to use it.