Search code examples
cfgetsc-stringscalloc

How to create a function to that returns next line of input in C


I'm pretty new to C, so as part of my learning I want to make a function that simply returns a string which is the next line in the input without any arguments needed.

This is what I have so far:

#define BUFFER 256
char *str;
char *getline()
{
    if (str == 0)
        str = (char*)calloc(BUFFER, sizeof(char));
    if (fgets(str, BUFFER, stdin) != 0)
    {
        size_t len = strlen(str);
        if (len > 0 && str[len-1] == '\n')
            str[len-1] = '\0';
        return str;
    }
    return 0;
}

Now, is this the best way to do such thing? Is there a better way you can thing of? If it is the best way, where should I free what I've allocated with calloc?


Solution

  • This works, but here are some notes to keep in mind:

    • Don't cast the return value of malloc().

    • You don't even need calloc() - fgets() NUL-terminates the string.

    • Even better, use a static array.

    • Don't use global variables. Declare str with static storage duration instead.

    • Instead of 256, use LINE_MAX - how come a line can only be shorter than 256 characters?

    • getline() is the name of a function in the POSIX C library. Rename your function to avoid name collision.

    • Check if malloc() failed!

    • Don't forget to free() the return value of the function after having read the last line if you use the approach with dynamic memory management.

    • The check for the newline ending can be simplified like this:


    char *p = strchr(str, '\n');
    if (p)
        *p = 0;
    

    All in all, the function I would write is something like this:

    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <limits.h>
    
    char *my_getline_stdin()
    {
        static char buf[LINE_MAX];
    
        if (fgets(buf, sizeof(buf), stdin)) {
            char *p = strchr(buf, '\n');
            if (p)
                *p = 0;
    
            return buf;
        }
    
        return NULL;
    }