C - scanf didn't stop for user input - c

I want to get the user input for variable L, but the scanf function is not working, and the program will jump and print the next cost statement and exit if I try to input anything.
I am new to C, and hope can get some help here. Thanks. Code below:
#include <stdio.h>
#include <conio.h>
int main()
{
float L = 0; // L is litre
float gallon;
gallon = 3.785 * L;
char x[2] = {'u', 'd'}; // u is unleaded and d is diesel
float cost;
printf("Hello, welcome to PetrolUpHere!!\n");
printf("Would u like unleaded or diesel fuel?");
scanf("%s", &x[2]);
printf("Enter the litre you want to fuel:");
scanf("%.2f", &L); //SCANF NOT WORKING
switch (x[2]) {
case 'u':
cost = 1.98 * gallon;
printf("The cost is :%.2f ", cost);
break;
case 'd':
cost = 1.29*gallon;
printf("The cost is :%.2f ",cost);
break;
}
getch();
return 0;
}

There are a number of problems here:
scanf("%s", &x[2]);
I imagine you wanted to read a string into the variable x. Instead, you're saying "read a string into memory 2 positions past where x points". In this case that memory will be out of bounds. You should do this, since you only care about one character:
char input;
scanf("%c", &input);
Your switch statement is similarly broken; x[2] is again out of bounds. Use input from the above code instead.
As others have pointed out, using %.2f is not what you want to do when reading in L. Use %f instead. Generally you should only do something like that with format specifiers when printing out variables, rather than reading them in. Eventually you won't be using scanf anyway, since it's not a particularly safe way of getting input.
Finally: it seems like your understanding of how C strings work is shaky at best. This is understandable, since this is a fairly confusing topic for anyone who hasn't worked in C before, and especially for novice programmers. Here's one explanation; I'm sure you can find many more, probably better ones if you look.

