This question already has answers here:
Reading string from input with space character? [duplicate]
(13 answers)
Closed 6 years ago.
I want to get string elements with space. Let's say I have a string called test and user will enter something in every cell, for instance he will enter colors he will enter the colors in a single line like; Green Yellow Blue Black - then he will press enter then program take everything until the space entered and put it on the first element of string then continues. In this case the string should be according to;
test[0] "Green"
test[1] "Yellow"
test[2] "Blue"
test[3] "Black"
I have tried to write it with 2 nested loops but I couldn't manage to get strings with space
long i
char* test[4]
printf("Enter your guess:\n");
for(i=0;i<5;i++)
{
while(test[i]!=" ")
{
scanf("%s", test[i]);
}
}
That's because scanf (and family) with the "%s" format only reads space delimited words. To get a whole line you should use fgets instead.
Do note that fgets puts the ending newline in the buffer you provide (if it can fit)
Also, you definitely need to allocate memory for the strings first. The code you show seems to tell us that you don't initialize the array test which means you either have an array of null pointers (if test is a global variable) or have pointers being indeterminate (if test is a local variable. Both of these will lead to undefined behavior.
Depending on platform, you might have a function available called getline which allows you to read lines, and also allocates memory for you. As with fgets the ending newline will be added to the buffer.
Lastly, you can't compare string using the == operator, it will only compare the pointers and not what they point to. Therefore comparing using == will almost always be false, unless both pointers point to the same memory.
To compare string you should use the strcmp function.
Related
The whole function the question is about is about giving a two dimensional array initialized with {0} as output and making a user able to move a 1 over the field with
char wasd;
scanf("%c", &wasd);
(the function to move by changing the value of the variable wasd is not important i think)
now my question is why using
scanf("%s", &wasd);
does only work partly(sometimes the 1 keeps being at a field and appears a 2nd time at the new place though it actually should be deleted)
and
scanf("%.1s", &wasd);
leads to the field being printed out without stop until closing the execution program. I came up with using %.1s after researching the difference between %c and %s here Why does C's printf format string have both %c and %s?? If one can figure out the answer by reading through that, i am not clever or far enough with c learning to get it.
I also found this fscanf() in C - difference between %s and %c but i do not know anything about EOF which one answer says is the cause of the problem so i would prefer getting an answer without it.
Thank you for an answer
Simple as that, %s is the conversion for a (non-empty) string. A string in C always ends with a 0 byte, so any non-empty string needs at least two bytes. If you pass a pointer to a single char variable, scanf() will just overwrite whatever is in memory after that variable -- you cause undefined behavior and anything can happen.
Side note, scanf("%s", ..), even if you give it an array of char, will always overflow the buffer if something longer is entered, therefore causing undefined behavior. You have to include a field width like
char str[10];
scanf("%9s", str);
Best is not to use scanf() at all. For your single character input, you can just use getchar() (be aware it returns an int). You might also want to read my beginners' guide away from scanf.
A char variable can hold only one byte of memory to hold a single character. But a string (array of characters) is different from a char variable as it is always ended with a null character \0 or numeric 0. So in scanf you specifically mentioned whether you are reading a character or a string so that scanf can add a null character at the end of a string. So you are not suppose to use a %s to read a value for a char variable
I started learning about inputting character strings in C. In the following source code I get a character array of length 5.
#include<stdio.h>
int main(void)
{
char s1[5];
printf("enter text:\n");
scanf("%s",s1);
printf("\n%s\n",s1);
return 0;
}
when the input is:
1234567891234567, and I've checked it's working fine up to 16 elements(which I don't understand because it is more than 5 elements).
12345678912345678, it's giving me an error segmentation fault: 11 (I gave 17 elements in this case)
123456789123456789, the error is Illegal instruction: 4 (I gave 18 elements in this case)
I don't understand why there are different errors. Is this the behavior of scanf() or character arrays in C?. The book that I am reading didn't have a clear explanation about these things. FYI I don't know anything about pointers. Any further explanation about this would be really helpful.
Is this the behavior of scanf() or character arrays in C?
TL;DR - No, you're facing the side-effects of undefined behavior.
To elaborate, in your case, against a code like
scanf("%s",s1);
where you have defined
char s1[5];
inputting anything more than 4 char will cause your program to venture into invalid memory area (past the allocated memory) which in turn invokes undefined behavior.
Once you hit UB, the behavior of the program cannot be predicted or justified in any way. It can do absolutely anything possible (or even impossible).
There is nothing inherent in the scanf() which stops you from reading overly long input and overrun the buffer, you should keep control on the input string scanning by using the field width, like
scanf("%4s",s1); //1 saved for terminating null
The scanf function when reading strings read up to the next white-space (e.g. newline, space, tab etc.), or the "end of file". It has no idea about the size of the buffer you provide it.
If the string you read is longer than the buffer provided, then it will write out of bounds, and you will have undefined behavior.
The simplest way to stop this is to provide a field length to the scanf format, as in
char s1[5];
scanf("%4s",s1);
Note that I use 4 as field length, as there needs to be space for the string terminator as well.
You can also use the "secure" scanf_s for which you need to provide the buffer size as an argument:
char s1[5];
scanf_s("%s", s1, sizeof(s1));
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Disclaimer: Been doing Java for a while, but new to C.
I have a program that I wrote, and I'm purposely trying to see what happens with different inputs and outputs.
#include <stdio.h>
int main() {
printf("whattup\n");
char str1[1], str2[1];
printf("Enter something: ");
scanf("%s", &str1);
printf("Enter something else: ");
scanf("%s", &str2);
printf("first thing: %s\n", str1);
printf("second thing: %s", str2);
}
This is the program flow:
whattup
Enter something: ahugestatement
Enter something else: smallertext
first thing: mallertext
Things I don't understand:
Why does "first thing" print out the str2?
Why does str2 have it's first letter cut off?
Why does "second thing:" not print out?
I made the char array with a size of 1, shouldn't it only hold 1 letter?
To answer your questions specifically, you'll have to keep in mind that what happens is very much implementation-specific. The specific behavior you're seeing doesn't have to hold true on all C implementations. This is what the C standard calls "undefined behavior". With that in mind:
Why does "first thing" print out the str2?
Why does str2 have it's first letter cut off?
You have allocated storage for two chars on the stack. The compiler allocates them next to each other, with str2 preceding str1 in memory. Therefore, after your first scanf, part of the stack will look like this:
str1 is allocated here
v
? a h u g e s t a t e m e n t \0
^
str2 is allocated here
Then, after the second scanf, the same part of memory will look like this:
str1 is allocated here
v
s m a l l e r t e x t \0 e n t \0
^
str2 is allocated here
In other words, the second input simply overwrites the first, since it goes beyond the bounds of the storage you allocated for it. Then, when you print out str1, it simply prints whatever is at the address of str1, which, as you can see in the figure above, is mallertext.
Why does "second thing:" not print out?
This is because of two effects interacting. For one thing, where you print str2, you do not end the output with a newline. stdout is normally line-buffered, which means that data written to it is not actually written to the underlying terminal until either A) a newline is written, B) you explicitly call fflush(stdout), or C) the program exits.
It would, therefore, print it when the program exited, but your program never exits. Since you overwrite parts of the stack that you don't manage, in this case you overwrite the return address from main, and therefore, when you return from main, your program promptly crashes, and thus never arrives to the point where it would flush stdout.
In the case of your program, the stack-frame layout of main looks like this (assuming AMD64 Linux):
RBP+8: Return address
RPB+0: Previous frame address
RBP-1: str1
RBP-2: str2
Since ahugestatement including its NUL terminator is 15 bytes, the 14 of those bytes that don't fit in str1 overwrite the entire previous frame address and 6 bytes of the return address. Since the new return address is entirely invalid, your program segfaults when the return from main jumps to an address that isn't even mapped in memory.
I made the char array with a size of 1, shouldn't it only hold 1 letter?
Yes, and it does. It's just that you clobber the memory that follows it.
As a general statement, scanf is not really a terribly useful function if you want to do even any most basic form of checking for illegal input. If you're hoping to do interactive input at all, it is almost always better to use something like fgets() instead and then parse the read input. fgets(), unlike scanf, takes an additional input for the size of the receiving buffer, and will then make sure to not write outside it.
You have to do the bounds checking in C, to make sure your buffers don't overflow. So your output is undefined. If you run that code many times, its bound to crash at some point because the overflown buffers will end up overwriting something important.
That's called buffer overflow. You allocated one character to hold your input, but you are writing beyond that (messing up the rest of your program's memory).
Unlike Java, the C compiler and runtime do not enforce array bounds. That is one of the main differences between "(memory-) managed languages" and low-level languages.
Your array only holds one character and the rest is out of bounds.
Access out of the range of an array is undefined and usually disastrous.
I have been trying to get a string input from a user using fgets
but fgets does not wait for input so upon investagation I learned of the gets function which seems to be working fine. My questions are: 1. Why does gets work when I input more than 10 characters if I declared an array of only ten elements. Here is my code
#include<stdio.h>
int main(void){
char name[10];
printf("Please enter your name: ");
gets(name);
printf("\n");
printf("%s", name);
return 0;
}
my input when testing: morethantenletters
will output: 'morethantenletters'
Surely, this should have caused some errors, no? Since name is only ten elements long.
2. My next question is that my code also works when I use gets(&name) instead of gets(name)-- I do not understand why. The &name is sending the address of name.while name is just sending the value of it, no?
That is exactly why you should always use fgets to replace gets. The array name has only 10 elements, but you are trying to store in it more than it's capable of. fgets prevents the program from buffer overflow, but gets doesn't.
It's undefined behavior when you are using gets in this way, don't use it.
Since name is only ten elements long.
Anything accepted more than 10 will be buffer overrun and may cause run time issues. So make sure your size is right. hint: Use getline or fgets instead.
while name is just sending the value of it, no?
For char arrays, name is also address to its starting position.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I know that every string in C ends with '\0' character. It is very useful in cases when we need to know when the string ends. However, I am unable to comprehend its use in printing a string and printing a string without it. I have the following code:-
/* Printing out an array of characters */
#include<stdio.h>
#include<conio.h>
int main()
{
char a[7]={'h','e','l','l','o','!','\0'};
int i;
/* Loop where we do not care about the '\0' */
for(i=0;i<7;i++)
{
printf("%c",a[i]);
}
printf("\n");
/* Part which prints the entire character array as string */
printf("%s",a);
printf("\n");
/* Loop where we care about the '\0' */
for(i=0;i<7&&a[i]!='\0';i++)
{
printf("%c",a[i]);
}
}
The output is:-
hello!
hello!
hello!
I am unable to understand the difference. any explanations?
In this case:
for(i=0;i<7;i++)
{
printf("%c",a[i]);
}
You loop for a number of times (7) and then quit. That is the end condition of the loop. It terminates, no matter anything else.
In the other case, you also loop for 7 times and no more and you just added another condition, which really serves no function as you already keeping a count of things. If you did the following:
int index = 0;
while (a[index] != '\0') { printf("%c", a[index]); index++; }
now you would depend on the zero termination character being there, if it wasn't in the string, you while loop would go on forever until the program crashed or something terminated it forcedly. Probably printing garbage on your screen.
\0 is not part of data in character string. It is indicator of end of string. If length of string is not known, look for this indicator. With its help you can replace your cycle of:
for(i=0;i<7&&a[i]!='\0';i++) { ...
with:
for(int i=0; a[i]; ++i) { ...
So, for-loops and printf are displaying the same string. The only difference how you print it.
'\0' does not correspond to a displayable character; that's why the first and last versions appear to be the same.
The second version is the same because under the hood, printf is just iterating until it hits the '\0'.
The purpose of the terminating zero character is to terminate the string, i.e. to indirectly encode the string length information in the string itself. If you somehow already know the length of your string, you can write code that works correctly without relying on that terminating zero character. That's basically all.
Now, in your code sample the first cycle does something that does not make much sense. It prints 7 characters from a string that actually has length 6. I.e. it attempts to print the terminating zero as well.
When you want to print a string from first character until end. Knowing the length of that string is not necessary when the string ends with \0 (Print characters until \0). So you don't need any extra variable to store the length of string.
In fact a string can have many various representations but minimizing the consumed memory (which it was important to C designers) leads designers to define zero-terminated strings.
Each string representation has its trade off between speed, memory and flexibility. For example you can have your string definition same as Pascal string which stores length of the string at first element of array but it causes that string to have limited length, but retrieving the length of string is faster that zero-terminated strings (Counting each character until \0).
I am unable to comprehend its use in printing a string and printing a string without it
Normally you don't print a string character by character like that. You print the whole string. In such cases, your C library will print until it finds a zero.
When printing a string of variable length, there has to be some 'signal' to indicate that you have reached the end. Generally, this is the '\0' character. Most C standard calls, like strcpy, strcat, printf, etc. depend on the string being zero-terminated, thus ending in a '\0' character. This corresponds to your second example.
The first example is printing a string of fixed length, which is simply a far less common occurence.
The third example combines both, it looks for a zero-terminator ('\0' character) ór 7 characters maximum. This corresponds to calls like strncpy, for example.
The purpose of the terminating zero character is to terminate the string, i.e. to indirectly encode the string length information in the string itself. If you somehow already know the length of your string, you can write code that works correctly without relying on that terminating zero character. That's basically all.
Now, in your code sample the first cycle does something that does not make much sense. It prints 7 characters from a string that actually has length 6. I.e. it attempts to print the terminating zero as well. Why it is doing that - I don't know. In other words, the first output generated by your code is formally different from the rest, since it includes the effect of printing a zero character right after the ! sign. On your platform that effect just happened to be "invisible" on the screen, which is why you probably assumed that the first output is the same as the other ones. However, if you redirect the output to a file, you will be able to see that it is actually quite different.
The other output methods in your code simply output the string up to (and not including) the terminating zero character. The last cycle has redundant condition checking, since you know that the cycle will stop at zero character, before i will have a chance to hit 7.
Other than that, I don't know what "difference" you might be asking about. Please, clarify your question, if this doesn't answer it.
In your loop, you actually print the nul character. Generally this has no effect since it is a non-printing, non-control character. However printf("%s",a); will not output the nul at all - it uses it as a sentinel value. So you loop is not equivalent to %s formatted output.
If you try say:
char a[] = "123456" ;
char b[]={'h','e','l','l','o','!' } ; // No terminator
char c[] = "ABCDEF" ;
printf( "%s", a ) ;
printf( "%s", b ) ;
printf( "%s", c ) ;
You might clearly see why the nul terminator is essential. In my case it output:
123456
hello!╠╠╠╠╠╠╠╠╠╠123456
ABCDEF
Your mileage may vary - the result is undefined behaviour, but in this case the output is running through to the adjacent string, but the compiler has inserted some unused space between them with "junk" in it. I packed a string either side of the un-terminated string because there is no way of telling how a particular compiler orders data in memory. Incidentally when I declared the strings static if the strings, the string b was output with no "run-on". Sometimes the surrounding "junk" may happen to already be zero.