Reputation: 2595
I'm getting some weird behavior I dont understand with this code:
char strings[5][4];
for (int i = 0; i < 5; ++i) {
scanf("%s", strings[i]);
}
for (int i = 0; i < 5; ++i) {
printf("%s\n", strings[i]);
}
If I enter 5 strings like:
this
is
a
test
help
I end up with something like this in the second for loop:
thisis
is
a
testhelp
help
Any idea what's happening? driving me crazy
Upvotes: 0
Views: 227
Reputation: 157
the Problem actually lies with the character array, you defined.
char strings[5][4]
the program allocates "strings" 20 "char" sized memory blocks.
lets suppose starting address is 0x00 so memory block from 0x00 to 0x20 (Mentioned in decimal system for easy understanding) is allocated to "strings"
this means strings[0] points to 0x00
this means strings[1] points to 0x04
this means strings[2] points to 0x08
this means strings[3] points to 0x12
this means strings[4] points to 0x16
now in the "scanf" is basically reading each character until endline and storing it in corresponding memory blocks
for (int i = 0; i < 5; ++i) {
scanf("%s", strings[i]);
}
so from your question, "this" is stored in 4 blocks of strings[0] and there is no space for endline character "is" occupies 3 characters from strings[1] with third being endline character.
Now coming to printf function for arrays.it considers array as pointer and iterates until it finds endline statement.
for (int i = 0; i < 5; ++i) {
printf("%s\n", strings[i]);
}
For strings[0] , printf function takes pointer 0x00 and iteartes until it finds endline character(ie at 0x06)
so "thisis" is printed and for string[1] , pointer is at 0x04 and so "is" is printed.
now if you give your input string of sizw more than 4 you can observe that the string is overflowed to next string
for (int i = 0; i < 1; ++i) {
scanf("%s", strings[i]);
}
for (int i = 0; i < 2; ++i) {
printf("%s\n", strings[i]);
}
**INPUT:**
thisab
in the above code, only strings[0] is assigned with value "thisab" but it printf produces
**OUTPUT:**
thisab
ab
to avoid such problem , use Strings or define size of each row equal to (max_input_size+1)
Upvotes: 1
Reputation: 4750
Your strings are wrongly sized for the inputs.
string in C are zero-terminated, meaning that they will contain the desired content plus an ending zero character (so that most function would understand where your string end).
Your array will be allocated contiguously onto the stack, meaning that before your first loop your memory would look like this:
000011112222333344445555
content will be arbitrary, but for ease of understanding your array would look like this
[[0,0,0,0],[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4],[5,5,5,5]]
[['t','h','i','s'],['\0',1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4],[5,5,5,5]]
[['t','h','i','s'],['i','s','\0',1][2,2,2,2],[3,3,3,3],[4,4,4,4],[5,5,5,5]]
in a contiguous view
't','h','i','s','i','s','\0',12222333344445555
resulting in the observed behavior
You can fix the issue in 2 ways
%4s
in the output format.%3s
so that input would not overlap when writing the terminating zero char.Upvotes: 0
Reputation: 56
So the way that an array of char works is that it allocates each character in the designated array; however, the last character is a null character which delimitates the "string":
char str[4] = {'n','o','t','\0'};
char str[4] = {'t','h','i','s'};
So if you add one more than the size it works due that it actually saves the space and your scanf works fine. So the solution, would be to either make the buffer one size bigger if it's a set size, or read in the string, and add the null character by hand
Upvotes: 1