An interactive program that reads 3 list of numbers, which are stored
in three seperate files, and creates one sorted list. Each file should
contain not more than 15 numbers.
/* BEGIN new.c output */
FILE_1
1527239318
496027619
3472826252
3598182113
3148076786
1796534671
3248372296
FILE_2
1324866413
2920400654
309044219
3683030724
926430905
1233764074
2700036903
FILE_3
1369223424
8144069
4157315718
1601114899
587384060
4063891857
4244305378
Sorted Output File
8144069
309044219
496027619
587384060
926430905
1233764074
1324866413
1369223424
1527239318
1601114899
1796534671
2700036903
2920400654
3148076786
3248372296
3472826252
3598182113
3683030724
4063891857
4157315718
4244305378
/* END new.c output */
/* BEGIN new.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#define FIFTEEN 7
#define NMEMB(A) (sizeof (A) / sizeof *(A))
#define LU_RAND_SEED 123456789LU
#define LU_RAND(S) ((S) * 69069 + 362437 & 0XFFFFFFFFLU)
struct list_node {
struct list_node *next;
void *data;
};
typedef struct list_node list_type;
struct file_struct {
char *fn;
FILE *fp;
list_type *head, *tail;
};
list_type *list_sort(list_type *head,
int (*compar)(const list_type *, const list_type *));
void close_and_remove(struct file_struct *file, size_t nmemb);
void list_free(list_type *node, void (*free_data)(void *));
list_type *merge_lists(list_type *head, list_type *tail,
int (*compar)(const list_type *, const list_type *));
int list_fputs(list_type *node, FILE *stream);
list_type *append_string(list_type **head,
list_type *tail,
char *string);
int get_line(char **lineptr, size_t *n, FILE *stream);
int numcomp(const list_type *a, const list_type *b);
static list_type *node_sort(list_type *head,
int (*compar)(const list_type *, const list_type *));
static list_type *list_split(list_type *head);
static list_type *list_merge(list_type *head, list_type *tail,
int (*compar)(const list_type *, const list_type *));
int main(void)
{
struct file_struct file[] = {
{"FILE_1"}, {"FILE_2"}, {"FILE_3"}
};
size_t index, number;
long unsigned lu_seed;
int rc;
char *buff;
size_t size;
list_type *output;
FILE *fp;
char *fn = "out";
puts("/* BEGIN new.c output */\n");
output = NULL;
buff = NULL;
size = 0;
lu_seed = LU_RAND_SEED;
for (index = 0; index != NMEMB(file); ++index) {
file[index].fp = fopen(file[index].fn, "w");
if (file[index].fp == NULL) {
close_and_remove(file, index);
puts("fopen(file[index].fn, \"w\") == NULL");
exit(EXIT_FAILURE);
}
for (number = 0; number != FIFTEEN; ++number) {
lu_seed = LU_RAND(lu_seed);
fprintf(file[index].fp, "%lu\n", lu_seed);
}
fclose(file[index].fp);
}
for (index = 0; index != NMEMB(file); ++index) {
file[index].fp = fopen(file[index].fn, "r");
if (file[index].fp == NULL) {
close_and_remove(file, index);
printf("fopen(%s, \"r\") == NULL", file[index].fn);
exit(EXIT_FAILURE);
}
while ((rc = get_line(&buff, &size, file[index].fp)) > 0) {
file[index].tail = append_string
(&(file[index].head), file[index].tail, buff);
if (file[index].tail == NULL) {
puts("file[index].tail == NULL");
break;
}
}
puts(file[index].fn);
list_fputs(file[index].head, stdout);
putchar('\n');
file[index].head = list_sort(file[index].head, numcomp);
output = merge_lists(output, file[index].head, numcomp);
}
free(buff);
close_and_remove(file, NMEMB(file));
puts("Sorted Output File");
list_fputs(output, stdout);
putchar('\n');
fp = fopen(fn, "w");
if (fp == NULL) {
printf("NULL = fopen(%s, \"w\")", fn);
}
list_fputs(output, fp);
list_free(output, free);
fclose(fp);
remove(fn);
puts("/* END new.c output */");
return 0;
}
void close_and_remove(struct file_struct *file, size_t nmemb)
{
while (nmemb-- != 0) {
fclose(file[nmemb].fp);
remove(file[nmemb].fn);
}
}
list_type *list_sort(list_type *head,
int (*compar)(const list_type *, const list_type *))
{
return head != NULL ? node_sort(head, compar) : head;
}
void list_free(list_type *node, void (*free_data)(void *))
{
list_type *next_node;
while (node != NULL) {
next_node = node -> next;
free_data(node -> data);
free(node);
node = next_node;
}
}
list_type *merge_lists(list_type *head, list_type *tail,
int (*compar)(const list_type *, const list_type *))
{
if (tail != NULL) {
if (head != NULL) {
head = list_merge(head, tail, compar);
} else {
head = tail;
}
}
return head;
}
int list_fputs(list_type *node, FILE *stream)
{
while (node != NULL) {
if (fputs(node -> data, stream) == EOF) {
return EOF;
}
if (putc('\n', stream) == EOF) {
return EOF;
}
node = node -> next;
}
return '\n';
}
list_type *append_string(list_type **head,
list_type *tail,
char *string)
{
list_type *node;
node = malloc(sizeof *node);
if (node != NULL) {
node -> next = NULL;
node -> data = malloc(strlen(string) + 1);
if (node -> data != NULL) {
strcpy(node -> data, string);
if (*head != NULL) {
tail -> next = node;
} else {
*head = node;
}
} else {
free(node);
node = NULL;
}
}
return node;
}
int get_line(char **lineptr, size_t *n, FILE *stream)
{
int rc;
void *p;
size_t count;
count = 0;
while ((rc = getc(stream)) != EOF) {
if (count != (size_t)-2) {
++count;
}
if (count + 2 > *n) {
p = realloc(*lineptr, count + 2);
if (p == NULL) {
if (*n > count) {
if (rc != '\n') {
(*lineptr)[count] = '\0';
(*lineptr)[count - 1] = (char)rc;
} else {
(*lineptr)[count - 1] = '\0';
}
} else {
if (*n != 0) {
**lineptr = '\0';
}
ungetc(rc, stream);
}
count = 0;
break;
}
*lineptr = p;
*n = count + 2;
}
if (rc == '\n') {
(*lineptr)[count - 1] = '\0';
break;
}
(*lineptr)[count - 1] = (char)rc;
}
if (rc != EOF) {
rc = INT_MAX > count ? count : INT_MAX;
} else {
if (*n > count) {
(*lineptr)[count] = '\0';
}
}
return rc;
}
int numcomp(const list_type *a, const list_type *b)
{
const long unsigned a_num = strtoul(a -> data, NULL, 10);
const long unsigned b_num = strtoul(b -> data, NULL, 10);
return b_num > a_num ? -1 : b_num != a_num;
}
static list_type *node_sort(list_type *head,
int (*compar)(const list_type *, const list_type *))
{
list_type *tail;
if (head -> next != NULL) {
tail = list_split(head);
tail = node_sort(tail, compar);
head = node_sort(head, compar);
head = list_merge(head, tail, compar);
}
return head;
}
static list_type *list_split(list_type *head)
{
list_type *tail;
tail = head -> next;
while ((tail = tail -> next) != NULL
&& (tail = tail -> next) != NULL)
{
head = head -> next;
}
tail = head -> next;
head -> next = NULL;
return tail;
}
static list_type *list_merge(list_type *head, list_type *tail,
int (*compar)(const list_type *, const list_type *))
{
list_type *list, *sorted, **node;
node = compar(head, tail) > 0 ? &tail : &head;
list = sorted = *node;
*node = sorted -> next;
while (*node != NULL) {
node = compar(head, tail) > 0 ? &tail : &head;
sorted -> next = *node;
sorted = *node;
*node = sorted -> next;
}
sorted -> next = tail != NULL ? tail : head;
return list;
}
/* END new.c */