简体   繁体   中英

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.

scanf(" %[^\n]c", &temp) does not read a character that is not a new-line ( '\n' ). The [ is a conversion specifier by itself, and c does not go with it.

%[^\n] says to read any number of characters until a new-line is seen. The c is not part of the conversion, and its presence causes a matching failure in scanf .

To read one character that is not a new-line character, use %1[^\n] , as in scanf(" %1[^\n]", &temp);

Another solutions are:

  • Use %c in the scanf. Afterward, test the character and ignore it if it is a new-line character.
  • Change the code to use getchar instead of scanf .

Avoid testing with scanf(...) != EOF . scanf returns EOF only if an input failure occurs before the first conversion has completed. Otherwise, it returns the number of input items assigned. This may work in simple uses of scanf with only one item to assign. However, in general, you want to at least test whether scanf assigned the desired number of items, scanf(...) == 1 . Even better would be to save the return value and handle the multiple possible returns: EOF , a number less than the desired number of items, or the desired number of items.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM