eLov AMV
eLov AMV

Reputation: 17

Convert int to string, then fill the array with the converted elements

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

Answers (4)

AdamF
AdamF

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

L.Grozinger
L.Grozinger

Reputation: 2398

Problem

char str[20]; arranges that str is a pointer to the first element of a chunk of memory containing 20 chars. 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

mlibby
mlibby

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

Rodney
Rodney

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

Related Questions