Andy Elvey wrote:
>
> On Jul 5, 4:13 pm, pete <pfil...@mindspring.com> wrote:
> > Andy Elvey wrote:
> >
> > > Hi all -
> > > I've been poking around with C for a while, but I have big problems
> > > with linked lists. This seems to be mainly around the "declaration,
> > > initialisation, iterating" area. Anyway, I have the code below, which
> > > compiles but gives a segfault (and I have no idea why), so hoping that
> > > someone may be able to help.
> > > ( I have three puts statements at the end because I'm unsure how to
> > > iterate along a list. )
> > > [code]
> > > /* This code is released to the public domain */
> > > #include <ctype.h>
> > > #include <stdio.h>
> > > #include <stdlib.h>
> > > #include <string.h>
> > > #include <sys/stat.h>
> >
> > > /* Linked list implementation */
> > > typedef struct _List List;
> >
> > > struct _List {
> > > void *data;
> > > List *next;
> > > };
> >
> > > static List *list_malloc (void)
> > > {
> > > return (List *) malloc (sizeof (List));
> > > }
> >
> > > List *list_prepend (List *list, void *data)
> > > {
> > > List *ret = list_malloc ();
> > > ret->data = data;
> > > ret->next = list;
> > > return ret;
> > > }
> >
> > > List *list_append (List *list, void *data)
> > > {
> > > List *ret;
> > > if (list == NULL) return list_prepend (list, data);
> > > ret = list;
> > > for (; list->next; list = list->next);
> > > list->next = list_malloc ();
> > > list->next->data = data;
> > > list->next->next = NULL;
> > > return ret;
> > > }
> >
> > > void list_free (List *list)
> > > {
> > > List *next;
> > > while (list)
> > > {
> > > next = list->next;
> > > free (list);
> > > list = next;
> > > }
> > > }
> >
> > > /* End linked list implementation */
> >
> > > int main()
> > > {
> > > /* Declare a list */
> > > List *mylist = NULL;
> > > list_append(mylist, "foo");
> > > puts(mylist->data);
> > > list_append(mylist, (int*) 42);
> > > puts(mylist->data);
> > > list_append(mylist, "baz");
> > > puts(mylist->data);
> > > return 0;
> > > }
> > > [/code]
> > > Very many thanks if you can get this code working...... :)
> > > - Andy
> >
> > /* BEGIN new.c */
> >
> > #include <stdio.h>
> > #include <stdlib.h>
> > #include <string.h>
> >
> > /* Linked list implementation */
> > typedef struct LIST {
> > struct LIST *next;
> > void *data;
> >
> > } List;
> >
> > List *
> > list_append(List **head,
> > List *tail,
> > const void *data,
> > size_t size)
> > {
> > List *node;
> >
> > node = malloc(sizeof *node);
> > if (node != NULL) {
> > node -> next = NULL;
> > node -> data = malloc(size);
> > if (node -> data != NULL) {
> > memcpy(node -> data, data, size);
> > if (*head != NULL) {
> > tail -> next = node;
> > } else {
> > *head = node;
> > }
> > } else {
> > free(node);
> > node = NULL;
> > }
> > }
> > return node;
> >
> > }
> >
> > void
> > list_free(List *node, void (*free_data)(void *))
> > {
> > List *next_node;
> >
> > while (node != NULL) {
> > next_node = node -> next;
> > free_data(node -> data);
> > free(node);
> > node = next_node;
> > }
> >
> > }
> >
> > int
> > list_fputs(List *node, FILE *stream)
> > {
> > int rc = 0;
> >
> > while (node != NULL
> > && (rc = fputs(node -> data, stream)) != EOF
> > && (rc = putc( '\n', stream)) != EOF)
> > {
> > node = node -> next;
> > }
> > return rc;
> >
> > }
> >
> > /* End linked list implementation */
> >
> > int
> > main(void)
> > {
> > /* Declare a list */
> > List *mylist = NULL;
> > List *tail = NULL;
> > char *w[] = {"foo", "bar", "bazooka"};
> > char **p = w;
> >
> > do {
> > tail = list_append(&mylist, tail, *p, 1 + strlen(*p));
> > } while(tail != NULL && ++p != w + sizeof w / sizeof *w);
> > puts("/* BEGIN new.c output */\n");
> > list_fputs(mylist, stdout);
> > list_free(mylist, free);
> > puts("\n/* END new.c output */");
> > return 0;
> >
> > }
> >
> > /* END new.c */
> >
> > --
> > pete
>
> Many thanks for that, Pete! That code is the best that I've seen for
> a linked list!
> It's good to see some code that's easy to understand.
> Thanks again - bye for now -
You're welcome.
You can also use the same list_append() and list_free()
functions for other data types as well.
/* BEGIN new.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Linked list implementation */
typedef struct LIST {
struct LIST *next;
void *data;
} List;
List *
list_append(List **head,
List *tail,
const void *data,
size_t size)
{
List *node;
node = malloc(sizeof *node);
if (node != NULL) {
node -> next = NULL;
node -> data = malloc(size);
if (node -> data != NULL) {
memcpy(node -> data, data, size);
if (*head != NULL) {
tail -> next = node;
} else {
*head = node;
}
} else {
free(node);
node = NULL;
}
}
return node;
}
void
list_free(List *node, void (*free_data)(void *))
{
List *next_node;
while (node != NULL) {
next_node = node -> next;
free_data(node -> data);
free(node);
node = next_node;
}
}
int
list_int_fprintf(List *node, FILE *stream)
{
int rc = 0;
while (node != NULL
&& (rc = fprintf(stream, "%d\n", *(int *)node->data)) > 0)
{
node = node -> next;
}
return rc;
}
/* End linked list implementation */
int
main(void)
{
/* Declare a list */
List *mylist = NULL;
List *tail = NULL;
int i[] = {1, 2, 42};
int *p = i;
do {
tail = list_append(&mylist, tail, p, sizeof *p);
} while(tail != NULL && ++p != i + sizeof i / sizeof *i);
puts("/* BEGIN new.c output */\n");
list_int_fprintf(mylist, stdout);
list_free(mylist, free);
puts("\n/* END new.c output */");
return 0;
}
/* END new.c */
--
pete