Lab 11-21
/*
This program has some kind of bug on option 6
This is an update of last weeks record.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FMAX 20
#define LMAX 20
#define QUIT 7
struct Employee {
int idNum;
char firstName[FMAX];
char lastName[LMAX];
struct Employee* next;
};
typedef struct Employee Employee;
typedef Employee* EmpList;
void write_record(Employee e, long pos, FILE *ofp);
Employee read_record(long pos, FILE *ifp);
Employee input_record();
void output_record(Employee record);
int main_menu();
long record_count(FILE *fptr);
long getUserNum(FILE *fptr);
EmpList createList(FILE *fptr);
EmpList createListLast(FILE *fptr);
void printList(EmpList l);
void deleteList(EmpList l);
EmpList findName(EmpList l, char * target);
int nameEquals(char * findName, char * first, char * last);
char * readLine();
void changeTwoItems(int *iptr, char *cptr);
int main(void) {
Employee record;
FILE *fptr;
long record_pos;
int choice;
EmpList list = NULL;
fptr = fopen("emp.dat", "r+");
if (fptr == NULL) {
fptr = fopen("emp.dat", "w+");
}
record_pos = record_count(fptr);
printf("%ld record(s)\n", record_count(fptr));
while ( (choice = main_menu()) != QUIT) {
switch ( choice ) {
case 1: {//add
record = input_record();
write_record(record, record_pos, fptr);
record_pos++;
break;
}
case 2: { //get
int recordNum = getUserNum(fptr);
record = read_record(recordNum, fptr);
output_record(record);
break;
}
case 3: { //list all
long i;
long rec_count = record_count(fptr);
//printf("record count: %d\n", rec_count);
for(i = 0; i < rec_count; i++) {
record = read_record(i, fptr);
output_record(record);
}
break;
}
case 4: { //create reverse linked list
if (list != NULL) {
deleteList(list);
}
list = createList(fptr);
printList(list);
break;
}
case 5: { //create forward linked list
if (list != NULL) {
deleteList(list);
}
list = createListLast(fptr);
printList(list);
break;
}
case 6: { //find name
char *name;
EmpList person;
printf("%s", "Name? ");
name = readLine();
if (list == NULL) {
list = createListLast(fptr);
}
person = findName(list, name);
free(name);
printf("name found? %s\n", person == NULL ?
"No" : "Yes" );
break;
}
default:
break;
}
}
//record = input_record();
//output_record(record);
return 0;
}
void write_record(Employee e, long pos, FILE *ofp) {
fseek(ofp, pos * sizeof(Employee), SEEK_SET);
fwrite(&e, sizeof(Employee), 1, ofp);
}
Employee read_record(long pos, FILE *ifp) {
Employee record;
fseek(ifp, pos * sizeof(Employee), SEEK_SET);
fread(&record, sizeof(Employee), 1, ifp);
return record;
}
Employee input_record() {
Employee record;
printf("%s", "ID Num: ");
scanf("%d", &record.idNum);
printf("%s", "First Name: ");
scanf("%s", record.firstName);
printf("%s", "Last Name: ");
scanf("%s", record.lastName);
return record;
}
void output_record(Employee record) {
printf("\n%s\n", "=====================");
printf("%s %d\n", "ID Num:", record.idNum);
printf("%s %s\n", "First Name:", record.firstName);
printf("%s %s\n", "Last Name: ", record.lastName);
printf("%s %s\n", "Next Null? ", (record.next == NULL) ?
"Yes" : "No" );
printf("%s\n", "=====================");
return;
}
int main_menu() {
int choice;
printf("\n%s", "1) Add new record\n");
printf("%s", "2) Get a record\n");
printf("%s", "3) List all records\n");
printf("%s", "4) Make reverse linked list\n");
printf("%s", "5) Make forward linked list\n");
printf("%s", "6) Find name in list\n");
printf("%s", "7) Quit\n");
printf("%s", "\n --> ");
fflush(stdin);
scanf("%d", &choice);
return choice;
}
long record_count(FILE *fptr) {
long current_pos = ftell(fptr);
long end_pos;
fseek(fptr, 0, SEEK_END);
end_pos = ftell(fptr);
fseek(fptr, current_pos, SEEK_SET);
return end_pos / sizeof(Employee);
}
long getUserNum(FILE *fptr) {
long num = -1;
long max_rec = record_count(fptr);
int firstTime = 1;
while( num < 0 || num >= max_rec) {
if (firstTime) {
printf("%s", "What record? ");
firstTime = 0;
}
else {
printf("%s", "Bad Record#: What record? ");
}
scanf("%ld", &num);
}
return num;
}
EmpList createList(FILE *fptr) {
EmpList list = NULL;
EmpList newEmp;
Employee record;
long i;
long rec_count = record_count(fptr);
for(i = 0; i < rec_count; i++) {
//printf("reading a record\n");
record = read_record(i, fptr); //read a record
newEmp = malloc( sizeof(Employee) ); //malloc memory
*newEmp = record; //copy record
newEmp->next = list; //put at start
list = newEmp; //update list ptr
}
return list;
}
EmpList createListLast(FILE *fptr) {
EmpList list = NULL; // points to head of list
EmpList last = NULL; // points to end of list
EmpList newEmp;
Employee record;
long i;
long rec_count = record_count(fptr);
for(i = 0; i < rec_count; i++) {
//printf("reading a record\n");
record = read_record(i, fptr); //read a record
newEmp = malloc( sizeof(Employee) ); //malloc memory
*newEmp = record; //copy record
newEmp->next = NULL; //put at start
if (list == NULL) {
list = newEmp; //update list ptr
}
else { // list exists
last->next = newEmp;
}
last = newEmp;
}
return list;
}
void printList(EmpList l) {
while ( l != NULL ) {
output_record( *l );
l = l->next;
}
}
void deleteList(EmpList l) {
EmpList temp;
while ( l != NULL ) {
temp = l;
l = l->next;
free( temp );
}
}
EmpList findName(EmpList l, char * target) {
// return pointer to found record or NULL
while ( l != NULL &&
!nameEquals(target, l->firstName, l->lastName) ) {
l = l->next;
}
return l;
}
int nameEquals(char * findName, char * first, char * last) {
// first + space + last + null
int nameLen = strlen(first) + strlen(last) + 2;
char *targetName = malloc( nameLen * sizeof(char) );
int result;
strcpy(targetName, first);
strcat(targetName, " ");
strcat(targetName, last);
printf("find name: %s target name: %s\n", findName, targetName);
result = strcmp(findName, targetName);
free(targetName);
return !result;
}
char * readLine() {
char line[100];
int charCount = 0;
char ch;
char *name;
fflush(stdin);
while ( (ch = getchar()) != '\n') {
line[charCount++] = ch;
}
line[charCount] = '\0';
name = malloc(charCount * sizeof(char));
strcpy(name, line);
//printf("Name entered: %s Len: %d\n", name, strlen(name));
return name;
}