Reputation: 17
Iam trying to fill array with numbers that i converted from int to string. The output iam trying to get is {"0", "1", "2"...} but my array is filled with the last number that i converted {"19", "19", "19"..} idk why is that. Could you please help me guys ?
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *arr[20] = {};
for(int i = 0;i < 20;i++){
char str[20];
itoa(i, str, 10);
arr[i] = str;
}
for(int i = 0;i < 20;i++){
printf("%s\n", arr[i]);
}
}
Upvotes: 1
Views: 103
Reputation: 2930
you need to allocate memory for each place in the array, arr
. you can do this on the stack
or on the heap
. In this approach i have allocated the strings on the heap
. So i called malloc()
for allocating buffers of size int
(no need to allocate more).
In my approach i have used sprintf()
from stdio.h
to convert the numbers to string format.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_INT_DIGITS_NUM 20
int main() {
char* arr[20]; /*this is an array of 20 char pointers*/
for(int i = 0;i < 20;i++){
arr[i] = (char*)malloc(sizeof(char) * MAX_INT_DIGITS_NUM);
sprintf(arr[i], "%d", i);
}
for(int i = 0;i < 20;i++){
printf("%s\n", arr[i]);
/*now you need to free all previous allocated buffers*/
free(arr[i]);
}
return 0;
}
what is wrong with your code?
arr
is only an array to char pointers
! its not really holding string buffers
that you can use for copy or scan to it! its only pointers that points to some address.
inside the for
loop, you are declaring str buffer
and you keep override it (itoa keeps copying to it) to the same place!! hence you exit the for loop in last iteration with only the last converted i
!
now, just to aware you, after existing the for loop
all the local variables marked by the os as released
! so this can lead to memory corruption or override later in the program!
keep in mind that in my solution i always allocates MAX_INT_DIGITS_NUM
bytes, no matter the i
deget length. this is waste of memory! keep in mind that itoa()
is not standard in C
or ansi c
!
Upvotes: 0
Reputation: 2398
Problem
char str[20];
arranges that str
is a pointer to the first element of a chunk of memory containing 20 char
s. Since the str
is a local variable to the for
loop, you cannot be sure what happens to that memory after the current iteration finishes. It is undefined behaviour.
With that in mind, think about what arr
will be at the the end of the first for
loop.
It will be an array of 20 pointers to some bit of memory. But you can no longer be sure what the memory contains. It may be, as in your case, that they all point to the same bit of memory, which is filled with the last string that itoa
put there. This might not happen in general though.
Solution
To fix this, you should probably use malloc
to allocate new memory for each string you want to keep, within the first for
loop. The memory is then heap allocated, and you can be sure that each call to malloc
will give you a chunk of unused memory, such that you won't be overwriting previous strings. Try for example:
for(int i = 0;i < 20;i++){
char *str = (char *) malloc(sizeof(char) * 20);
itoa(i, str, 10);
arr[i] = str;
}
Note that it is also good practice to explicitly free
memory you have allocated with malloc
.
Upvotes: 2
Reputation: 6724
char str[20];
creates a single location in memory where str
is stored. It does not create a new location each time the loop is run.
arr[i] = str;
points each element of arr
at that one location, which by the end of the loop contains just "19".
Instead of arr[i] = str;
you need to do something like strcpy(arr[i], str)
to copy the current contents of str
to the appropriate element of arr
.
Also, as Scott Hunter pointed out, you should declare arr
using char arr[20][20]
to have 20 unique char arrays to actually write the strings into.
I tested the following code (changed itoa
to sprintf
) and it worked for me:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char arr[20][20] = {};
for(int i = 0;i < 20;i++){
char str[20];
sprintf(str, "%i", i);
strcpy(arr[i], str);
}
for(int i = 0;i < 20;i++){
printf("%s\n", arr[i]);
}
}
Upvotes: 1
Reputation: 3041
Unrolling the loop, you get
arr[0] = str;
....
arr[1] = str;
....
arr[2] = str;
.... // etc
Which is basically:
arr[0] = arr[1] = arr[2] = arr[3] (...) = str;
So yeah, they all point to the same string. There is only one str
.
There's also some undefined behaviour here. Firstly, all of your pointers arr[0]
etc are being dereferenced here:
printf("%s\n", arr[i]);
when the thing they point to, str
, has gone out of scope, there is no guarantee what might happen when you access it. Infact, the first "instance" of str
goes out of scope at the end of the first iteration of the first loop. When you assign arr[1]=str
, arr[0]
is techincially invalid already. However, it likely that there is just one str
that remains on the stack for the duration of the function, which would be consistent with the observed behaviour, but not guaranteed.
Try this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char arr[20][20] = {}; // Allocate the space to store the results
for(int i = 0;i < 20;i++){
char str[20]; // Temp store
itoa(i, str, 10);
strcpy (arr[i], str); // Copy the string from the temp store
// str goes out of scope NOW at the end of the loop, you cannot
// any pointer that points to it either outside this loop or the next time
// around the loop
}
// etc
Upvotes: 0