I'm preparing for my graduation test and I have some questions regarding the c programming language. I will combine two of these questions which I have answers for, but I don't really understand them. The first question is select the correct expression that outputs the value of the i-th element of the array and these are the possible answers:
(note that the code for both questions is the same)
printf("%f",B[i]);
printf("%f",&B[i]);
printf("%f",B+i);
printf("%p",*(B+i));
printf("%f",*(B+i));
The second question is select the correct expression that inputs the value of the i-th element of the array
scanf("%f", B[i]);
scanf("%f", B+i);
scanf("%p", B+i);
scanf("%f", &B[i]);
scanf("%f", *(B+i));
I tried to compile and run a program that simulates these questions. The scanf part works for the answers 2-5 and all of the printfs print out a zero except the 4th one (of course after input).
float *B;
int n;
B=calloc(n,sizeof(float));
Your understanding of which answers are correct are flawed.
To print a value of type float using printf, you need to use the %f format specifier and pass a value of type float. To read a value of type float with scanf, you also use the %f format specifier but pass a value of type float *.
Regarding array indexing, the notation A[N] is exactly equivalent to *(A + N) and has the type of the array element, and &A[N] is exactly equivalent to A + N and has type pointer to array element.
Based on that, we have the following:
printf("%f",B[i]); // Correct
printf("%f",&B[i]); // Incorrect, passing a float *, expected float
printf("%f",B+i); // Incorrect, passing a float *, expected float (same as prior)
printf("%p",*(B+i)); // Incorrect, %p is used to print a pointer (expects a void *)
printf("%f",*(B+i)); // Correct
scanf("%f", B[i]); // Incorrect, passing a float, expected float *
scanf("%f", B+i); // Correct
scanf("%p", B+i); // Incorrect, %p is used to read a pointer (expects a void *)
scanf("%f", &B[i]); // Correct
scanf("%f", *(B+i)); // Incorrect, passing a float, expected a float *
float
There are 2 ways to printf a float and 1 way to scanf them.
printf("%f", my_float);
printf("%lf", my_float); // works fine but bad style
scanf("%f", &my_float);
(In the oldest C standard, printf didn't allow %lf)
float*
There is one way to printf the pointer itself:
printf("%p", ptr);
It doesn't make sense to read a pointer with scanf, but you can read to the memory pointed-at by the pointer ptr as:
scanf("%f", ptr); // no & needed, it is already a pointer
Everything else from your examples doesn't make much sense. Printing an address is not printing a float. Applying various forms of arithmetic on the pointer such as &B[i] versus *(B+i) have nothing whatsoever to do with the the printing.
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.
I apologies in advance if there is a stupid error in this code, but I can't seem to trouble shoot it. My problem is this, I compile with GCC-8 (installed on Mac via home-brew), then execute in the terminal. When using int do define variables s & a, I get zeros as output using the print statements below. If I declare s & a variables as double I still get zeros for the first two print statements, and 1024 for the last print statement. I'm just lost as to what is going on. Appreciate any help!
/* square code */
#include <stdio.h>
int main() {
int s, a;
printf("enter the length of your square \n");
scanf("%f", &s);
a= s * s;
printf("the area of your square is %f cm using f placeholder \n", a);
printf("the area of your square is %lf cm uning fl placeholder\n", a);
printf("the area of your square is %d cm using d placeholder \n", a);
return(0);
}
int s;
scanf("%f", &s);
If s is an int then you need to scan it in like an int using "%d" instead of "%f". What you are doing is undefined behavior, both in scanf() and printf(). An integer needs to be scanned and printed as an integer.
I think the misunderstanding is that you treat the conversion specifiers %d and %f as defining only the output formatting, regardless of the type of value passed.
Actually each conversion specifier is tightly coupled with a particular type of argument it will accept; For example, %d is defined for integral types only, and all other types like floating point or string used together with %d will yield undefined behaviour (cf, for example, cpp-reference of printf for a more detailed explanation).
So double f=1.2;printf("%d",f) will not format a floating point value 1.2 as integral (someone might expect 1 being the output); It rather yields undefined behaviour, having any output (even no output), a crash, a... whatever.
Same applies to scanf-format specifiers, of course.
So if data type is int, use %d; if data type is double, use %f.
In your code you use s as an int, and when you use scanf you are using %f instead of %d. That's the reason why you are getting the first two outputs as a zero.
As for the third output, you will get the expected value, because in that case you are correctly using %d. See the code below:
int s;
printf("enter the value");
scanf("%d", &s);
printf("the area of square is=", s*s);
Hey guys thanks so much for the help. Before checking back this morning I tried one more thing, and alas it was a stupid error.
When declaring "double s,a", I realized my scanf() function was using scanf("%f",s) as opposed to the correct scanf("%lf", s)".
Also thanks for the help for use of %d when using "int s,a".
This question already has answers here:
warning: format ‘%d’ expects type ‘int *’, but argument 2 has type ‘int’
(8 answers)
Closed 5 years ago.
if (answer == 'Y') {
int a, u, l;
printf("How many numbers do you need?\n");
scanf("%d", a);
The program crashes after this line. What should I be using instead of "%d"?
printf("Specify the lower bound of the range:");
scanf("%d", l);
printf("Specify the upper bound of the range:");
scanf("%d", u);
for(c = 1;c <= a ;c++) {
n = rand() %(u - l) + 1;
printf("%d\n", n);
}
}
scanf("%d", &a);
scanf() needs as argument an address where he can store the information.
a is the name of the variable, while &a is the address of memory that contains that variable.
You need to pass the address of the variable, because scanf() will store the value in it.
The program crashes because scanf() is dereferencing an int which is not even yet initialized both things cause undefined behavior.
In fact, all these are undefined behavior and all occur in that single scanf() call
Dereferencing an invalid pointer
Passing the incorrect types for given format specifiers.
Reading from uninitialized variables.
To pass the address use the & address of operator
if (scanf("%d", &a) == 1) {
// Proceed with `a' and use it
} else {
// Bad input, do not use `a'
}
In this case, the warning is not an error because int is in principle convertible to a pointer, but the behavior is undefined if you try to reference such type, and also the pointer size might be too big for int to store it.
This warning is very severe, ignoring it will never result in good behavior because it involves treating a value that is unlikely to be a pointer value as if it was, this normally would lead to the program crashing.
In general, you should only ignore a warning if you REALLY know what you're doing. And almost never, you do someting on purpose that would trigger a warning, although there are situations where it might be legit.
As a beginner (I know that you are a beginner simply because you are using scanf()), you MUST NOT ignore a warning.
Also, even if your text book examples never check the return value of scanf() you should. Not doing so, and specially when you haven't initialized the variables yet will probably invoke undefined behavior.
Pass address of the variable in scanf as shown below:
if (answer == 'Y') {
int a, u, l;
printf("How many numbers do you need?\n");
scanf("%d", &a);
printf("Specify the lower bound of the range:");
scanf("%d", &l);
printf("Specify the upper bound of the range:");
scanf("%d", &u);
for(int c = 1;c <= a ;c++) {
n = rand() %(u - l) + l;
printf("%d\n", n);
}
}
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
}
What does "for each value converted" mean in the following sentence?
Q: Why doesn't the call scanf("%d", i) work?
A: The arguments you pass to scanf must always be pointers: for each
value converted, scanf "returns" it by filling in one of the
locations you've passed pointers to. (See also question 20.1.) To fix
the fragment above, change it to scanf("%d", &i) .
I have found this in the c-faq; it's question 12.12.
If you execute scanf("%d", &i) with input 123, the character sequence 123 is converted to an int value, which is stored in i.
This is not a type conversion as might be specified by a cast, but it's still reasonable to refer to it as a "conversion".
scanf() can scan for more than one value in a single call. e.g.:
int numConverted = scanf("%d %f %d", &myInt1, &myFloat, &myInt2);
Note: you should always inspect the return value to find out how many have actually been converted, though.