Formatted input in C - c

Can someone please help tell me what is wrong with my code. I am trying to ask user fro two name of his/her friends and their age. then return the average of their ages. but the output is not as expected.
#include <stdio.h>
int main(void){
char friend1;
char friend2;
float age1;
float age2;
float average;
printf("Please enter name of your friend...\n");
scanf("%s", &friend1);
printf("How old is %s?\n",&friend1);
scanf("%f", &age1);
printf("Enter name of one more friend!\n");
scanf("%s",&friend2);
printf("How old is %s?\n", &friend2);
scanf("%f", &age2);
average = (age1+age2)/2;
printf("Average age of your friends %s and %s is %4.2f years old\n" ,&friend1,&friend2,&average);
return 0;
}

Two things -
In C strings are basically null terminated char arrays.
You need to have enough memory to hold the inputted characters and the '\0' to mark the end of the string.
You have used one char variable and passed it's address to scanf. scanf tries to store the input name but it will access some memory that it shouldn't resulting in undefined behavior.
The correct way would be to use an array with some number maximum char that might be there. You will do the same thing for friend2 variable also.
#define MAXLETTERS 10
char friend1[MAXLETTERS ];
if( scanf("%9s",friend1) == 1){
// got name in friend1
}
Notice the %9s - why 9? Because we will get 9 characters from input and the last one (10th one) will be the \0 character. The problem with scanf("%s",friend1) is %s matches any string, of any length, and scanf() has no idea when to stop reading. It reads as long as it can parse the input according to the format string, as a result it writes to friend1 more than 10 characters - leaving us with a possibility of buffer overflow.
By specifying that 9 we are telling scanf don't read more than 9 characters.
& operator when applied to variable returns the address of it - in your case after calculating the average of two friend's, you need to print it's value not it's address. So remove & in printf for the 3 variables listed in each of the cases. Just pass the value of the variables to the printf function not the addresses.
In case you are wondering why there is no & used in scanf with friend1 and friend2 - then you should know that when an array is passed to a function (here that function being scanf) it is converted into (known as array decaying) pointer to the first element. The first element here is friend1[0] and a pointer to it means that pointer's content is &friend1[0]. And that is what is being expected by scanf - the address where it will store the inputted data.

Declare friend1 & friend2 as char array if you want to store names into them as below
char friend1[50];/** take the char array of required size **/
char friend2[50];
And while scanning you no need to provide & in scanf if friend1 is declared as char array, because char array name itself address.
printf("Please enter name of your friend...\n");
scanf("%s", friend1);
Apply the same for friend2. Also while printing don't use & if you want to print value of average.
Replace
printf("Average age of your friends %s and %s is %4.2f years old\n" ,&friend1,&friend2,&average);
with
printf("Average age of your friends %s and %s is %4.2f years old\n" ,friend1,friend2,average);

Since scanf requires a string (pointer to char), try switching to an array of char.
char friend1[20];
char friend2[20];
May be a valid example if the strings are less than 19 characters.

Related

C printf function data formats

