In the following code
scanf("%s", input);
sscanf(input," %s %f ", change, &grades);
printf("%s\n", change);
printf("%f", grades);
grades will be printed as 0.00, no matter the input. Why doesn't sscanf recognise float format?
The first call to scanf is looking for a sequence of characters delimited by whitespace. If your input looks something like this:
test 98.3
Then input will only contain the string test.
If you want to read a full line of text so you can later parse it with sscanf, use fgets instead which will read a line:
char input[100];
char change[10];
float grades;
fgets(input, 100, stdin);
sscanf(input," %s %f ", change, &grades);
printf("%s\n", change);
printf("%f", grades);
Input:
test 96.5
Output:
test
96.500000
scanf("%s", str) reads from stdin upto a newline or whitespace that mean you are reading input as change78.12 here change is change string value and 78.12 is float grade value. when you'll do sscanf(str, "%s %f", change, &grade) since str is valid %s type so it will read by change only so nothing left for grade so it takes default as 0.00 . If you want to read from stdin and then do scanf then do this.
// input format is (separated by whitespace)
// change 78.5
fgets(input, input_length, stdin);
sscanf(input,"%s %f ", change, &grades);
printf("%s\n", change);
printf("%f", grades);
Related
I am having some issues with the scanf function.
I am trying to printf a scanf result, but it only returns 0.00000
Can someone help me? Here is my code done so far:
#include <stdio.h>
int main() {
float grade;
char choise;
do {
printf ("Type your grade: ");
scanf("%f", &grade);
printf("Want to continue? s/n: ");
scanf(" %c", &choise);
printf("%s \n", &choise);
printf("%f", &grade);
}while(choise != 'n');
}
printf("%f", &grade); is wrong
try
printf("%f", grade);
But there are many other issues. At the very least, you must check the values returned by scanf, and you should use int main(void) or int main(int argc, char **argv). eg:
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
float grade;
char choise;
do {
printf("Type your grade: ");
fflush(stdout);
if( scanf("%f", &grade) != 1 ){
fprintf(stderr, "Invalid input\n");
exit(1);
}
printf("Want to continue? s/n: ");
fflush(stdout);
if( scanf(" %c", &choise) != 1 ){
fprintf(stderr, "Invalid input\n");
exit(1);
}
printf("%c\n", choise);
printf("%f\n", grade);
} while( choise != 'n' );
return 0;
}
If you don't check the value returned by scanf, you don't know if any data was written into the variable. Since neither choise nor grade is initialized, attempting to read those values if scanf did not assign to them is undefined behavior. The behavior is also undefined if the input stream contains a value that cannot be represented as a float (eg, if it is a value greater than FLT_MAX), but that's really just an argument for avoiding scanf rather than a suggestion to try to make scanf usable. You can try to use scanf to make a user friendly interface, but it's really not worth the effort. Much better to simply abort on bad input. (If you want a user friendly interface, I would recommend you are using the wrong language.) See http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html for more details on why you really ought to just avoid scanf completely.
These calls of printf
printf("%s \n", &choise);
printf("%f", &grade);
are incorrect.
In the first call you are trying to output a single character as a string. In the second call you are trying to output a pointer of the type float * as an object of the type float.
Instead you have to write
printf("%c\n", choise);
printf("%f\n", grade);
The lines
printf("%s \n", &choise);
printf("%f", &grade);
are wrong.
They should be
printf("%c \n", choise);
printf("%f", grade);
The %s format specifier should only be used for strings (null-terminated sequences of characters), not individual characters. The expression &choice does not point to a string, as the character sequence is not null-terminated.
Also, the %c and %f format specifiers require values, not addresses, when using them with printf. Only when using them with scanf should you pass an address.
Updated
I am having some trouble with Question 2 on Chapter 4 from "A Guide to C Programming" by Paul Kelly.
As far as I can tell, my syntax is correct, however when the program reaches line 36 the program auto fills the scanf(); variable slots.
I can not seem to find a solution to this problem anywhere.
Here is my code. I have put a marker beside line 36
/*
Program to demonstrate single scanf function
to read various data types and output results.
*/
#include <stdio.h>
main(){
int first;
int second, third, fourth;
float principle, rate, time;
char keyVal1, keyVal2;
char c;
int i;
float f;
double d;
printf("\nPlease Enter an Integer\n");
scanf("%d", &first);
printf("\nYou Entered %d\n", first);
printf("\nThank You, Please Enter 3 more integers\n");
scanf("%d %d %d", &second, &third, &fourth);
printf("\nYou Entered %d %d and %d\n", second, third, fourth);
printf("\nGreat,
now please enter decimal values for principle,
rate and time.\n");
scanf("%f %f %f", &principle, &rate, &time);
printf("\nYou Entered %.2f %.2f and %.2f\n", principle, rate, time);
printf("\nPlease Enter any 2 characters\n");
scanf(" %c %c", &keyVal1, &keyVal2);
printf("\nYou Entered %c and %c\n", keyVal1, keyVal2);
// ***36
printf("\nNow Enter any other character,
followed by an integer and 2 decimal numbers\n");***
scanf(" %c %d %f %lf ",&c, &i, &f, &d);
printf("\nYour character was %c.\nYour integer was %d\nYour
decimal numbers were %.2f and %.2lf\n", c, i, f, d);
}
scanf("%1s %1s", &keyVal1, &keyVal2);
Use %c specifier instead of %1s .
scanf(" %c %c", &keyVal1, &keyVal2);
Similarly ,
scanf("%c %d %f %lf ",&c, &i, &f, &d);
leave a space before %c -
scanf(" %c %d %f %lf ",&c, &i, &f, &d);
You need to leave space because as ENTER is pressed after previous scanf '\n' remains in stdin .
scanf("%1s %1s", &keyVal1, &keyVal2);
it should be...
scanf(" %c %c", &keyVal1, &keyval2);
you need to use the c identifier, that will end the crashing, now after you do that you'll notice that the first character doesn't seem to be read in. This is because you have a printf() right before, so your scanf() will read in the last char in the printf() which was the \n character. We have to fix this by putting a space before the identifier, so it won't read in the last value in stdin.
Also you need to change the printf() statements to the same identifiers otherwise an 'undefined action will occur'.
Also, the last scanf() change it to this...
scanf(" %c %d %f %lf",&c, &i, &f, &d);
By taking out the space in after the last identifier, the program works well.
the problem is with this line:
scanf(" %c %d %f %lf ",&c, &i, &f, &d);
the space at the end of the format string means that all 'white space' is consumed until a non-white space character is encountered in the input stream.
so the scanf() never completes until a non white space character is entered by the user, after entering the 4 requested values.
To fix the problem, remove the trailing space in the format string.
scanf(" %c %d %f %lf",&c, &i, &f, &d);
This code works well for words with less than five letters: (but not for higher)
#include <stdio.h>
int main(void)
{
const int size = 5;
char str1[size], str2[size], str3[size];
printf("Type word1: ");
scanf("%s", str1);
printf("Type word2: ");
scanf(" %s", str2);
printf("Type word3: ");
scanf(" %s", str3);
printf("First chars: '%c', '%c' e '%c'.\n", str1[0], str2[0], str3[0]);
return 0;
}
The only way to run correctly would increase the 'size' variable? I wonder if it is possible to work properly with larger words without necessarily increasing the 'size' variable.
This will get you close
Just save 1st char
#include <stdio.h>
int main(void)
{
char str[3];
printf("Type word1: ");
scanf(" %c%*s", &str[0]);
printf("Type word2: ");
scanf(" %c%*s", &str[1]);
printf("Type word3: ");
scanf(" %c%*s", &str[2]);
printf("First chars: '%c', '%c' e '%c'.\n", str[0], str[1], str[2]);
return 0;
}
regarding this kind of line: 'scanf("%s", str1);'
1) the scanf format string needs to limit the number of characters input,
otherwise (in this case)
inputting a word longer than 4 char will result in a buffer overrun
2) always check the returned value from scanf
to assure the input/conversion operation was successful.
3) I would strongly suggest using fgets() and sscanf()
then
--the max number of characters is limited by a fgets() parameter,
--the string is null terminated,
--the newline is part of the string,
so will need to be overlayed with '\0'
4) in the user prompts,
I would use:
printf( "\nUsing %d or less characters, enter a string:", argv[1] );
where argv[1] is a command line parameter that indicates the max string length.
(be sure to allow for the nul terminator byte)
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.
printf is ouput is being destyoryed by a "\n" after I run scanf. I am attempting to use.
scanf ("%*c");
to chomp the "\n" but its not working... here is the code
printf("Enter char float int char:", char4, deci2, num2, char5);
scanf ("%c %f %d %c", &char4, &deci2, &num2, &char5);
scanf ("%*c");
printf("You entered: '%c' %.3f %d '%c' " ,char4 ,deci2, num2, char5 );
and it outputs to
Enter char int char float:a 5 a 5.5
You entered: 'a' 5 'a' 5.500
Enter char float int char:a 5.5 6 b
You entered: '
' 0.000 0 ''
The line
scanf ("%c %f %d %c", &char4, &deci2, &num2, &char5);
is picking up the stray newline left in the input buffer from your previous scanf call. You can work around that by putting a space in front of the first %c:
scanf (" %c %f %d %c", &char4, &deci2, &num2, &char5);
This will tell scanf to skip over any leading whitespace (blanks, newlines, tabs, etc.) before reading the next non-whitespace character.
The line
printf("Enter char float int char:", char4, deci2, num2, char5);
is a bit of a head-scratcher; it won't cause any problems (the excess arguments are evaluated, but otherwise ignored), but it looks wrong, and indicates some confusion.
In this line:
printf("Enter char float int char:", char4, deci2, num2, char5);
remove the char4, deci2, num2, and char5. If you're still seeing issues as Carl Norum suggests, then try consuming the newline character left over from your first scanf as such:
scanf ("%c %f %d %c", &char4, &deci2, &num2, &char5);
getchar();
printf("You entered: '%c' %.3f %d '%c' " ,char4 ,deci2, num2, char5 );
It's the remaining \n in the buffer from your first read that's still hanging around. You need to eat that one before doing the second scanf, not after.
Editorial note: You should really include all of the relevant code in your question rather than just a subset. I could only infer this to be your problem from the output you provided. It contains the string Enter char int char float which isn't present in your example code.