Hello guys!
I made a thread here a few days ago and got very good feedback. It helped alot but I have stumpled upon a new problem in the same program. This is quite much code (atleast for me, hehe), and I understand if you dont have time to look at it.
Anyway, the problem is that I have a list with a struct in each position. The struct contains four strings; artist, album, type and rating.
I need the user to be able to sort the list depending on one of these columns. For that I will use merge sort. This is the code for the list:
Code:
#ifndef _DLIST_H
#define _DLIST_H
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#ifndef __DATA
#define __DATA
typedef void *data;
#endif
#ifndef __MEMFREEDATAFUNC
#define __MEMFREEDATAFUNC
typedef void memFreeFunc(data);
#endif
typedef struct link {
data data;
struct link *next;
} element;
typedef element * dlist_position;
struct list {
element *head;
memFreeFunc *freeFunc;
};
typedef struct list dlist;
dlist *dlist_empty(void);
void dlist_setMemHandler(dlist *l, memFreeFunc *f);
dlist_position dlist_first(dlist *l);
dlist_position dlist_next(dlist *l,dlist_position p);
bool dlist_isEmpty(dlist *l);
dlist_position dlist_insert(dlist *l,dlist_position p,data d);
dlist_position dlist_remove(dlist *l, dlist_position p);
void dlist_free(dlist *l);
data dlist_inspect(dlist *l, dlist_position p);
bool dlist_isEnd(dlist *l, dlist_position p);
#endif
Code:
#include "dlist.h"
dlist *dlist_empty(void) {
dlist *theList=malloc(sizeof(struct list));
theList->head=malloc(sizeof(element)); //huvudet för listan
theList->head->next=NULL;
theList->freeFunc=NULL;
return theList;
}
void dlist_setMemHandler(dlist *l, memFreeFunc *f) {
l->freeFunc=f;
}
dlist_position dlist_first(dlist *l) {
return l->head;
}
dlist_position dlist_next(dlist *l, dlist_position p) {
return p->next;
}
bool dlist_isEmpty(dlist *l) {
return (l->head->next==NULL);
}
dlist_position dlist_insert(dlist *l,dlist_position p,data d) {
dlist_position newPosition=malloc(sizeof(element));
newPosition->data=d;
newPosition->next=p->next;
p->next=newPosition;
return p;
}
data dlist_inspect(dlist *l, dlist_position p) {
return p->next->data;
}
dlist_position dlist_remove(dlist *l,dlist_position p) {
dlist_position temp=p->next;
p->next=p->next->next;
if(l->freeFunc!=NULL)
l->freeFunc(temp->data);
free(temp);
return p;
}
bool dlist_isEnd(dlist *l,dlist_position p) {
return (p->next==NULL);
}
void dlist_free(dlist *l) {
dlist_position p=dlist_first(l);
while(!dlist_isEmpty(l)) {
p=dlist_remove(l,p);
}
free (l->head);
free (l);
}
And here is the code which gives me trouble:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include "dlist.h"
#define BUFSIZE 90
typedef struct {
char artist[41];
char album[41];
char type[3];
char rating[5];
} record;
void printMenu();
void readFile(FILE *infilep, dlist *list);
void printText(dlist *list);
dlist *mergeSort(dlist *list);
/*dlist *merge(dlist *list1, dlist *list2);*/
int main(int argc, char *argv[]) {
int n;
if(argc < 1) {
fprintf(stderr, "Usage: %s <musik.txt>\n", argv[0]);
exit(1);
}
/* Öppna filen */
FILE * infilep;
infilep = fopen(argv[1],"r");
if (infilep == NULL) {
fprintf(stderr, "Couldn't open input file.");
exit(1);
}
/* Skapa listor och allokera minne */
dlist *list=dlist_empty();
/* Läs filen */
readFile(infilep, list);
/* Skriv ut meny */
printMenu();
do {
printf("\n\n Ange ditt val: ");
scanf("%d",&n);
switch (n) {
case -1: printf("Programmet avslutas\n\n"); return 0; break;
case 0: printMenu(); break;
case 1: printText(list); break;
case 2: mergeSort(list); break;
// case 3: merge(list1, list2); break;
default: printf("Ogiltigt val\n"); printMenu(); break;
}
} while (n != -1);
return 0;
}
/*
Funktion: printMenu
Beskrivning: Skriver ut menyn för programmet.
Input: -
Output: -
*/
void printMenu(void) {
printf("\nMENY:\n");
printf("0. Visa menyn\n");
printf("1. Visa lista\n");
printf("2. Sortera lista på artister\n");
printf("3. Sortera lista på album\n");
printf("4. Sortera lista på typ\n");
printf("5. Sortera lista på betyg\n");
printf("-1. Avsluta\n");
}
/*
Funktion: readFile
Beskrivning: Läser in data från filen.
Input: Datastukturen record och filpekaren infilep.
Output: -a
*/
void readFile(FILE *infilep, dlist *list) {
char line[BUFSIZE];
dlist_position pos;
pos=dlist_first(list);
/*Läs in information från musik.txt och spara
structs i listan */
while (fgets(line, BUFSIZE, infilep) != NULL) {
record *info = malloc(sizeof(record));
sscanf(line, "%[^;];%[^;];%[^;];%s",
info->artist, info->album,
info->type, info->rating);
pos = dlist_insert(list,pos,info);
pos = dlist_next(list,pos);
}
}
/*
Funktion: printText
Beskrivning: Skriver ut artist, album, typ och betyg
i kolumner på skärmen. Man kan välja att visa mer text.
Input: Riktad lista
Output: Utskriven text
*/
void printText(dlist *list) {
int n;
dlist_position pos;
pos = dlist_first(list);
printf("\nAnge hur många rader du vill visa:");
scanf("%d",&n);
printf("\nARTIST ALBUM TYP
/* Skriver ut det antal rader användaren bestämt */
for(int i = 0; i < n; i++) {
record *rcrd = (record*) dlist_inspect(list, pos);
printf("%-40s%-40s%-2s %-4s\n", rcrd->artist, rcrd->album, rcrd->type, rcrd->rating);
pos=dlist_next(list, pos);
if(dlist_isEnd(list, pos) == 1) {
printf("\n Listans slut.");
return;
}
}
}
/*
Funktion: mergeSort
Beskrivning: Delar upp den ursprungliga listan i två delar, där vartannat värde hamnar
i lista1, och vartannat i lista 2. Funktionen anropar sig själv så att två till listor skapas,
och slutar först när listorna bara har en position. Då skickas listorna vidare till
funktionen merge.
Input: Riktad lista
Output: Halverade listor
*/
dlist *mergeSort(dlist *list) {
dlist_position pos, pos1, pos2;
/* Skapa två nya listor */
dlist *list1 = dlist_empty();
dlist *list2 = dlist_empty();
/* Tag fram den första posititonen */
pos = dlist_first(list);
pos1 = dlist_first(list1);
pos2 = dlist_first(list2);
/* Allokera minne */
record *rec = malloc(sizeof(record));
/* Dela upp ursprungslistan i två nya listor */
if(!dlist_isEnd(list, pos)) {
while(!dlist_isEmpty(list)) {
rec = (record*) dlist_inspect(list, pos);
dlist_remove(list, pos);
dlist_next(list, pos);
dlist_insert(list1, pos1, rec);
dlist_next(list1, pos1);
if(!dlist_isEmpty(list)) {
rec = (record*) dlist_inspect(list, pos);
dlist_remove(list, pos);
dlist_next(list, pos);
dlist_insert(list2, pos2, rec);
dlist_next(list2, pos2);
}
}
}
/* Anropa mergeSort med de nya listorna */
list1 = mergeSort(list1);
list2 = mergeSort(list2);
/* Anropa merge med listorna */
merge(list1, list2);
/* Returnera den sorterade listan */
return(list);
}
The commenting is in swedish I'm afraid, but I hope you can get something out of it without the comments...
When I try to run the program it runs through the while-loop in mergeSort a few times but then I get a segmentation fault. I think it has to do with dlist_inspect trying to extract a struct when there is nothing to extract. But at the same time I thought I fixed that with the "!dlist_isEmpty(list)"...
Would love some help, if its possible.
Thanks