There are three problems in this much of your code (at least):
char x[2] = {'u', 'd'};//u is unleaded and d is diesel
float cost;
printf("Hello, welcome to PetrolUpHere!!\n");
printf("Would u like unleaded or diesel fuel?");
scanf("%s", &x[2]);
printf("Enter the litre you want to fuel:");
scanf("%.2f", &L); //SCANF NOT WORKING
switch (x[2]) {
x is an array of 2 char which is initialized, but is not a null terminated string.
You use scanf("%s", &x[2]), which is reading a string into data that is not part of the array x.
You then dereference x[2] in the switch statement — again accessing data that is out of bounds.
You don't check either scanf() call to ensure it was able to scan a result.
You don't print what you read immediately after you read it.
The . in the scanf() format is not valid; use "%f" (you probably do not want to use "%2f" as that would limit you to two digits maximum).
You haven't actually said what you entered in response to the 'unleaded or diesel' question.

scanf("%s", &x[2]);
Should be:
scanf("%c", &x[2]);
scanf("%.2f", &L);
Should be:
scanf("%2f", &L);
And you initialized gallon with '0.0',then your output will always be '0.0'.
Hope it works.

Related

C programming scanf assistance

I am attempting to build a form/gpa calculator for class, but when entering the amount of classes using scanf, the output is 6,487,576 regardless of what I enter.
int main()
{
int opt;
int c;
printf("*******************************\n");
printf("** Fanshawe Grade Calculator **\n");
printf("*******************************\n");
printf("Please Choose an Option:\n");
printf("[1] Enter Your Marks\n");
printf("[2] Quit\n");
scanf("%d", &opt);
switch(opt) {
case 1 :
printf("********************************************************\n");
printf("** Enter Your Marks For Your Courses (Up to 10 Only): **\n");
printf("********************************************************\n");
scanf("%i", &c);
printf("You Have Entered %i Classes!\n", &c);
/*int i;
for(i=1;i=c;i++) {
printf("Enter Your Mark for Class #%i\n", &i);
}*/
break;
case 2 :
printf("GoodBye!");
exit(0);
break;
}
return 0;
}
Help please!
When you use %i with scanf(), it can allow you to input hexadecimal and octal numbers as well (this isn't an issue as explained here).
However, you shouldn't use & while using printf() as it'll display the memory location of the variable instead of the value stored in it.
Try this:
case 1 :
printf("********************************************************\n");
printf("** Enter Your Marks For Your Courses (Up to 10 Only): **\n");
printf("********************************************************\n");
scanf("%d", &c);
printf("You Have Entered %d Classes!\n", c);
break;
printf("You Have Entered %i Classes!\n", &c) outputs the address of the variable c (&c takes the address), i.e. it outputs the number of the memory cell. Since you want to pass the value of the variable you should not use the operator of taking address of a variable &.
printf("You Have Entered %i Classes!\n", c);
There are two problems here. First, you need to include the following headers:
#include <stdio.h> // declares functions like printf and scanf
#include <stdlib.h> // declares functions like exit
If you don't include these headers, then the compiler does not know how to execute them or their exact formats. When you attempt to compile, the warnings will not be helpful. There are a few good websites for this; just search something like "c exit()" in Google and it will tell you which headers you need in the future. When I compiled this code, I used gcc main.c -Wall which forces all warnings to be displayed.
Secondly, you use the address of c in both cases. When you go to print the value of c, you are actually printing the address of c, not the value. scanf() takes the address(es) of the variables to store values in, but printf() takes the variables themselves. The code should look more like this:
scanf("%i", &c);
printf("You Have Entered %i Classes!\n", c);
It is also always a good idea to initialize your variables. This way, you know when something is assigned improperly, or not assigned at all. I forgot to assign my variables for a while, and when compiled on another machine, it didn't work. This is because different machines will initialize variables differently. Just change the code to the following:
int opt = 0;
int c = 0;

Scanf won't continue after I seized an input text

so, I am basically building an array of students with their evaluation.
I made a basic struct :
struct Eleve{
char Nom[100];
int Note;
};
struct Eleve *array;
Then asking for how many children I want to input into my array, then loop and asking information for each child. But, when I enter an input into scanf("%s\n", array[i].Nom); the code stop.
int nbEleves;
float total = 0;
printf("Nombre?!\n");
scanf("%d", &nbEleves);
array = malloc(nbEleves * sizeof(struct Eleve));
int i = 0;
while (i < nbEleves) {
printf("Nom? ");
scanf("%s\n", array[i].Nom);
printf("La note? ");
scanf("%d\n", &array[i].Note);
total = total + array[i].Note;
i++;
}
It doesn't even go on the next printf. I don't understand why, because I don't get any build error or execution errors on this line. Eventually I would have looked at the format if by any chance I'd get an error there, but nothing. No errors, just not getting to the next step of the program.
I think my scanf looks right, and I've got no warnings on it. So, what can prevent the code to go further?
The data I entered in Nom is test.
You should not use scanf! This is an age old discussion that use of scanf requires care and is dangerous. Disadvantages of scanf.
Instead use fgets().
Check this answer How to read from stdin with fgets()? or this
Not able to input a string with spaces in a loop in C
But if you still insist on using scanf(), this may be useful:
while(i<nbEleves){
printf("Nom? ");
scanf(" %[^\n]",array[i].Nom);// remove the \n and notice the space before %[^\n]
printf("La note? ");
scanf("%d", &array[i].Note);
total = total + array[i].Note;
i++;
}
Also I suggest that you must free the memory you allocated using free() in order to prevent memory leaks.
free(array);
Remove the \n from scanf("%s\n", array[i].Nom); and scanf("%d\n", &array[i].Note); or press CTRL + D after you inserted the value.

Wrong output in calculating average program

For years, I don't do anything in C and now I can't do simple things, I was accustomed to cin and cout and now Java. I was trying to make a simple program to calculate the average X amount of exams notes. The output are "random numbers" and checking to interrupt the program occurs before entering a note. Why is that?
#include <stdio.h>
int main(void) {
int numeroDeNotas;
float nota = 0.0;
float notaAuxiliar = 0.0;
char continuar;
int media;
do{
printf("Enter the exam grade\n");
scanf("%f", &notaAuxiliar);
nota += (int) notaAuxiliar;
numeroDeNotas++;
printf("Do you want to continue? Enter n if you want to stop\n");
scanf("%c", &continuar);
}while(continuar != 'n');
printf("%d\n\n", nota);
printf("%d\n\n", numeroDeNotas);
media = nota/numeroDeNotas;
printf("Average grade: %d", media);
return 0;
}
nota is a float, but you are using %d format code to print it. %d expects an int; you need %f to print floating point numbers.
C's standard I/O formatting is definitely not typesafe. When you provide a format code, you have to make sure the corresponding argument has the right type. However, if you had compiled with the -Wall option (at least, with gcc or clang), the compiler would have warned you.
Also, scanf("%c", &continuar); reads a single character without skipping whitespace, which will be the character immediately following the number read by scanf("%f", &notaAuxiliar);. That character is most likely a newline. You need to skip whitespace before reading the y or n, so you could use:
scanf(" %c", &continuar);
numeroDeNotas was declared with a variable type - float. So you can't use %d later in your code when writing a printf statement.
numeroDeNotas
variable is declared but no where initialized. and you are incrementing in do while loop.
media = nota/numeroDeNotas;
printf("Average grade: %d", media);
and you are using garbage value to calculate media which is undefined output. initialize numeroDeNotas to zero.

Is there a limit to how many times the scanf function can be used? [duplicate]

This question already has answers here:
Program doesn't wait for user input with scanf("%c",&yn);
(5 answers)
Closed 9 years ago.
In an effort to get back into the flow of C programming, I've been typing up some simple test programs. I've ran into a strange problem with the scanf function. I have 3 in the following code, but only the first 2 are initialized; the third scanf is ignored. Is this normal, or am I doing something wrong? I've been staring at this code for the last half an hour and I can't find any errors.
#include <stdio.h>
int math(int a, int b, char selection) {
int result;
switch (selection) {
case 'a':
result = a + b;
break;
case 's':
result = a - b;
break;
case 'm':
result = a * b;
break;
case 'd':
result = a / b;
break;
}
return result;
}
int main() {
int num1 = 0;
int num2 = 0;
int result = 0;
char selection;
printf("Enter first number: ");
scanf("%i", &num1);
printf("Enter second number: ");
scanf("%i", &num2);
printf("\n[a] Add\n[s] Subtract\n[m] Multiply\n[d] Divide\n\nWhich one: ");
scanf("%c", &selection);
result = math(num1, num2, selection);
printf("%i", result);
return 0;
}
To answer your over all question:
Is there a limit to how many times the scanf function can be used?
No, no there is not.
but that's not what is happening here anyway.
When you do something like this:
printf("Enter second number: ");
scanf("%i", &num2);
You're actually entering two values on stdin, first a number, second an invisible newline character.
you can't see that, but it's there
V
> Enter second number: 3\n
The way scanf() works, it will read and store input from stdin to your variables until they are all filled, then it will leave the rest. In my example 3 got stored to num2 and '\n' is left on stdin Then when this code runs:
scanf("%c", &selection);
It will look on stdin and find the newline character ('\n') sitting there. This can be stored to a character type, so it will fill selection with it.
One way to fix this is to change your code to:
scanf(" %c", &selection);
The space before the % tells scanf to ignore any white space (including newlines) that are at the start of the stdin buffer.
Side note on debugging:
When you think something is going wrong, either use a debugger or print some values to give you confidence and understanding. For example, I would update your code as such:
printf("\n[a] Add\n[s] Subtract\n[m] Multiply\n[d] Divide\n\nWhich one: ");
int ret = scanf("%c", &selection);
printf("Scanf I think failed. Return value is: %d. Selection is: %c (%d)\n",
ret, selection, selection);
You can find the meaning of return values from man pages. In this case the return code here will tell you how many items were successfully matched and assigned. You'd see 1 here, so you know the call worked. Your output would look like:
Scanf I think failed. Return value is: 1. Selection is:
(10)
This tells you that scanf did indeed get something, you don't see a character printed, but the output skipped a line (suspicious) and the ASCII value of what was printed was 1010, looking that up you'll see it's a newline character.

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

Resources