Cool problem, here's a quick and dirty solution I came up with to see how it might be done
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DELIM " =;"
enum { NAME_MARKER = '$', STR_MARKER = '\"', DBL_MARKER = '.' };
enum { STRING, DOUBLE, INT };
struct file_fields {
struct file_fields *next;
char *name;
int field;
union field_value {
double d;
char s[BUFSIZ];
int i;
} value;
};
void cleanup(struct file_fields *list);
int main(void)
{
FILE *in;
char buf[1000];
struct file_fields *head;
struct file_fields *it;
in = fopen("input.txt", "r");
if (in == NULL)
{
perror("File couldn't be opened");
exit(EXIT_FAILURE);
}
head = malloc(sizeof (*head));
if (head == NULL)
{
fprintf(stderr, "Memory exhausted\n");
cleanup(head);
}
it = head;
while (fgets(buf, sizeof (buf), in))
{
char *t;
char *newline;
it->next = malloc(sizeof (*head));
if (it->next == NULL)
{
fprintf(stderr, "Memory exhausted\n");
cleanup(head);
}
it = it->next;
newline = strrchr(buf, '\n');
if (newline)
*newline = '\0';
for (t = strtok(buf, DELIM); t; t = strtok(NULL, DELIM))
{
if (*t == NAME_MARKER)
{
it->name = malloc(strlen(t) + 1);
if (it->name == NULL)
{
fprintf(stderr, "Memory exhausted\n");
cleanup(head);
}
strcpy(it->name, t);
}
else
{
/* Not a name, must be a value */
if (*t == STR_MARKER)
{
it->field = STRING;
strncpy(it->value.s, t, BUFSIZ);
}
else if (strchr(t, DBL_MARKER))
{
it->field = DOUBLE;
it->value.d = strtod(t, NULL);
}
else
{
it->field = INT;
it->value.i = strtol(t, NULL, 0);
}
}
}
}
for (it = head->next; it; )
{
int i;
struct file_fields *save;
save = it;
for (i = 1; it && i % 6; i++)
{
printf("%-15s", it->name);
fflush(stdout);
it = it->next;
}
printf("\n");
it = save;
for (i = 1; it && i % 6; i++)
{
switch (it->field)
{
case STRING:
printf("%-15s", it->value.s);
break;
case DOUBLE:
printf("%-15g", it->value.d);
break;
case INT:
printf("%-15d", it->value.i);
break;
}
it = it->next;
}
printf("\n\n");
}
cleanup(head);
return 0;
}
void cleanup(struct file_fields *list)
{
struct file_fields *forward;
while (list)
{
forward = list->next;
free(list->name);
free(list);
list = forward;
}
exit(0);
}
And yes, I know main is way too long.