Here's what I came up. I'm not sure if my implementation of the seek algorithm is the best.
list.c:
Code:
#include <stdio.h>
#include <stdlib.h>
/* a linked list of line fragments */
typedef struct foo_tag {
char buff[10];
struct foo_tag *next;
} foo;
foo *newnode ( void ) {
foo *new = malloc ( sizeof *new );
if ( new ) {
new->next = NULL;
}
return new;
}
foo *read_long_line ( FILE *fp, int *num_nodes ) {
foo *head = NULL, *tail = NULL;
foo *this = NULL;
char *eol;
*num_nodes = 1;
this = newnode();
while ( this && fgets( this->buff, sizeof this->buff, fp ) != NULL ) {
if ( head == NULL ) {
head = tail = this;
} else {
tail->next = this;
tail = this;
}
if ( !(eol = strchr(this->buff,'\n') )) {
this = newnode(); /* no newline yet - prepare for more */
(*num_nodes)++;
} else {
*eol = 0; // replace newline with NULL character
this = NULL; /* th th that's all folks */
}
}
free( this );
return head;
}
void print_long_line ( foo *line ) {
while ( line ) {
printf( "'%s'\n", line->buff );
line = line->next;
}
}
char *pack_line(foo *line, int num_nodes)
{
foo *head = line;
char *ln = (char *) malloc(num_nodes*9 + 1); // buff holds nine char string
int length, i, j = 0;
while(head)
{
length = strlen(head->buff);
for(i = 0; i < length; i++, j++)
ln[j] = head->buff[i];
head = head->next;
}
ln[j] = '\0';
return ln;
}
int main (int argc, char **argv) {
FILE *fp;
int num_nodes;
char *line;
int i;
foo *myline;
for(i = 0; i < 10; i++)
{
fp = fopen(argv[1], "r");
while((myline = read_long_line( fp, &num_nodes )))
{
line = pack_line(myline, num_nodes);
printf("%s\n", line);
free(line);
}
fclose(fp);
}
return 0;
}
seek.c:
Code:
#include <stdio.h>
char *getline(FILE *fp)
{
char *line;
char ch;
int start;
int end;
start = ftell(fp); // get the initial file pointer
do
{
fread(&ch, 1, 1, fp);
}while(!feof(fp) && ch != '\n');
if(feof(fp))
return (char *) 0;
end = ftell(fp);
fseek(fp, -(end - start), SEEK_CUR); // go back to where start was
line = (char *) malloc(end - start);
fgets(line, end - start, fp);
fseek(fp, 1, SEEK_CUR); // move ahead of the newline character
return line;
}
int main(int argc, char *argv[])
{
FILE *fp;
char *line;
int i;
for(i = 0; i < 10; i++)
{
fp = fopen(argv[1], "r");
while((line = getline(fp)))
{
printf("%s\n", line);
free(line);
}
fclose(fp);
}
return 1;
}
Results:
ymalik-> gcc -o seek seek.c
ymalik-> gcc -o list list.c
ymalik-> /usr/bin/time ./seek b
...
9.96 real 0.88 user 0.25 sys
ymalik-> /usr/bin/time ./list b
...
9.74 real 0.64 user 0.25 sys