Very simple C printing question!
#include <stdio.h>
#include <conio.h>
int main() {
int Age = 0;
printf("Enter your Age\n");
scanf("%d",&Age);
char Name;
printf("Enter your Full name\n");
scanf("%s",&Name);
printf("My name is %s and I am aged %d" ,&Name,Age);
return 0;
}
When I input "blah" and 1, for some reason this returns:
"My name is Blah and I am aged 1929323232"
I presume I am misunderstanding a data format in either the scanf or the printf functions but can't work it out.
The problem is because of line
char Name;
Name is of type char. That means that it is supposed to store only one character. As a result
1. The scanf() is not able to store the input text properly (this will result in a crash in most cases or other undefined behaviour depending on the system - which judging by the output you provided is what you got)
2. (if the code didn't crash) Treating Name as a string with the %s argument in printf() essentially outputs garbage.
The type that corresponds to strings in C is char * (or char[]). Essentially, changing Name to some statically allocated char-array while performing the necessary changes in the next lines should fix your error:
char Name[256]; //allocated 256 bytes in Name array
printf("Enter your Full name\n");
scanf("%s",Name); // removed & before Name
printf("My name is %s and I am aged %d" ,Name,Age); // same here
You could also opt to go with a dynamically allocated string of type char * but I guess that's a different topic altogether.
As a general suggestion, I think you should look at pointers more closely. Especially in C, almost all string operations involve being aware of pointer mechanisms.

How to take character input in an array in C?

char name[2];
scanf("%c",name);
printf("%c",name);
I am just starting to learn C. I'm curious about the above code, what I got from the printf output, is not the same with the character I typed in. Rather the output was some funny looking symbol. Can someone explain this to me?
For the %c specifier, scanf needs the address of the location into which the character is to be stored, but printf needs the value of the character, not its address. In C, an array decays into a pointer to the first element of the array when referenced. So, the scanf is being passed the address of the first element of the name array, which is where the character will be stored; however, the printf is also being passed the address, which is wrong. The printf should be like this:
printf("%c", name[0]);
Note that the scanf argument is technically ok, it is a little weird to be passing an array, when a pointer to a single character would suffice. It would be better to declare a single character and pass its address explicitly:
char c;
scanf("%c", &c);
printf("%c", c);
On the other hand, if you were trying to read a string instead of a single character, then you should be using %s instead of %c.
Either Read a single char
char name[2];
scanf("%c",name);
printf("%c",name[0]);
Or read a string
char name[2];
scanf("%1s",name);
printf("%s",name);
You need %s since because name contains 2 elements. %c is used for single character so if you want the user to input something for e.g. "as"(without "") and the program to print it out you need %s.
char name[2];
scanf(" %s", name);
printf("%s",name);
if you give your input which contains characters less than or equal to two you will get a correct output just as your input if your input contains characters greater than 3 then it doesn't work

How to concatenate number in printf

I would to do something like this:
int index=1;
for(index=1; index<10; index++)
printf("Welcome player"+index+". How are you today?");
I'm new in C programming and not sure how to concatenate an integer.
printf() has special format specifiers that enables you to inject variables into the resulting string. In your case you would want to do it like this:
printf("Welcome player %d. How are you today?", index);
See more info here.
what I think you are trying to do is this
char index[20];
printf("Enter Name: ");
scanf("%s", index);
printf("Welcome player %s How are you today?", index);
The reason we do the scanf is because we want user input, whatever the user will put in the scan f will come out as the output for your printf.
We use %s because index is a string, for things such as ints, floats, and chars you use %d, %f, or %c or else it wouldn't compile if you were trying to use %d if it was actually a string
at the end of the second printf we used the name of the integer we wanted to use, show the value within the string would print.
The array with the char index[20]; is to assume that the string will not be longer than twenty bits, if you wanted more than you can write however long you wish it to be, if you want it less you can write it to be small as 0 if you wished. (This would give it eight character input, because a byte can store 8 bits, so 8 characters).

problems with scanf and conversion specifiers

Here you can see my source code:
#include <stdio.h>
int main()
{
char yourname;
char yoursex;
int yourage = 0;
printf("Hey, what's your name?\n");
printf("My name is: ");
scanf("%s", &yourname);
printf("Oh, hello %s! \n\n", &yourname);
printf("Are you a boy or a girl?: ");
scanf("%s", &yoursex);
printf("Nice to know you are a %s! \n\n", &yoursex);
printf("How old are you %s? I am ", &yourname);
scanf("%d", &yourage);
printf("I see you are %d, you have many years then!", &yourage);
return 0;
}
I was trying things that I didn't knew, and strangely it is not working for me. What's the problem? Also, why it needs to be %s and not %c? If I use %c instead it does not work!
Where it says:
How old are you %s? instead of putting my name, it says ''oy''
and instead of showing my age in the last line, it shows a big number.
These are the very basics of C Programming, and I strongly advise you to get a decent book - The C Programming Language by Dennis Ritchie would be a good start.
There are numerous errors in your code.
A char can contain only one character, like 'A', or 'a' or something like that. When you're scanning a name, it is going to be a group of characters, like 'E', 'd', 'd', 'y'. To store multiple characters, you need to use a character array. Also, the format specifier used to scan/print characters is %c, %s is for when you need to scan a group of characters, also called a string into an array.
When you use printf, you do not supply a pointer to the variable you are trying to print (&x is a pointer to variable x). The pointer is a 32/64-bit integer, which is likely why you see a random integer when trying to print. printf("%c\n", charVar) is sufficient.
scanf does not need an & while using %s as the format specifier, assuming you have passed a character array as the argument. The reason is, scanf needs to know where to store the data you are reading from the input - and that is given by a pointer to the memory location. When you need to scan an integer, you need to pass an &x - which means, pointer to memory location of x. But when you pass a character array, it is already in the form of a memory address, and doesn't need to be preceded by an ampersand.
I once again recommend you look up some decent tutorials online, or get a book (the one I mentioned above is a classic). Type the examples as given in the material. Experiment. Have fun. :)
%s is for reading a string -- multiple characters delimited by whitespace. %c is for reading a single char.
You declare your yourname and yoursex vars as characters, and then try to read strings into them. The string read will overwrite random other things in the stack frame and misbehave or crash.
You want to declare yourname and yoursex as character arrays, so they can hold strings:
char yourname[32];
char yoursex[32];
then, when reading into them, you want to include a length limit so they don't overflow:
scanf("%31s", yourname);
This is a single character:
char yourname;
But %s indicates that the variable is a string (i.e., an array of characters terminated by a NUL). That's why you need %c. If you really did mean to use a string, then define the variable like
char yourname[32]; /* just pick a big enough size */
Also, you are correct to use the address of the variable with scanf(), but printf() needs the value. So instead of
printf("I see you are %d, you have many years then!", &yourage);
use
printf("I see you are %d, you have many years then!", yourage);
The "big number" is the memory address.
Make sure you read the comments in code!
#include <stdio.h>
int main()
{
char yourname[10];
char yoursex[5]; // boy or girl + null terminator
int yourage = 0;
printf("Hey, what's your name?\n");
printf("My name is: ");
scanf("%s", &(*yourname)); // & and * cancel each other out,
// thus take a look at the next scanf()
printf("Oh, hello %s! \n\n", yourname); // yourname is now an array
printf("Are you a boy or a girl?: ");
scanf("%s", yoursex);
printf("Nice to know you are a %s! \n\n", yoursex);
printf("How old are you %s? I am ", yourname);
scanf("%d", &yourage); // ok
printf("I see you are %d, you have many years then!", yourage); // here you don't
// need the address of the variable!
return 0;
}
The expression char yourname; only holds space for a single character, so quite likely you end up corrupting the memory space when scanning for yourname. You should allocate a bigger buffer and make sure that you don't overrun its length by setting a maximum number of characters to be read with the scanf function; as described in some of the other answers.
The fact that the following printf print correctly the name doesn't mean that the memory doesn't get corrupted; as C/C++ don't really check the boundary of any strings or arrays used at runtime.
As suggested by others, starting by reading a good book about C and/or C++ wouldn't a bad idea.

