Search code examples
cloopsscanfc-stringsrealloc

Weird character after realloc


I am writing a program which takes in user input character by character and print it out at the end:

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


#define FACTOR 2

int main(void) {

    printf("Enter line: ");
    int curr_size = 10;
    char curr_char = 0;
    char *ptr = malloc(curr_size * sizeof(char));
    int num_of_chars = 0;

    while (1) {
        int res = scanf(" %c", &curr_char);
        if (res == EOF) {
            break;
        }
        if (res != 1) {
            printf("Error: %c is not a character", res);
            break;
        }
        if (num_of_chars == curr_size) {
            curr_size = FACTOR * curr_size;
            ptr = realloc(ptr, curr_size);
        }

        ptr[num_of_chars] = curr_char;
        num_of_chars++;
    }

    printf("%s\n", ptr);
    return 0;
}

However, I notice that whenever I enter a line more than 10 characters (which trigger realloc), there is a unknown character appended at the end of my line when outputing:

output image, cant display that character on paste
If I change ptr[num_of_chars] = curr_char; to *(ptr + num_of_chars) = curr_char; the character disappear, may I know why and how to fix it? Thanks in advance.


Solution

  • Taking into account this if statement

        if (res == EOF) {
            break;
        }
    

    the following if statement

        if (res != 1) {
            printf("Error: %c is not a character", res);
            break;
        }
    

    does not make sense. Moreover you are trying to output an integer returned by the function scanf as a character.

    In general the function realloc can return NULL. In this situation there will be a memory leak because the previous value of the pointer ptr was overwritten

    ptr = realloc(ptr, curr_size);
    

    and this statement

        ptr[num_of_chars] = curr_char;
    

    will invoke undefined behavior.

    Also you are trying to output the character array as a string

    printf("%s\n", ptr);
    

    but you did not append the array with the terminating zero character.

    You should in this case use the call at least like

    printf("%*.*s\n", num_of_chars, num_of_chars, ptr);
    

    or you have to append the terminating zero character.

    And you should free the allocated memory.

    The program can look like

    #include <stdio.h>
    #include <stdlib.h>
    
    #define FACTOR 2
    
    int main(void) 
    {
        size_t curr_size = 10;  
    
        char *ptr = malloc( curr_size * sizeof( char ) );
        ptr[0] = '\0';
        char c;
    
        printf( "Enter line: " );
    
        size_t i = 0;
        for ( ; scanf( "%c", &c ) == 1 && c != '\n'; i++ )
        {
            if ( i == curr_size )
            {
                char *tmp = realloc( ptr, curr_size * FACTOR );
    
                if ( tmp == NULL ) break;
    
                curr_size *= FACTOR;
                ptr = tmp;
            }
    
            ptr[i] = c;
        }
    
    //  i == curr_size ? ptr[i-1] = '\0' : ( ptr[i] = '\0' );
    
    //  puts( ptr );
    
        printf( "%*.*s", ( int )i, ( int )i, ptr );
    
        free( ptr );
    
        return 0;
    }