0

I was just experimenting and wondered why my attempt did not work (the program crashes).

#include <stdio.h>
#include <stdlib.h>  
int main(int argc, char **argv)
{
    
    char *list;
    list =  (char*)malloc(sizeof(char));
    char a;
    int i = 0;
    
    while ( (a =getchar()) !='\n'){
        
        list[i]= a;
        list = (char*)realloc(list,sizeof(char));
        ++i;
       
    } 
    
    printf("%s",list);
    free(list);
    
    
    return 0;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
visitor
  • 111
  • 5
  • 3
    Yes you can, but remember two things: First of all that strings in C are really called ***null-terminated** string*, which means a string of `x` elements need space for `x + 1` characters to fit the terminator (which you need to add at the of course); The second thing is that the size provided to `realloc` is the *new* size, in bytes. Not how much memory to add. – Some programmer dude Sep 03 '21 at 16:35
  • 3
    Note that [`getchar()` returns an `int`](https://stackoverflow.com/q/13694394/15168) and you should account for EOF as well as newline: `int a; … while ((a = getchar()) != EOF && a != '\n')`. You should probably add a newline to the format string in the `printf()` statement, too. It's also best to avoid repeatedly incrementing the amount of allocated space in a buffer by one — that gets expensive. Keep a track of the amount allocated, start with a small allocation (say 4 bytes) and double the size when you need more space. You can free the excess when your input is complete. – Jonathan Leffler Sep 03 '21 at 16:37
  • 1
    Afzel one more thing that's a good habit, I did not include it in the answer as it doesn't answer your direct question. And this always takes a long time to bite us and we've formed bad habits by the time it does. malloc and realloc can return null if there's a problem fetching more memory. So you should never just assume these commands worked. You don't need to pepper all your code with null checks. I've taken to making "constructor" functions whenever I use malloc and "destructors" when I want to free, the latter is especially useful with linked lists and nested structures. – Jessica Pennell Sep 03 '21 at 16:44
  • 2
    Don't cast the value returned by malloc: https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – William Pursell Sep 03 '21 at 16:44

1 Answers1

1

sizeof(char) is always 1. You need to multiply this by the length of your list.

To keep track of the size of your list it's best to use a size_t or an integer, e.g.

list = (char*)realloc(list,sizeof(char)*(i+2));

As @Ian Abbot mentions in the comments, we add 2 instead of 1 to make room for the null terminator (below).

Note : I am retaining your code style but please see the advice in the comments to your original question, this cast is not needed.

After your loop you also need a null terminator.

...

    }
    list[i] = 0;
Jessica Pennell
  • 578
  • 4
  • 14
  • 1
    Since `i` is incremented after the `realloc`, the realloc size should be `i+2` to allow room for both the character stored at `list[i]` and the null terminator at the end. (Your code would be OK if you also moved the `i++;` line to just before the `realloc`.) – Ian Abbott Sep 03 '21 at 17:05