Search code examples
cscanfdynamic-memory-allocation

Reading input input into a char pointer with scanf


What I want to do here is, I want to read input from a user with scanf into a char pointer and dynamically allocate memory as more input is read.

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

int main()
{
    char *ptr, temp;
    int i, ind = 0;

    ptr = malloc(sizeof(char) * 2);

    while (scanf(" %[^\n]c", &temp) != EOF)
    {
        ptr[ind] = temp;
        ind++;
        ptr = realloc(ptr, sizeof(char) * (ind + 1));
    }

    for (i = 0; i < 5; i++)
        printf("%c", *(ptr + i));

    return 0;
}

My code is like this, however it either throws a segmentation error (when the number of character in one line is more than 8) or does not even print any characters. What am I missing? Thanks in advance.


Solution

  • Adding to Eric's answer, your code could be better without scanf(). Here is a getchar() solution:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        int c = 0; /* int so it can hold the EOF value */
        size_t ind = 0, i = 0;
        char *buff = NULL, *tmp = NULL;
    
        buff = malloc(2); /* sizeof char is 1 */
    
        if (buff == NULL) /* malloc failed */
        {
            exit(EXIT_FAILURE);
        }
    
        while (1)
        {
            c = getchar();
    
            if (c == EOF || c == '\n')
            {
                break;
            }
    
            buff[ind++] = (char)c; /* maybe check for overflow here, for non ascii characters */
    
            /* can use ctype functions or just manually compare with CHAR_MIN and CHAR_MAX */
    
            tmp = realloc(buff, ind + 2);
    
            if (tmp == NULL) /* reallloc failed */
            {
                fprintf(stderr,"Out of memory\n");
                exit(EXIT_FAILURE);
            }
    
            buff = tmp;
        }
    
        /* --------- NULL terminate if you are looking for a string  */
    
        /* buff[ind] = 0;                                            */
    
        /* --------------------------------------------------------- */
    
        for (; i < ind; i++)
        {
            putchar(*(buff + i));
        }
    
        free(buff);
    
        return 0;
    }
    

    I would like add that multiple realloc() calls, isn't really a sufficient practice. The better approach, would be initially allocate an X amount of memory with malloc() and if you need more, then use realloc() with an appropriate size.