Character variable string size in C

I'm trying to make a simple C program where printf asks your name and then enter it with scanf but the output only gives me one letter in the name. This is the code I used:
#include <stdio.h>
main()
{
char cName;
cName = '\0';
printf("What is your name?: ");
scanf("%c", &cName);
printf("Good evening %c", cName);
}
Output:
What is your name?: Michael
Good evening M
I tried putting [] and [20] beside cName when I declared the variable but that didn't work either. Anyone know what I'm doing wrong?
char cName[100];
printf("What is your name?: ");
scanf("%s", cName);
printf("Good evening %s", cName);
Nah... explanation, this is what I forgot about:
char c; is (most probably) 1-byte-long, that is, it allocates only 1 byte on the stack. Your intention is probably to read the entire string into it, which is wrong. That is why I replaced it with an array of characters (limited to 99 characters + null terminating character \0): char cName[100];
scanf("%c", &cName); reads only one character into your cName variable.
You should use the %s format to scan the entire string, and store it into an array (big enough to store all input characters), by passing the address to a newly created variable cName.
printf("Good evening %c", cName); it prints out a single character, same as with scanf you should use %s instead to print out a sequence of characters from your array until a null terminating character (\0) is encountered.
Why for the single character &cName was necessary as 2nd argument, and now just cName for a string ?
This is because we have changed the formatting string and the destination that scanf initializes. That is, scanf needs to initialize your variable. Your variable is allocated on the stack and what you need to do is to pass its address, so that the scanf can set its value in an indirect manner (through pointer).
In C, to get the address of a variable, whe normally use an ampersand - &. However, in case of arrays (declared like char cName[500];), the name of the array is itself a pointer to its first character. Alternatively, you could use a syntax like &cName[0] to obtain the address of the first character.
This is why in case of a single character we would say &cName to get its address, and in case of arrays we say simply cName.
It is possible to overflow cName array!
Yes it is! Your array is now only [100]-character-long. Some hacker could now type in more characters, possibly overriding your stack. How can we make it more safe? Very easily! We can limit the length of the string being copied to the array within scanf itself by proving length-specifier, just like below:
scanf("%99s", cName);
Hold on a second! My array is 100-character-long, why do you allow only 99 in scanf ?
If you want to treat your char-array as a string of characters, it should be terminated with (that is, the last character should be set to) a null terminating character, expressed by the \0 constant. And scanf appends this character after all input symbols have been read. This last 100th character is reserved for this purpose.
Should I provide %99s to printf just like to scanf ?
No! %s is sufficient. When printf sees the %s format, it knows to print out all characters until a null terminating character is encountered. Additionally, a length-specifier in case of printf is in fact a minimum-width-specifier, which allots a space for the argument in the output stream.
you can also declare a character pointer
char *cName;
cName = malloc(20*sizeof(*cName));
replace your scanf with this
scanf("%s", cName);
add this together with other header files
#include <stdlib.h>
and free the dynamic memory after you're done using it
free(cName);
I believe that you must use %s instead of %c. As %c will only scan/print one character. %s should scan/print multiple characters. You will also probably need to use strings. try:
#include <stdio.h>
#include <string.h>
int main ()
{
char cName [200];
scanf("%s",&cName);
printf("Good evening %s.\n",cName);
return 0
}

Resources