While I agree with most of what's been said in the comments, I do think that writing your own linked list is a worthwhile exercise. (Though so is learning about reallocating arrays.) So I'll go with that premise - that it's worth your time to write a linked list. And I think you've done a pretty good job to start with! Here are some suggestions. **Don't Reinvent The Wheel** You've written your own functions for `count_to_next()` and `string_copy()`. There are functions in the standard C library that do these same things, so you don't need to write your own. Instead, you could use [`strpbrk()`](http://www.techonthenet.com/c_language/standard_library_functions/string_h/strpbrk.php) and [`strdup()`](http://www.mkssoftware.com/docs/man3/strdup.3.asp) or `memcpy()`. `strdup()` actually allocates the memory for you, if you want to go that route. Edit: Also, instead of calling `malloc()` and then manually setting each field to `0`, you can use `calloc(sizeof(Node), 1);` to both allocate and clear the memory. **Use Types** You should create type definitions for your structures to make it easier to read and save some typing. I'd do this: typedef struct Node { void* value; struct Node* next; } Node; Then, whenever you declare one, you can simply write: Node *root; instead of: struct Node *root; **Avoid Magic Numbers** Instead of just putting the number `20` into your code, you should either have a named constant telling you what the value `20` represents (something like `const int TEST_STR_LENGTH = 20;`, or get the value from the string so you can change the string without having to update the value in the code. Like this: int remaining = strlen(raw); **Name Your Variables Appropriately** The variable names `raw`, `pointer`, and `buffer` aren't very informative. I recommend naming them something like `input_string`, `next_line`, and `string_copy` or something along those lines. **Bugs** I think the last line is incorrect. I think it should be: lines = root; Otherwise you're starting with the second line. Also, you were starting with an empty node with an uninitialized string, and ending with an empty node with an uninitialized string. I fixed the first by setting the `value` field of `last` before allocating a new node. I fixed the second by only allocating the next node if we have some characters remaining in the string. Edit: I also realized that both of our implementations have another bug in them. If the file (or input string) is empty, we end up with a list containing an empty node, whereas we probably should not have a list at all. You could fix that by not allocating a node until you know you have a string. So `root` would start out as NULL and could end up as NULL if there are no lines in the input. I'll leave that as an exercise for the reader. :-) So putting it all together, your function might look something like this: #include <stdlib.h> #include <string.h> typedef struct Node { void* value; struct Node* next; } Node; int main() { char *input_string = "Line 1\nLine 2\nLine 3"; long remaining = (long)strlen(input_string); long chunk_size; char *next_line = input_string; char *string_copy; Node *root = calloc(sizeof(Node), 1); Node *last = root; Node *lines = NULL; while (remaining > 0) { char* next_new_line = strpbrk(next_line, "\n"); /* If the string doesn't end with "\n", we need the rest of the string */ if (next_new_line == NULL) { chunk_size = remaining; } else { chunk_size = next_new_line - next_line; } /* This allocates and copies the string */ string_copy = strndup(next_line, chunk_size); last->value = (void *) string_copy; /* + 1 bc the '\n' is ignored */ remaining -= chunk_size + 1; next_line += chunk_size + 1; /* If there's more, then allocate another node for the next go round */ if (remaining > 0) { last->next = calloc(sizeof(Node), 1); last = last->next; } } lines = root; /* do something with lines */ } Oh, and don't forget to `free()` all those strings and `Node`s after you've used them!