When running this little C script using Xcode, I get this message:
Format specifies type 'float *' but the argument has type 'double" at scanf("%f", v) and scanf("%f", i).
I don't get it, since I have not declared any double type variables.
int main(int argc, const char * argv[]) {
char choice[10];
float v;
float i;
float r;
printf("What would you like to calculate?: ");
scanf("%s", choice);
printf("\nYou chose: \n""%s", choice);
if (strcmp(choice, "r") == 0)
{
printf("\nPlease enter voltage (V): \n");
scanf("%f", v);
printf("\nPlease enter current (I): \n");
scanf("%f", i);
r = v/i;
printf("%f", r);
}
}
Any ideas?
You're getting that warning because you failed to pass a pointer to a float (float*) to the function scanf. The compiler tells you that it's a double because scanf is a variadic function. Variadic parameters are subject to default argument promotion, where arguments of certain data types are converted to larger data types. In this case, float is promoted to double.
The only way for a function in C to modify variables v, i, and choice is to pass them as pointers, so you need to pass pointers to scanf, using the & "address of" operator.
Your code should look like this:
int main(int argc, const char * argv[]) {
char choice[10];
float v;
float i;
float r;
printf("What would you like to calculate?: ");
scanf("%9s", &choice); /* this specifier prevents overruns */
printf("\nYou chose: \n""%s", choice);
if (strcmp(choice, "r") == 0)
{
printf("\nPlease enter voltage (V): \n");
scanf("%f", &v); /* use a pointer to the original memory */
printf("\nPlease enter current (I): \n");
scanf("%f", &i); /* use a pointer to the original memory */
r = v/i;
printf("%f", r);
}
}
Note also that I used the format specifier %9s. That way, if the user inputs more than 9 characters, adjacent memory won't be overwritten. You have to reserve the last element of the array for the null character \0 because strings in C end with \0.
I don't get it since I have not declared any double type variables.
When there is no visible prototype to indicate what type a function expects for a given argument, or when that argument is among a set of variadic arguments, then default argument promotion is performed on that argument. This provides for compatibility with pre-ANSI C code that assumed such promotions were performed on all arguments.
In this case, scanf() is variadic, with this prototype:
int scanf(const char *fmt, ...);
so everything but the format is subject to default argument promotion. For arguments of type float, that is a promotion to double, and that's where your double comes from.
Of course, as other answers describe, you shouldn't be passing the float at all, but rather a pointer to it.
You have to use the & operator. For example replace scanf("%f", v); with scanf("%f", &v);. This will pass the address of the variable (instead of the value) to scanf().
You have to write scanf("%f", &i); e.t.c, as you want the variable to be passed as a pointer as C has no reference type like C++
Related
I read the following codes:
//talkback.c -- nosy, informative program
#include <stdio.h>
#include <string.h> //for strlen() prototype
#define DENSITY 62.4 //human density in lbs per cu ft
int main() {
float weight, volume;
int size, letters;
char name[40]; //name is an array of 40 characters
printf("Hi! What's your first name?\n");
scanf("%s", name);
printf("%s, what's your weight in pounds?\n", name);
scanf("%f", &weight);
size = sizeof name;
letters = strlen(name);
volume = weight / DENSITY;
printf("Well, %s, your volumn is %2.2f cubit feet.\n", name, volume);
printf("Also, your first name has %d letters, \n", letters);
printf("and we have %d bytes to store it.\n", size);
}
Run it and output:
In [13]: !./a.out
Hi! What's your first name?
Hery
Hery, what's your weight in pounds?
100
Well, Hery, your volumn is 1.60 cubit feet.
Also, your first name has 4 letters,
and we have 40 bytes to store it.
I noticed that scanf("%s", name); and scanf("%f", &weight); , the second has a prefix & ahead of weight.
How could I distinguish which situation to add the prefix or not?
scanf() stands for scan formatted string. Now while scanning input from a standard input stream, scanf() needs to put that input data into somewhere. To store the formatted input data, scanf() needs to know the memory location of a variable of the same data type.
That is why scanf() needs a pointer (a pointer in C stores memory location of a variable or an expression) to store input. The address-of operator (&) preceeding a variable i.e. &var Indicates the memory location of variable 'var'.
int var;
scanf("%d",&var);
char str[20];
scanf("%s",str);
For the second example, we do not need the address-of operator because C treats array name variable as a pointer.
printf() is the reverse function of scanf(). It prints the formatted string to the standard output. Printf doesn't need any memory location to print the output, it only needs the variable to get the data and formats it according to the format specifier.
printf("%c in ASCII is %d",65,65);
The output will be: A in ASCII is 65
Because when you are accepting strings(ie; character arrays) you don't need & in front of the variable name. This is because, scanf() expects address of the variable. For normal variables the variable name represents its value, whereas the for an array the array name is a pointer pointing to the first element of the array. So when you say weight the address of the first element in the array gets substituted and you don't need to use &.
I recommend to start from scanf c rerefence and pay attention to type. E.g. %f means type of argument float* - pointer to float. So you can use only pointer, i.e. address, and there are several way to provide address:
if you have just variable (float a;) you should use & operator applied for variable name;
if you have pointer (float * ptr; or float arr[10];) you can use ptr, or arr, or (arr+4), etc. (all of this have type float *), as well as you can use &arr[4] (here arr[4] is of type float, but &arr[4] is of type float *)
Note: before using float * ptr; in scanf pointer should be initialized with valid address, e.g. ptr = (float*)malloc(sizeof(float));
How about a simply example "when to add prefix &"?
scanf("%f", ...) expects a a following float *.
With float weight, weight is not a float *, but &weight is a float *.
float weight;
scanf("%f", &weight); // & needed
With float *p, p is a float *.
float weight;
float *p = &weight
scanf("%f", p); // no &
Tip: insure your compiler has all its warnings are enabled. A well enabled compiler will report a scanf() specifier and argument mis-match.
//o/p when i/p is 16 and 2 is 4 and if variable is int then o/p will be 20;
#define SETBIT(A,B) A|1<<B
int main(){
char n,pos;
printf("Enter a value");
scanf("%d",&n);
printf("Enter position");
scanf("%d",&pos);
printf("Value after setting %d",SETBIT(n,pos));
}
For the *scanf functions, the d conversion specifier expects its corresponding parameter to have type int *; if that's not the case, then the behavior is undefined, and pretty much any result is possible.
If you want to use char for pos and n, then you must use %hhd instead of %d in the scanf call.
I was trying c code to add but my program doesn't execute, codeblocks unfortunately closes. What is the error?
void main()
{
float a,b;
printf("%30sAddition Of Numbers\n");
printf("\nEnter Number 1: ");
scanf("%f",&a);
printf("\nEnter Number 2: ");
scanf("%f",&b);
printf("\nThe addition of %0.3f and %0.3f is %0.3f",a,b,(a+b));
}
I want to put the result of addition directly in printf statement with float inputs but I am not getting it working.
I also tried putting the result in variable a but it didn't work either.
void main()
{
float a,b;
printf("%30sAddition Of Numbers\n");
printf("\nEnter Number 1: ");
scanf("%f",&a);
printf("\nEnter Number 2: ");
scanf("%f",&b);
a=a+b;
printf("\nThe addition of %0.3f and %0.3f is %0.3f",a,b,a);
}
where am I going wrong?
The problem is in the following statement
printf("%30sAddition Of Numbers\n");
here, the format string supplied to the printf() conatins %30s (or, %s, in general) which is a format specifier (conversion specifier), and you did not supply any argument to it. It invokes undefined behavior.
To quote C11 standard, chapter ยง7.21.6.1
[...] If there are insufficient arguments for the format, the behavior is
undefined. [...]
You can also check the man page to find out more about the format specifiers.
EDIT:
As discussed in the below comments, if you want some spaces to appear before the output, change
printf("\t\tAddition Of Numbers\n");
That said,
void main() should be int main (void), at least, to conform to the standards.
You should always check the return value of scanf() to ensure the successful scanning.
The "%30sAddition Of Numbers\n" issue in your post has been addressed by two good answers (at the time of this post). But you asked a question in comments that may not have been answered completely:
works with %30s when i use all integer numbers and not float! how do i make it work with floats.
A generic answer to that question:
The format specifier you use in scanf(): "%f",&a could result in undesirable results if scanning in unexpected newlines, spaces or other white space. This can be addressed by modifying the format specifier string to suppress these characters. Here is a suggestion:
char* fmt = "%[^\n]%*c";//This generic format specifier, can be used for both integer
//and floating point inputs when used in conjuction
//with strtod() or strtol() (see below)
scanf(fmt, input);
Explanation of "%[^\n]%*c".
When a user is asked to enter a generic number, it might be a float or an integer. You can accommodate that by creating methods for both, and being specific about what kind of value you would like to process:
float get_float(void)
{
char input[80];
char **dummy={0};
char* fmt = "%[^\n]%*c";
printf("Enter floating point number and hit return:\n");
scanf(fmt, input);
return strtod(input, dummy);
}
long get_int(void)
{
char input[80];
char **dummy={0};
char* fmt = "%[^\n]%*c";
printf("Enter integer number and hit return:\n");
scanf(fmt, input);
return strtol(input, dummy, 10);
}
Called like this:
int main(void)
{
long integer_var = get_int();
float float_var = get_float();
float sum = (float)integer_var + float_var;
return 0;
}
Try adding getch(); function at the bottom before closing curly brackets,
like this
void main()
{
float a,b;
printf("%30sAddition Of Numbers\n");
printf("\nEnter Number 1: ");
scanf("%f",&a);
printf("\nEnter Number 2: ");
scanf("%f",&b);
a=a+b;
printf("\nThe addition of %0.3f and %0.3f is %0.3f",a,b,a);
getch();//it will hold your output screen so you can see the output
}
In this line
printf("%30sAddition Of Numbers\n");
you did not supply a string argument for the %s format. This causes undefined behaviour.
If you want the output spaced, you could try a small modification
printf("%30s\n", "Addition Of Numbers");
in this case you are supplying a string literal to satisfy the %s format.
Additionally you must always check the return value from scanf to see that it did convert the number of arguments it was supposed to. It's a basic newbie error not to, and the root cause of hundreds of SO questions.
Creating a code that prints out Body Mass Index
printf("What is your height in inches?\n");
scanf("%d", height);
printf("What is your weight in pounds?\n");
scanf("%d", weight);
I have height and weight as initialized as int height, int weight, but the program is not letting me run it because it says the format is type int* on both scanf lines. What am I doing wrong to get this program to run?
scanf requires the format (your "%d") and also a memory address of the variable where it should put the value that was read. height and weight are int, not the memory address of an int (this is what int * type 'says': a pointer to a memory address of an int). You should use the operator & to pass the memory address to scanf.
Your code should be:
printf("What is your height in inches?\n");
scanf("%d", &height);
printf("What is your weight in pounds?\n");
scanf("%d", &weight);
Update: As The Paramagnetic Croissant pointed out, reference is not the correct term.So I changed it to memory address.
taking into account what the other users have said, try something like this;
int height; <---- declaring your variables
int weight;
float bmi; <---- bmi is a float because it has decimal values
printf("What is your height in inches?\n");
scanf("%d", &height); <----- don't forget to have '&' before variable you are storing the value in
printf("What is your weight in pounds?\n");
scanf("%d", &weight);
bmi = (weight / pow(height, 2)) * 703; <---- the math for calculating BMI
printf("The BMI is %f\n", bmi);
(for this you will need to include the math.h library.)
scanf reads characters from the standard input, interprets them according to the format specifiers here "%d" for integers and stores them in corresponding arguments.
To store them you must specify &variable_name, it will specify the address location where the input should be stored.
Your scanf statement should be:
//For storing value of height
scanf(" %d", &height);
//For storing value of weight
scanf(" %d", &weight);
Like others have said, it's because when you have a value that is a primitive (like an int) that is being read with scanf you have to pass the memory address to that primitive value. However, just to add something that has not been mentioned yet, the same is not true for strings.
Example 1. Using with a primitive value
#include <stdio.h>
int main()
{
int primitiveInteger; // integer (i.e. no decimals allowed)
scanf("%i", &primitiveInteger); // notice the address of operator getting the address of the primitiveInteger variable by prepending the variable name with the & (address of) operator.
printf("Your integer is %i", primitiveInteger); simply printing it out here to the stdout stream (most likely your terminal.)
}
Example 2. Not using a primitive value
#include <stdio.h>
int main()
{
char *nonPrimitiveString; // initialize a string variable which is NOT a primitive in C
scanf("%s", nonPrimitiveString); // notice there is no address of operator here
printf("%s\n", nonPrimitiveString); // prints string
}
Hello I'm trying to make simple program that will check if student assessment is greater than 5.50. When I try to enter the var "number in class" I get SEGFAULThere is my code:
#include <stdio.h>
typedef struct student{
char name[100];
int number_in_class;
double assessment;
}student;
int main(void){
student corrective[25];
int i;
for(i = 0; i < 25; i++){
printf("Ime na uchenika:\n");
scanf("%s", corrective[i].name);
printf("Nomer v klas:\n");
scanf("%i", corrective[i].number_in_class);
printf("ocenka:\n");
scanf("%f", corrective[i].assessment);
}
for(i = 0; i < 25; i++){
if(corrective[i].assessment >= 5.50){
printf("Ime: %s\nNomer v klas: %i\nOcenka: %i\n",corrective[i].name, corrective[i].number_in_class ,corrective[i].assessment);
}
}
return 0;
}
Any idea why?
You need to pass the address of the objects to scanf(), not their values
for(i = 0; i < 25; i++){
printf("Ime na uchenika:\n");
scanf("%s", corrective[i].name); // array converted to pointer to 1st element (an address)
printf("Nomer v klas:\n");
scanf("%i", &corrective[i].number_in_class); // use & to pass the address
printf("ocenka:\n");
scanf("%lf", &popravitelni[i].assessment); // same as before
}
As other posters have noted, you need "%lf" for addresses of objects of type double.
Use %lf to read a double object and not %i or%f. For printf, use %f to print a double. Also you need to pass pointers for scanf arguments. Enable all your compiler warnings and fix them.
The parameters to scanf() are incorrect. You have to pass them as pointers.
scanf("%s", corrective[i].name); is correct, because corrective[i].name is an array therefore a pointer by definition, but you cannot do the same with the other primitive data types. Head then with & to get its pointer.
...
scanf("%i", &corrective[i].number_in_class);
...
scanf("%f", &corrective[i].assessment);
In addition you should check the types you are reading as mentioned in ouah's answer.
You are using %i in this statement:
scanf("%i", corrective[i].number_in_class);
while the number_in_class is a double. Use %lf, thats used for double. Also correct %f to %lf in this statement too:
scanf("%f", popravitelni[i].assessment);
Also use &-the address-of operator to pass the address instead of value in the scanf() function.
Corrected Code:
scanf("%lf", &corrective[i].number_in_class);
.
.
scanf("%lf", &popravitelni[i].assessment);