1

I'm trying to generate the following output:

0.1

0.12

0.123

0.1234

...

0.123456789

My code uses string/char arrays and some pointer data types that I'm not familiar with.

Code was taken from here to help get started, but I get the following output of gibberish.

CMD Output

Here is the code:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main()
{
    char *str = "0.";
    char digit = '0';

    size_t len = strlen(str);

    int i = 1;


    while(i<10)
    {
        printf("i: %d\n",i);
    
        char *temp = malloc(len + 1 + 1);
    
        len = strlen(temp);
    
        digit = i + '0';
    
        temp[len] = digit;
    
        char string[len];
    
        strcpy(string,temp);
    
        free(temp);
    
        printf("%s\n\n",string);
    
        i = i +1;
    }
}

What needs to be modified to get the data types to work correctly together?

snowg
  • 15
  • 4
  • 3
    `temp` points to the `malloc` allocated memory but no string is stored in it, so `strlen(temp)` will result in some random value... – isrnick Aug 21 '20 at 04:23

2 Answers2

1

As already pointed out by @isrnick, the problem is that you allocate memory but don't initialize it before calling strlen.

It is in general not a good idea to repeatedly alloc/free memory as it fragments the heap. It is better to allocate once in the beginning, reuse the memory and free it in the end.

A better and neater solution would be to keep it on the stack:

#include <stdio.h>

int main()
{
    char str[64] = "0.";

    for (int i = 1; i < 10; i++) {
        str[1 + i] = '0' + i;
        printf("%s\n", str);
    }

    return 0;
}

Output:

0.1
0.12
0.123
0.1234
0.12345
0.123456
0.1234567
0.12345678
0.123456789
Frode Akselsen
  • 616
  • 2
  • 8
  • 23
  • Do you think it would be better to keep it on the stack if you wanted the code to handle strings up to 100+ digits? – snowg Aug 21 '20 at 14:53
  • 1
    For small array lengths (<= 512) I would keep it on the stack, it's hard to give a general answer because it depends on your system and the application. It is in general bad to *repeatedly* alloc/free small amounts of memory. It fragments the memory and it's also harder to keep track of it (imagine a larger system with multiple files). It's better to allocate a single junk, reuse it and free it at the end. – Frode Akselsen Aug 21 '20 at 22:25
-1

As @ismick mentioned, temp points to unintialized memory and so can contain anything. A safer bet, especially for 0-terminated strings like C, is to use calloc.

It's also quite a bit simpler to use sprintf rather than strcpy.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main()
{
    char *str = "0.";

    size_t len = 2;

    for (int i = 1; i < 10; i++) {
        printf("i = %d\n", i);                                                                            
        len = len + 2;

        char *temp = calloc(len, sizeof(char));
        sprintf(temp, "%s%d", str, i); 
        if (i > 1) free(str); // string literal when i=1
        str = temp;
        printf("%s\n\n", str);
    }
    free(str);
}

A few new things here: for(int i = 1; i < 10; i++) or for(int i = 1; i < 10; i = i+1) are a handy shortcut for the common construction

int i = 1;

while (i < 10) {
  ....
  i = i + 1;
}

We use calloc to get a pointer to a block of memory that's initialized with 0; the second sizeof(char) parameter tells us to get a block that fits len-many chars.

We use sprintf(temp, "%s%d", str, i); to ease copying the previous value of str into this new block of memory plus the next digit, e.g. 0. ~~> 0.1 or 0.12 ~~> 0.123.

Finally, we set str = temp; to point str to the start of temp, so we don't lose the copied/concatenated string we just made using sprintf.

edit: add comments about code
edit 2: fixed the double free pointed out in the comments.

Eric Canton
  • 324
  • 2
  • 10