Search code examples
cunixposixstdingetchar

Read all data from stdin C


I've wrote this small function to read all the data from stdin.

I need to know if this function is POSIX compatible (by this, I mean it will work under Unix and Unix-like systems) at least it works on Windows...

char* getLine()
{
    int i = 0, c;
    char* ptrBuff = NULL;

    while ((c = getchar()) != '\n' && c != EOF)
    {
        if ((ptrBuff = (char*)realloc(ptrBuff, sizeof (char)+i)) != NULL)
            ptrBuff[i++] = c;
        else
        {
            free(ptrBuff);
            return NULL;
        }
    }

    if (ptrBuff != NULL)
        ptrBuff[i] = '\0';

    return ptrBuff;
}

The function reads all the data from stdin until get '\n' or EOF and returns a pointer to the new location with all the chars. I don't know if this is the most optimal or safer way to do that, and neither know if this works under Unix and Unix-like systems... so, I need a little bit of help here. How can I improve that function? or is there a better way to get all the data from stdin without leaving garbage on the buffer? I know that fgets() is an option but, it may leave garbage if the user input is bigger than expected... plus, I want to get all the chars that the user has written.

EDIT:

New version of getLine():

char* readLine()
{
    int i = 0, c;
    size_t p4kB = 4096;
    void *nPtr = NULL;
    char *ptrBuff = (char*)malloc(p4kB);

    while ((c = getchar()) != '\n' && c != EOF)
    {
        if (i == p4kB)
        {
            p4kB += 4096;
            if ((nPtr = realloc(ptrBuff, p4kB)) != NULL)
                ptrBuff = (char*)nPtr;
            else
            {
                free(ptrBuff);
                return NULL;
            }
        }
        ptrBuff[i++] = c;
    }

    if (ptrBuff != NULL)
    {
        ptrBuff[i] = '\0';
        ptrBuff = realloc(ptrBuff, strlen(ptrBuff) + 1);
    }

    return ptrBuff;
}

LAST EDIT:

This is the final version of the char* readLine() function. Now I can't see more bugs neither best ways to improve it, if somebody knows a better way, just tell me, please.

char* readLine()
{
    int c;
    size_t p4kB = 4096, i = 0;
    void *newPtr = NULL;
    char *ptrString = malloc(p4kB * sizeof (char));

    while (ptrString != NULL && (c = getchar()) != '\n' && c != EOF)
    {
        if (i == p4kB * sizeof (char))
        {
            p4kB += 4096;
            if ((newPtr = realloc(ptrString, p4kB * sizeof (char))) != NULL)
                ptrString = (char*) newPtr;
            else
            {
                free(ptrString);
                return NULL;
            }
        }
        ptrString[i++] = c;
    }

    if (ptrString != NULL)
    {
        ptrString[i] = '\0';
        ptrString = realloc(ptrString, strlen(ptrString) + 1);
    } 
    else return NULL;

    return ptrString;
}

Solution

  • POSIX-compatible: yes!

    You're calling only getchar(), malloc(), realloc() and free(), all of which are standard C functions and therefore also available under POSIX. As far as I can tell, you've done all the necessary return code checks too. Given that, the code will be good in any environment that supports malloc() and stdin.