Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PATH_MAX 256
//#include <conio.h>
//Delete the #include <conio.h> line and at the top, after the includes, write:
//Code:
//#define _MAX_PATH1 255
/* define a structure for an entry in an test question*/
typedef struct entry_s{
char* question;
char* a;
char* b;
char* c;
char* d;
char* answer;
struct entry_s* next;/* pointer to next element*/
struct entry_s* prev;/* pointer to previous element*/
}entry_t;
entry_t* head=NULL;/* always points at first element*/
entry_t* tail=NULL;/* always points at last element*/
int size=0;
/*
===================================================
question: destroy_test()
function: frees all dynamic memory used by the list
parameters: none
return value: none
===================================================
*/
void destroy_test(){
entry_t* tmp=head;
entry_t* del=head;
while(tmp){
del=tmp;
tmp=tmp->next;
free(del->answer);
free(del->question);
free(del->c);
free(del->d);
free(del->b);
free(del->a);
free(del);
}
head=NULL;
tail=NULL;
size=0;
}
/*
============================================================================================
question: add_entry(char* question,char* a,char* b,char* c,char* d,char* answer)
function: adds an entry to the list
parameters: elements of test question entry as char*
return value: none
============================================================================================
*/
void add_entry(char* question,char* a,char* b,char* c,char* d,char* answer){
entry_t* fresh=(entry_t*)malloc(sizeof(entry_t));/* dynamically allocate data*/
fresh->answer=answer;
fresh->question=question;
fresh->c=c;
fresh->d=d;
fresh->b=b;
fresh->a=a;
/* link the variable in*/
if(head==NULL){/* insert into empty list*/
fresh->next=NULL;
fresh->prev=NULL;
head=tail=fresh;
}
else{/* insert at tail in non-empty list*/
fresh->next=NULL;
tail->next=fresh;
fresh->prev=tail;
tail=fresh;
}
size++;
}
/*
============================================================
question: load_entry(char* tagline)
function: adds an entry to the list that was read from a file
parameters: char* tagline=one line of file
return value: none
=============================================================
*/
void load_entry(char* tagline){
entry_t* fresh=(entry_t*)malloc(sizeof(entry_t));
char parameter[80];
unsigned int i=0,j=0;
unsigned int mod=0;
for(i=0;i<strlen(tagline);i++){
if(tagline[i]!=';'){/* build up the parameter*/
parameter[j]=tagline[i];
j++;
}
else{
parameter[j]=0;
j=0;
switch(mod){/* cycle through parameters*/
case 0: fresh->question=(char*)malloc((strlen(parameter)+1)*sizeof(char));
strcpy(fresh->question,parameter);break;
case 1: fresh->a=(char*)malloc((strlen(parameter)+1)*sizeof(char));
strcpy(fresh->a,parameter);break;
case 2: fresh->b=(char*)malloc((strlen(parameter)+1)*sizeof(char));
strcpy(fresh->b,parameter);break;
case 3: fresh->c=(char*)malloc((strlen(parameter)+1)*sizeof(char));
strcpy(fresh->c,parameter);break;
case 4: fresh->d=(char*)malloc((strlen(parameter)+1)*sizeof(char));
strcpy(fresh->d,parameter);break;
case 5: fresh->answer=(char*)malloc((strlen(parameter)+1)*sizeof(char));
strcpy(fresh->answer,parameter);break;
}
mod++;
}
}
/* link the variable in*/
if(head==NULL){/* insert into empty list*/
fresh->next=NULL;
fresh->prev=NULL;
head=tail=fresh;
}
else{/* insert at tail in non-empty list*/
fresh->next=NULL;
tail->next=fresh;
fresh->prev=tail;
tail=fresh;
}
size++;
}
/*
===================================================================================
question: load_addrbook(char* filename)
function: attempts to load an test question from the file specified by char* filename
parameters: char* filename
return value: none
===================================================================================
*/
void load_test(char* filename){
FILE* file=NULL;
char buffer[80];
file=fopen(filename,"r");/* try to open for read*/
if(file){
while(fgets(buffer,80,file))/* read a line of 80 chars*/
load_entry(buffer);/* store entry in test question*/
fclose(file);
printf("\nTest sucessfully loaded!\n\n");
}
else
printf("\a\nFile not found!\n\n");
}
/*
=======================================================================
question: save_test(char* filename)
function: stores an test question in the file specified by char* filename
parameters: char* filename
return value: none
=======================================================================
*/
void save_test(char* filename){
FILE* file=NULL;
char choice;
entry_t* show=head;
if(head==NULL){
printf("\nYour test question is currently empty!\n\n");
return;
}
file=fopen(filename,"r");/* check for file exist*/
if(file){
fclose(file);
printf("\a\nFile already exists!");
printf("\n<O>verwrite/<A>ppend/<C>lose? ");
scanf("%c",&choice);
fflush(stdin);
switch(choice){
case 'o':
case 'O':
file=fopen(filename,"w");
break;
case 'a':
case 'A':
file=fopen(filename,"a");
break;
case 'c':
case 'C':
return;
break;
default:
printf("\nIllegal command!\n\n");
return;
break;
}
}
else{
file=fopen(filename,"w");/* open for write*/
}
if(file){
while(show!=NULL){/* cycle through list, write one entry per line, each parameter seperated by semicolon*/
//fprintf(file,"Question [%.2d]: %s\n\n \t\tA.) %s\n \t\tB.) %s\n \t\tC.) %s\n \t\tD.) %s\n \t\tAnswer: %s\n\n",id,show->question,show->a,show->b,show->c,show->d,show->answer);
fprintf(file,"%s;%s;%s;%s;%s;%s;\n",show->question,show->a,show->b,show->c,show->d,show->answer);
show=show->next;
}
if(fclose(file))
printf("\a\nError during write operation!\n\n");
else
printf("\nWrite operation completed successfully!\n\n");
}
else
printf("\a\nError during write operation!\n\n");
}
/*
==============================================================================================
question: print_test(int sort_criteria)
function: prints test question to stdout, starting with the parameter specified by sort_criteria
parameters: int sort_criteria
return value: none
==============================================================================================
*/
void print_test(int sort_criteria){
entry_t* show;
int i=1;
if(head){
show=head;
printf("\nYour test question currently has %d entries:\n\n",size);
while(show){
switch(sort_criteria){
case 1:/*question*/
printf("Question [%.2d]: %s\n\n \t\tA.) %s\n \t\tB.) %s\n \t\tC.) %s\n \t\tD.) %s\n \t\tAnswer: %s\n\n",i,show->question,show->a,show->b,show->c,show->d,show->answer);
break;
//case 2:/* a*/
//printf("[%.3d]=%s, %s, %s %s, %s, %s\n",i,show->a,show->question,show->b,show->c,show->d,show->answer);
//break;
///case 3:/* b*/
//printf("[%.3d]=%s %s, %s, %s, %s, %s\n",i,show->b,show->c,show->question,show->a,show->d,show->answer);
//break;
//case 4:/* c*/
//printf("[%.3d]=%s %s, %s, %s, %s, %s\n",i,show->c,show->b,show->question,show->a,show->d,show->answer);
//break;
//case 5:/* d*/
//printf("[%.3d]=%s, %s, %s %s, %s, %s\n",i,show->d,show->answer,show->b,show->c,show->question,show->a);
//break;
//case 6:/* answer*/
//printf("[%.3d]=%s, %s, %s %s, %s, %s\n",i,show->answer,show->d,show->b,show->c,show->question,show->a);
//break;
}
show=show->next;
i++;
}
printf("\n");
}
else
printf("\nYour test question is currently empty!\n\n");
}
/*
============================================================================================================
question: search_entry(char* search,int search_criteria,int* num_matches)
function: search an entry in the list
parameters: char* search=search value, int search_criteria=what parameter. int* num_matches=counter for main
return value: int*=dynamically created area containing all positions that had a match
============================================================================================================
*/
int* search_entry(char* search,int search_criteria,int* num_matches){
entry_t* found=head;
int i=0,pos=1;
char* str_search=NULL;
int* matches=NULL;
*num_matches=0;
/* count how many times we have a match*/
while(found){
switch(search_criteria){
case 1:/* question*/
str_search=found->question;
break;
case 2:/* a*/
str_search=found->a;
break;
case 3:/* b*/
str_search=found->b;
break;
case 4:/* c*/
str_search=found->c;
break;
case 5:/* d*/
str_search=found->d;
break;
case 6:/* answer*/
str_search=found->answer;
break;
}
if(!strcmp(str_search,search)){
(*num_matches)++;
if(*num_matches==1){/* dynamically allocate memory*/
matches=(int*)malloc(*num_matches*sizeof(int));
matches[*num_matches-1]=pos;
}
if(*num_matches>1){/* increase memory block according to num_matches*/
matches=(int*)realloc(matches,*num_matches*sizeof(int));
matches[*num_matches-1]=pos;
}
}
found=found->next;
pos++;
}
return matches;/* return array with matching positions or NULL*/
}
/*
=============================================================
question: delete_entry(int index)
function: deletes an entry in the list specified by int index
parameters: int index
return value: 1=entry at index deleted,0=wrong index
=============================================================
*/
int delete_entry(int index){
entry_t* del=head;
entry_t* left;
entry_t* right;
int pos=1;
while(del){
if(pos==index){
left=del->prev;/* store left side*/
right=del->next;/* store right side*/
if(left)/* close the gap*/
left->next=right;
if(right)
right->prev=left;
if(del==head)/* if we have to touch the head*/
head=right;
if(del==tail)/* if we have to touch the tail*/
tail=left;
free(del->answer);/* free dynamically allocated memory*/
free(del->question);
free(del->c);
free(del->d);
free(del->b);
free(del->a);
free(del);/* free the pointer itself*/
size--;/* decrease size*/
return 1;
}
else{
del=del->next;
pos++;
}
}
return 0;
}
/*
===============================================================================
question: sort_test(int sort_criteria)
function: sorts the test question by performing a bubble sort using sort_criteria
parameters: int sort_criteria
return value: 1=test question was sorted,0=nothing to sort (zero or one elements)
===============================================================================
*/
int sort_test(int sort_criteria){
int i,j;
entry_t* sort;
entry_t* tmp;
entry_t* left;
entry_t* right;
char* str_sort;
char* str_sort_next;
if(size<2)
return 0;
/* perform a bubble sort*/
for(i=size-1;i>0;i--){
sort=head;
for(j=0;j<i;j++){
if(sort&&sort->next){
switch(sort_criteria){
case 1:/* question*/
str_sort=sort->question;
str_sort_next=sort->next->question;
break;
case 2:/* a*/
str_sort=sort->a;
str_sort_next=sort->next->a;
break;
case 3:/* b*/
str_sort=sort->b;
str_sort_next=sort->next->b;
break;
case 4:/* c*/
str_sort=sort->c;
str_sort_next=sort->next->c;
break;
case 5:/* d*/
str_sort=sort->d;
str_sort_next=sort->next->d;
break;
case 6:/* answer*/
str_sort=sort->answer;
str_sort_next=sort->next->answer;
break;
}
if(stricmp(str_sort,str_sort_next)>0){/* lexographic compare (case-independent)*/
if(sort==tail->prev)/* if we have to touch the tail*/
tail=sort;
left=sort->prev;/* store left side of sort*/
right=sort->next->next;/* store right side of sort->next*/
tmp=sort->next;/* store sort->next*/
sort->next=right;/* swap sort and tmp(1)*/
sort->prev=tmp;
if(left)/* ensure correct order from left side*/
left->next=tmp;
if(right)/* ensure correct order from right side*/
right->prev=sort;
tmp->prev=left;/* swap sort and tmp(2)*/
tmp->next=sort;
if(sort==head)/* if we touched the head*/
head=tmp;
}
else
sort=sort->next;
}
else{
if(sort)
sort=sort->next;
}
}
}
return 1;
}
/*
=================================================================
question: main(int argc,char** argv)
function: you really should know this
parameters: int argc=argument counter,char** argv=argument vector
return value: 0=success,!=0 otherwise
=================================================================
*/
int main(int argc,char** argv){
int i=0,index=0,num_matches=0;
//int i=0,index=0,num_matches=0,PATH_MAX=0;
char buffer[80]={0},filename[PATH_MAX]={0};
char *question=NULL,*a=NULL,*b=NULL,*c=NULL,*d=NULL,*answer=NULL;
int *matches=NULL;
unsigned char choice=0,sort_criteria=1,search_criteria=0;
do{
printf("*** TOMS (Today's Operating Media Services) ***\n\n");
printf("[1] new entry\n[2] search entry\n[3] delete entry\n[4] print\n[5] sort\n[6] load\n[7] save\n[8] exit\n ");
scanf("%c",&choice);
choice-=48;
fflush(stdin);
switch(choice){
case 1:
fflush(stdin);
printf("\nPlease enter new record:\n");
printf("\nQuestion: ");
gets(buffer);
question=(char*)malloc((strlen(buffer)+1)*sizeof(char));
strcpy(question,buffer);
printf("\nOption A: ");
gets(buffer);
a=(char*)malloc((strlen(buffer)+1)*sizeof(char));
strcpy(a,buffer);
printf("\nOption B: ");
gets(buffer);
b=(char*)malloc((strlen(buffer)+1)*sizeof(char));
strcpy(b,buffer);
printf("\nOption C: ");
gets(buffer);
c=(char*)malloc((strlen(buffer)+1)*sizeof(char));
strcpy(c,buffer);
printf("\nOption D: ");
gets(buffer);
d=(char*)malloc((strlen(buffer)+1)*sizeof(char));
strcpy(d,buffer);
printf("\nAnswer: ");
gets(buffer);
answer=(char*)malloc((strlen(buffer)+1)*sizeof(char));
strcpy(answer,buffer);
add_entry(question,a,b,c,d,answer);
printf("\n");
break;
case 2:
fflush(stdin);
printf("\nEnter search criteria\n(1=question,2=a,3=b,4=c,5=d,6=answer): ");
scanf("%c",&search_criteria);
search_criteria-=48;
fflush(stdin);
if(search_criteria>=1&&search_criteria<=6){
printf("\nEnter search value: ");
gets(buffer);
matches=search_entry(buffer,search_criteria,&num_matches);
if(matches==NULL)
printf("\nNo matching entry!\n\n");
else{
printf("\nEntry found at position(s) ");
for(i=0;i<num_matches;i++)
if(i==num_matches-1)
printf("%d!\n\n",matches[i]);
else
printf("%d,",matches[i]);
free(matches);/* free dynamically allocated data*/
}
}
else
printf("\a\nWrong search criteria!\n\n");
break;
case 3:
fflush(stdin);
printf("\nEnter index: ");
gets(buffer);
index=atoi(buffer);
if(delete_entry(index))
printf("\nEntry deleted!\n\n");
else
printf("\a\nWrong index!\n\n");
break;
case 4:
print_test(sort_criteria);
break;
case 5:
fflush(stdin);
printf("\nEnter sort criteria\n(1=question,2=a,3=b,4=c,5=d,6=answer): ");
scanf("%c",&sort_criteria);
sort_criteria-=48;
fflush(stdin);
if(sort_criteria>=1&&sort_criteria<=6){
if(sort_test(sort_criteria))
printf("\nTest Questions sorted!\n\n");
else
printf("\nNothing to sort!\n\n");
}
else
printf("\a\nWrong sort criteria!\n\n");
break;
case 6:
fflush(stdin);
printf("\nEnter path+filename: ");
gets(filename);
destroy_test();
load_test(filename);
break;
case 7:
fflush(stdin);
printf("\nEnter path+filename: ");
gets(filename);
save_test(filename);
break;
case 8:
destroy_test();
break;
default:
printf("\a\nIllegal command!\n\n");
break;
}
}while(choice!=8);
return 0;
}