Array elements overwritten by the last element
With the following code snippet, I am getting a very simple result. Why does the last value of an element overwrite all previous elements of the array? I suspect there is a bigger problem than just this tricky problem.
#include <stdio.h>
main()
{
int i, cases;
char num[1000000];
scanf("%d", &cases);
char* array[cases];
//store inputs in array
for(i=0; i<cases; i++)
{
scanf("%s", &num);
array[i] = #
}
//print out array items and their memory addresses
for(i=0; i<cases; i++)
{
printf("%d %s\n", i, array[i]); //print (array index) (array value)
printf("%d %p\n", i, &array[i]); //print (array index) (array address)
}
}
Inputs:
3 <-- number of lines to follow
0 <-- put in array[0]
1 <-- put in array[1]
2 <-- put in array[2]
Outputs
0 3 <-- why is this being overwritten with the last element?
0 0013BCD0
1 3 <-- why is this being overwritten with the last element?
1 0013BCD4
2 3
2 0013BCD8
a source to share
The result is a string array[i] = #
that you set the value of the element array[i]
to the address of the array num
; since it array
is a char array, I suspect it truncates your array address num
and the low byte is 3.
But. However, your char num [1000000] is a disgusting form and you shouldn't be doing it at all. Highlight the heap and choose a lower number, for heaven's sake. Also, scanf ("% s", & num) won't actually give you what you want. Here's a hint; use a getc () loop to read numbers; this avoids the need to preallocate the array for scanf ().
a source to share
Here is your corrected code:
#include <stdio.h>
main(void)
{
int i, cases;
scanf("%d", &cases);
char* array[cases];
//store inputs in array
for(i=0; i<cases; i++)
{
char *num = malloc(100000);
scanf("%s", num);
array[i] = num;
}
//print out array items and their memory addresses
for(i=0; i<cases; i++)
{
printf("%d %s\n", i, array[i]); //print (array index) (array value)
printf("%d %p\n", i, (void*)&array[i]); //print (array index) (array address)
}
return 1;
}
You can also use
char *num = calloc(100000, sizeof(char));
which is a little defensive. I don't know why you need 100000. You can do this dynamically using malloc. It will take more work, but very reliable.
What is hapenning in your code is that you store the string% s at address num, which does not change, and then assign array [i] to that element. Assigning in C is nothing more than storing the reference, you are not storing the element itself - that would be a waste of space. Since all the elements of the array point to an address (only store the link), the value in the address changes in this way, and this link, so they all change to 2 (not 3 as you pointed out in your post).
a source to share
Replace
//store inputs in array
for(i=0; i<cases; i++)
{
scanf("%s", &num);
array[i] = #
}
from
array[0] = num;
//store inputs in array
for(i=0; i<cases; i++)
{
scanf("%s", array[i]);
array[i+1] = array[i] + strlen(array[i]) + 1;
}
scan each line to the first available space in num[]
and set the next item array[]
to point to the next available space. Your strings printf()
will now work. The original scanned each line at the beginning num[]
.
Note: scanf()
with unadorned is %s
no worse than gets()
, because it does not limit the amount of data that will be covered. Don't use it in real code.
Replace
printf("%d %p\n", i, &array[i]); //print (array index) (array address)
from
printf("%d %p\n", i, (void*)(array[i])); //print (array index) (array address)
to actually print the addresses stored in a[]
, not the addresses of the items a[]
. The cast is required because it %p
expects a pointer to void
, so you must specify it.
a source to share
This is for the kind of thing that C ++ seems to do. Parsing user input and dynamic allocations are done more reliably and downwind. I can't think of a system where you have a UI like this where you can't switch to C ++.
Of course, if this is just a test excerpt from other code that is suffering from the problem, then of course ...
Your code suffers from several common C beginner mistakes and things that shouldn't be done today.
If I understand correctly, you want to keep the original sereval input lines (your example output is a little misleading because you are only showing numbers).
You are preparing an array to hold all pointers (examples) for strings, but you only save memory for one string. You need to do this for every line, so the case. To do something simple in terms of the "dynamic memory allocation" lesson, I recommend doing it like this: char* array[cases][10000];
This gives you random strings of 10K characters.
You probably also don't want to have separate pointers to array elements. This starts to make sense if you want to sort the elements of an array when those elements are larger than the pointers themselves. In this case, your performance gain is not to move (copy) large chunks, but only pointers (usually 4 bytes). In your case, int is also 4 bytes long. And you don't sort anyway :)
scanf()
dangerous to say the least. In your second application, you instruct it to write a string at the address of an array. This seems to be a simple mistake, but it can lead to a lot of problems. You probably want to do it like this: scanf("%d", &array[i]);
(Unfortunately, I don't have a compiler, so I'm not 100% sure). drop next line :)
Question to Markdown Professionals: Why is it so difficult to make LISTS in combination with CODE blocks?
a source to share