#include #include #include #include struct item { char *string; int line; struct item *next; }; int main(int argc, char **argv) { FILE *ff; // The input file char line[1024]; // The input line struct item *head=NULL; // The top of the linked list struct item *ptr; // A temp pointer for wizzing down lists int lineno=0; // which line number /* there is always 1 argc, the program name argv[0] */ if (argc<2) { /* Moan if we don't get given a file name */ fprintf(stderr, "Hey, gimme a file name!\n"); exit(1); } if ((ff=fopen(argv[1], "r"))==NULL) { /* moan about it, but include the real Error message */ fprintf(stderr, "Whoops, file '%s' said %s\n", argv[1], strerror(errno)); exit(1); } while (!feof(ff) && fgets(line, 1024, ff)!=NULL) { struct item *new; char *c; /* chop the end off the line */ if ((c=strchr(line, '\n'))!=NULL) *c=0; if ((c=strchr(line, '\r'))!=NULL) *c=0; /* make a new structure */ new = malloc( sizeof(struct item) ); /* fill it in */ new->string = strdup( line ); new->line=lineno; /* stick it at the top of the list */ new->next=head; head=new; lineno++; } fclose(ff); /* now print it all out. It's in reverse order, because we inserted at the top of the list, like a stack */ /* because head was NULL to begin with, and we copied that to the next pointer each time, we know when we end up with a NULL again, so we're done, without needing to know how long the list was. This is also safe on empty lists */ ptr=head; while ( ptr!=NULL ) { printf ("%d: %s\n", ptr->line, ptr->string); ptr=ptr->next; } exit (0); }