Linked list for array of movies I am attempting to create a Linked List where someone can enter in some movie titles and their rating for it. Here is what I have thus far:
#include &lt;stdio.h&gt;
#include &lt;stdbool.h&gt;
#include &lt;ctype.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;

#define TITLE_MAX 50
void mygets(char buffer[], size_t limit);

// linked list
struct film {
    char title[TITLE_MAX];
    int rating;
    struct film *next;
};

int main(void)
{
    struct film *head = NULL, *current = NULL;
    char tbuffer[TITLE_MAX];

    while (true) 
    {
        printf(&quot;Enter the name of the film (empty line to stop)\n&quot;);
        mygets(tbuffer, TITLE_MAX);
        if (*tbuffer=='\0') break;

        if (!head) 
            current = head = malloc (sizeof(struct film));
        else
            // assignment associates right-to-left so can do this trick
            current = current-&gt;next = malloc (sizeof(struct film));

        current-&gt;next = NULL;
        strcpy(current-&gt;title, tbuffer);
        printf(&quot;Now enter in your rating for it: &quot;);
        scanf(&quot;%d&quot;, &amp;(current-&gt;rating));
        for (int c; (c=getchar()) != '\n' &amp;&amp; c != EOF; ); // clean up garbage in scanf -- should probably write a function for this
    }

    // print the Linked List
    current = head;
    for (int i=1; current != NULL; current=current-&gt;next)
        printf(&quot;Linked List Item #%d: %s (Rating: %d)\n&quot;, 
                i++, current-&gt;title, current-&gt;rating
        );

    for(struct film *current=head, *next; current != NULL; current=next) {
        next = current-&gt;next;
        free(current);
    }

}

void mygets(char buffer[], size_t limit)
{
    // first non-space char until newline or EOF, 
    // eating any extra chars in buffer
    // will add \0 at the end, so will get up to N-1 chars

    int c, idx=0;
    bool started=false;
    while ((c=getchar()) != EOF &amp;&amp; c != '\n')
    {
        if (!started &amp;&amp; isspace(c));
        if (idx &lt; limit-1) 
            buffer[idx++] = c;
    }
    buffer[idx] = '\0';

}

How does it look so far? What can be improved? Additionally, in real-world implementations of a linked list, what sort of additional metadata is stored -- for example, things like List Size and such.
Also, how does the free look in there. For a linked list does it matter which direction I free the data?
Bugs

A quick bug: if (!started &amp;&amp; isspace(c)); has no effect.  Did you want continue; or something there?  As it is, you will store leading spaces in the buffer after all, which apparently is not what you want.
gcc -Wextra gives a warning, btw.
(Did you test the program on input lines with leading spaces?  I don't think it could ever have worked.)
And you currently have no way for started to ever become true...


Code quality improvements

mygets is not a great choice for your function name. A reader will incorrectly guess that it behaves like the standard fgets (or worse, the formerly standard gets), but it differs in that it (is supposed to) strip leading spaces.  I'd choose something more like get_film_title.  You could try to explain in the function name that it strips spaces but that may make it awkwardly long.

I'd split the three tasks of populating the list, printing it out, and freeing it, into three separate functions, instead of dumping them all in main.

The while (true) idiom with a break; makes the reader have to hunt through the loop body for the termination condition.  See if you can think of a clean way to restructure to avoid this.  If not, at least add a comment to explain when the loop will terminate.

See if you can restructure the if (!head) to avoid writing out the malloc call twice, which is a danger point if you eventually want to change it but miss updating both instances.

Some would suggest malloc(sizeof *current) instead of sizeof(struct film).  I don't have strong feelings either way, myself.

Any time you need a comment to explain a &quot;trick&quot;, where the comment is longer than the extra code it avoids having to type, you are probably trying to be too clever. (And I found it confusing even with the comment.) Just write out the two statements.

Consider moving the task of reading the rating and &quot;cleaning up the input stream&quot; into its own function.  It's awkward when some of the I/O work is farmed out to a subroutine (mygets) and some is left behind.

for (int c; ...): A for loop that doesn't need to do anything in either of the init-clause or the iteration-expression should probably just be a while.

In the printing code, it's nice to keep the for focused on the actual loop iterator, which here is current, rather than mixing it between current and i (and since the latter is not the iterator, it could use a different name).  And there's no need to bury the increment of i inside a statement that does something else.   I would write:


int film_number = 1;
for (current = head; current != NULL; current = current-&gt;next) {
    printf(&quot;...&quot;, film_number, current-&gt;title, current-&gt;rating);
    film_number++;
}


In the freeing code, why do you declare a new variable named current, shadowing the existing one?

The for loop and use of the variable next in the freeing code is maybe more clever than readable.  I would write more simply:


current = head;
while (current) {
    struct film *tmp = current;
    current = current-&gt;next;
    free(tmp);
}


I think your plan of freeing the list from beginning to end is fine.  With a single-linked list, it's not so easy to do it the other way.  (Unless you want to build a double-linked list instead.

Error checking on every input and memory allocation function.  Yes, it's boring, but essential for any real program, and even for toy programs it is very helpful for debugging.


Suggested enhancements

As to additional metadata: store only what you have a use for.  If  knowing the size or the last element becomes useful for your application, add it then.  But I don't suggest overdesigning a fully general and heavily featureful linked list for a specific program; if you want to reinvent a generic linked list container, that's a separate project (and one that might be better for a language that actually supports generic programming).

Using scanf to read user input is not ideal outside toy programs, as it makes it hard to detect and recover from improper input.  A better design is usually to read an entire input line and parse it out with sscanf.

Consider using dynamic allocation so as to allow the film titles to be of arbitrary length.  Otherwise the user who wants to rate The Englishman Who Went Up a Hill But Came Down a Mountain (57) is going to be peeved.

Command line programs that prompt for interactive input, and terminate on something like an empty line, are rare outside of toy examples.  For one thing, they are hard to adapt for batch processing or pipelines.  Useful command-line programs more often don't prompt, and read input until end-of-file is encountered.