Related
#include <stdio.h>
#include <stdlib.h>
int main() {
char a;
printf("What? \t");
scanf("%s", &a);
printf("U have to %s", a);
return 0;
}
Whenever I build and run this code and enter a value in %s, I get an error and the debug program stops working and closes. But when I use ampersand sign like this:
#include <stdio.h>
#include <stdlib.h>
int main() {
char a;
printf("What? \t");
scanf("%s", &a);
printf("U have to %s", &a);
return 0;
}
in the printf... it works. Why is that? It also differs between the format specifier, such as one doesn't need to put & (ampersand) sign in printf when one uses %c or %d in the scanf. Why does this happen and is it related to the data types and which format specifiers concludes this result?
(sorry for my bad English. I am not a native English speaker and this is my first time here).
What you have here is a classic example of code that seems to work, but for the wrong reasons.
Let's review a few things about printf and scanf. The format specifier %d is for values of type int. You can read an integer like this:
int i;
scanf("%d", &i);
And you can print it back out like this:
printf("%d\n", i);
Why does one use an & and one does not? Well, C uses what's called "pass by value". If we wrote
scanf("%d", i); /* WRONG */
we would be passing the value of i to scanf. But we don't want to pass the (old) value of i to scanf, we want scanf to read a new value, and store it into i. In other words, we want scanf to, in effect, pass the new value of i back to us. For that to work, we instead pass scanf a pointer to the variable i where we want it to store the just-read integer. That's what the & does -- it generates a pointer to i.
When we call printf, on the other hand, the regular way of passing arguments works just fine. We do want to pass i's value to printf so that it can print it out. If we were to call
printf("%d\n", &i); /* WRONG */
it wouldn't work, because printf expects an int, and here we're wrongly handing it a pointer-to-int.
So now we've learned that for integers with %d, printf wants an int and scanf wants a pointer-to-int.
Let's talk about characters. The format %c is for characters. We can read one character with scanf:
char c;
scanf("%c", &c);
And we can print it with printf:
printf("%c\n", c);
Again, the pattern is exactly the same. scanf needs a pointer, so that it can fill in the value, so we pass &c. But printf just needs the value, so we pass plain c.
Now we get to strings. A string in C is an array of characters. Also strings in C are always terminated by a special null character, '\0', that marks the end of the string. So if we wanted to declare a variable that could contain strings up to 9 characters long, we might write
char s[10];
That gives us room for 9 characters, plus the terminating '\0'.
But arrays are special in C: Whenever you pass an array to a function, or whenever you do anything that would require the "value" of the array, what you get instead (what the compiler automatically generates for you) is a pointer to the array's first element.
What this means is that to read a string with scanf and %s, we can just call:
scanf("%s", s);
"But where is the &?", you ask. "I thought you always needed an & when calling scanf!"
Well, not quite. You always need a pointer when calling scanf. And in fact, when you called scanf("%s", s), it was just as if you had written
scanf("%s", &s[0]);
When you use %s with scanf, it expects a pointer to the first of several characters, that is, a pointer to the beginning of an array of characters, where it should begin writing the string it reads. (How does it know how big the array is? What if the user types a string that's too long to fit in the array? We'll get to those points in a moment.)
You can print strings with %s too, of course, and it looks like this:
printf("%s\n", s);
This is, again, just as if you had written
printf("%s\n", &s[0]);
When you use %s with printf, it expects a pointer to the first of several characters which it should begin printing, until it finds the terminating '\0' character.
So %s is special with printf and scanf, because strings are special (because arrays are special). With %d and %c and just about every other format specifier, you usually need a & when you call scanf, and you usually don't want that & when you call printf. But with %s, you usually don't want the & for either printf or scanf.
(And if we think about it a bit more carefully, the exception is not so much that scanf and %s does not need the &. Remember, the rule is really, scanf always needs pointers. The only reason scanf and %s doesn't need an & is that when you pass an array, you get a pointer to the array's first element automatically. So the exception is really for printf and %s: printf and %s does expect a pointer, and the reason printf and %s is designed to expect a pointer is that there's no way to not give it one: it has to accept a pointer, because for strings, that's what you always end up giving it.)
So the rule with %s is that scanf expects a pointer to the first of several characters, and printf expects a pointer to the first of several characters, too.
So now, with all that background out of the way, we can look at your code. You basically wrote
char c;
scanf("%s", &c);
At first this might seem to be kinda, sorta, almost correct. scanf and %s wants a pointer to a character, and you gave it &c, which is a pointer to a character. But %s really wants a pointer to the first of several characters. But you gave it a pointer to just a single character. So when the user types a string, the first character typed will get stored in c, but the rest of the characters, and the terminating '\0', will get written to unallocated memory somewhere off to the right of variable c. They'll overwrite ("clobber") memory that was, perhaps, used for something else. This is a serious problem, but it might not become evident right away.
Finally, you tried to print things out again with printf. You first tried
printf("%s\n", c); /* WRONG */
but this didn't work at all. The reason is that %s with printf expects a pointer-to-char, but you gave it a plain char. Suppose c contains the letter 'A'. This would end up asking printf to go to address 65 and begin printing characters until it finds the terminating '\0'. Why address 65? Because 65 is the ASCII code for A. But there's probably not a proper, null-terminated string starting at address 65 in memory; in fact there's a good chance your program doesn't have permission to read from address 65 at all.
So then you tried
printf("%s\n", &c); /* ALSO WRONG */
and this seemed to work. It "worked" because, if scanf succeeded in storing a complete string into c and the unallocated memory off to the right of it, and if clobbering that memory somehow didn't cause (too many) other problems, then when you pass the pointer &c to printf, printf can find those characters, making up a string, and print them out.
So it "works", but as I said, for the wrong reasons: in the process it stomps all over memory it doesn't "own", and sooner or later, something else is going to not work as a result.
How should you have scanned and printed a string? One way is like this, as we saw before:
char s[10];
scanf("%s", s);
printf("%s\n", s);
Now when scanf gets a pointer to the first element of the array s, it has 10 characters to play with.
We really do have to worry about the possibility that the user will type more than 9 characters. But there's a fix for that: we can tell scanf how long a string it's allowed to read, how many characters it's allowed to write to the array we handed it:
scanf("%9s", s);
That 9 in there tells scanf that it's not allowed to read more than 9 characters from the user. And since 9 is less than 10, there's still room for the terminating '\0' character.
There's much more that could be said about scanf. As chqrlie noted in a comment, it's important to check its return value, to make sure it succeeded in converting as many values as you wanted it to. It's got some strange rules about whitespace. Unless you know what you're doing, you can't intermix calls to scanf with calls to other input-reading functions like getchar or fgets -- you'll get strange results. And, finally, scanf is so persnickety and (in the end) so lacking in truly useful functionality that it's not really worth using at all. But those are topics for another day, since this answer is tl;dr already.
The %s format specifier requires a pointer to a string. When used with scanf, it must be a char array with enough characters for the word you enter plus the trailing null byte that indicates the end of the string. In printf() it has to be a null-terminated char array.
Using a pointer to a char variable doesn't work, because it doesn't have room for the null byte. You're causing undefined behavior by writing outside the variable.
char word[100];
scanf("%s", word);
printf("%s\n", word);
You can use %c to read and write a single character rather than a string of multiple characters.
char letter;
scanf("%c", &letter);
printf("%c\n", letter);
In statement char a; a is a character variable & to scan a char variable use %c format specifier.
scanf("%s",a);/* %s expects base address of char buffer, not single char */
scanf(" %c",&a);/* this is correct */
If you want to scan using %s then your input should be char buffer like char buf[10]. for e.g
char a[10];
scanf("%s",a);
u don't need to put &(ampersand) sign in printf when u use %c or %d ? no need to provide address & to printf() as printf() job is to print not to scan. for e.g
char input;
scanf("%c",&input);/* here you need &, As scanf() will store input char into
address you provided i.e &input */
printf("%c",input);/*here no need &input, bcz input char already stored,
printf will just print the char*/
Well, if you print the address you can use %p.
printf("%p",a);/*a is char buffer */
#include<stdio.h>
#include<string.h>
void main()
{
char a,b,c;
printf("Enter alien names:\n");
scanf("%s\n%s\n%s\n",a,b,c);
printf("The alien names are %s, %s and %s. A meteor hit %s's spaceship. A star scratched %s\'s spaceship. But %s fixed %s and %s\'s spaceships. The three became friends and are from the planet BYG (which means BLUE YELLOW GREEN)",a,b,c,a,b,c,a,b);
}
What is the specific reason for the runtime error I'm getting here?
To solve this issue you should simply consider to use strings (arrays of chars) to contain the different names.
Here is an example how to do that:
void main()
{
// The string "a" can contain up to 100 symbols (chars).
char a[100];
printf("Enter an alien name:\n");
scanf("%s",a);
printf("The alien name is %s.", a);
}
The difference between "char a" and "char a[100]" is that in the first case the variable "a" corresponds to a single character and in the second it corresponds to a string - an array of chars which can contain up to 100 characters.
The posted code has undefined behavior, because the variables a, b, and c are of type char, while the %s conversion specifier in the call to scanf() is expecting a pointer to the first element of a character array that can hold the input string. Mismatched conversion specifers and arguments in a scanf() call lead to undefined behavior, and attempting to write too many characters into the receiving array causes undefined behavior.
The first problem can be fixed by declaring a, b, and c as arrays large enough to hold expected input:
char a[100], b[100], c[100];
...
scanf("%s\n%s\n%s\n", a, b, c);
Note that arrays decay to pointers to their first elements in most expressions, including function calls, so here a is a pointer to the first element of the character array a[]; this is equivalent to &a[0].
There is still a possibility for undefined behavior if the user enters too many characters. To avoid this, always specify a maximum width when using scanf() to read user input into a string. Note here that the specified width is the maximum number of characters that will be read for that input item, not including the null terminator, \0, which will be automatically added by scanf(), so the maximum width must be at least one less than the size of the receiving array:
scanf("%99s\n%99s\n%99s\n", a, b, c);
But if you compile and run this code, you will find that it does not behave as expected. After the third name is entered, the program will continue waiting for more input. This is because the \n character is a whitespace character, and when scanf() encounters a whitespace character in a format string, it reads and discards zero or more whitespace characters in the input until a nonwhitespace character is encountered, or until no more characters can be read. The %s directive tells scanf() to read characters until a whitespace character is encountered. So when the user presses Enter after the final name, scanf() completes matching input characters for the final name and returns the \n character to the input stream; then the \n is reached in the above format string, and scanf() matches the aforementioned \n character in the input stream, and any further whitespace characters that are encountered. This will end if the user enters another nonwhitespace character, or signals end-of-file from the keyboard (e.g., with Ctrl-D or Ctrl-Z).
To avoid this complication, remember that it is almost never correct to end a scanf() format string with a whitespace character. Also, there is no need to use \n rather than a space character, since both are simply interpreted as whitespace directives by scanf():
scanf("%99s %99s %99s", a, b, c);
It would further improve the posted code if the return value from the call to scanf() were checked before attempting to use the input. Since scanf() returns the number of successful assignments made, this value should be 3:
#include <stdio.h>
#include <string.h>
int main(void)
{
char a[100], b[100], c[100];
printf("Enter alien names:\n");
int ret_val = scanf("%99s %99s %99s", a, b, c);
if (ret_val == 3) {
printf("The alien names are %s, %s and %s. A meteor hit %s's "
"spaceship. A star scratched %s\'s spaceship. But %s "
"fixed %s and %s\'s spaceships. The three became friends "
"and are from the planet BYG (which means BLUE YELLOW GREEN)\n",
a, b, c, a, b, c, a, b);
} else {
puts("Input error");
}
}
What is the specific reason for the runtime error I'm getting here?
The function scanf using the format specifier %s expects to be passed the address of a char array, in which to place the input data. For example an array such as
char a[100];
However, you pass simple char variables a and b and c which can hold values in the range -128 to 127, or 0 to 255, depending on whether the implementation's char is signed or unsigned.
These variables were not even initialised, so indeterminate values were passed to scanf. But even if they had been initialised, it is very likely that the values passed will cause a segfault, when used as addresses.
My compiler issued 2 warnings for each of a, b and c passed to scanf.
warning C4477: 'scanf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'int'
warning C4700: uninitialized local variable 'a' used
Please enable and act on all compiler warnings.
//There are things that shoudn't be there. Im not a pro but this is what I think.
#include<stdio.h>
#include<string.h>//you have include this library but you didn't use a function from it.
//I think what you want to do is use the str functions like strcpy
//but in this case you don't need to use it.
void main()
{
char a[25],b[25],c[25];//Here you declared a character a, b and c. But if you want to store a string, you have to declare an array of characters. So instead of a, b, c, it's a[someValue], b[someValue] and c[someValue].
//Declare an array with a size that you think will cover the whole "alien name". e.g. a[25]..
//but i don't know, maybe you did it on purpose. Maybe you just want to name the aliens with one character like A, B, C. But if you want to name the aliens with a long name, you must declare an array.
printf("Enter alien names:\n");
scanf("%s\n%s\n%s\n",a,b,c);//You don't need to put the "\n" between those "%s". "\n" means "newline". It will work without it because scanf automatically reads next set of characters when it meets white space of newline.
//--so you can remove "\n" in there and replace it with space. But you can leave it there also but you really have to remove the last "\n" because scanf will search again for the next
//--new line before it will end asking for input and pressing enter will not work because you have to type another set of characters before scanf will read the last "\n" that you put at scanF.
//Another mistake here is the format specifier that you used (%s). It doesn't match declaration because you declare char a, b, c, that will only store one character each.
//In case that you're really just storing one character each alien's name, you have to use the "%c" instead of "%s" and you must pass the reference of the char variable in
//--scanf, e.g. scanf("%c %c %c", &a, &b, &c);
//Just remember that if you plan on storing a string or a long name there, you must declare an array like I said at the beginning.
//--and if it's an array, you don't need to include the '&' on every variable when you're passing it in scanF.
//There's nothing wrong here if you're alien's names are string.
printf("The alien names are %s, %s and %s. A meteor hit %s's spaceship. A star scratched %s\'s spaceship. But %s fixed %s and %s\'s spaceships. The three became friends and are from the planet BYG (which means BLUE YELLOW GREEN)",a,b,c,a,b,c,a,b);
}
The specific reason for the runtime error is this line:
scanf("%s\n%s\n%s\n",a,b,c);
The %s conversion specifier tells scanf to read a sequence of non-whitespace characters from the input stream (skipping over leading whitespace) and store that sequence to an array of char pointed to by the corresponding argument. The problem is that a, b, and c are not pointers to char; they're single char objects that haven't been initialized. The odds of any of them containing a value that corresponds to an address that scanf can write to is almost non-existant.
First, change the declarations of a, b, and c tochar a[SOME_LENGTH] = {0}; // initialize array contents to 01
char b[SOME_LENGTH] = {0};
char c[SOME_LENGTH] = {0};
where SOME_LENGTH is a number that's long enough to contain the longest string you expect to enter plus one extra space for the string terminator. IOW, if the longest string you intend to read is 10 characters long, then your declarations need to be
char a[11] = {0};
char b[11] = {0};
char c[11] = {0};
Secondly, change your scanf call to
scanf( "%(SOME_LENGTH-1)s %(SOME_LENGTH-1)s %(SOME_LENGTH-1)s", a, b, c );
where (SOME_LENGTH-1) is the length of your buffer minus 1. Again, assuming SOME_LENGTH is 11:
scanf( "%10s %10s %10s", a, b, c );
This will help prevent a buffer overrun in the event you enter a string longer than what the buffer is sized to hold.
Both the %s conversion specifier and a blank space in the format string tell scanf to consume and discard any leading whitespace. You can run into trouble specifying whitespace characters in the format string.
Additional notes:
main returns int, not void - change your main to
int main (void)
{
...
}
If there are fewer elements in the initializer than there are in the array, then excess elements are initialized to 0. So in this case, the first element is *explicitly* initialized to 0, and the remaining elements are *implicitly* initialized to 0.
I don't know why this program doesn't work:
char syze;
printf("Please enter your desired size (Choose from S,M,L,XL)\n");
scanf("%s", &syze);
if(syze =='S')
{printf("Available");}
else if(syze =='M')
{printf("Available");}
else if(syze =='L')
{printf("Available");}
else if(strcmp(syze,"XL")==0)
{printf("Available");}
else
{printf("Please enter a valid character");}
return 0;
The problem is in
scanf("%s", &syze);
in your code, size is of type char and you should be using %c format specifier to scan the input.
If you use %s format specifier to scan the input for a char, essentially you'll be overrunning the allocated memory thereby creating undefined behaviour
Then,
strcmp(syze,"XL")
is also wrong, as strcmp() needs a (const)char * as both the arguments, and you're passing a char as the first one. You can simply make use of the equality operator, == to compare a char.
Finally, a char will never be able to hold "XL".
Solution: If you need to have "XL" as one of the inputs, you may want to change syze to an array, like
char syze[3] = {0};
or likewise. In that case, you can keep the scanf() as
scanf("%2s", syze);
and compare your inputs using strcmp().
You have a problem in strcmp(syze,"XL")==0. You can't compare a char to a string XL. Use only X for that choice and compare the same as the others if(syze =='X').
You have another problem in scanf("%s", &syze);. Use %c to scan a char:
scanf("%c", &syze);`
If you want to keep using the choice "XL", you should declare syze as char syze[3] and compare all choices using strcmp.
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.
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
}