I'm having trouble figuring out how to get my program to stop reading a file once the character string endOfFileMarker "***" is read given a file called "studentRecords.txt" with sample input as shown:
23456770,Mina,Porter,3,ENEE,114,CMSC,412,ENME,515
23456790,Alex,Simpson,1,CMSC,412
***
I'm reading the file using a while loop indicating that as long the file is not equal to the end of the file and if the first input from which I read is not equivalent to the endOfFileMarker. Right now the output doesn't stop reading at the endOfFileMarker and takes it as a new record in the structure with the given output of a display function (I realize the error with the 2nd record but that appears to be a problem with the display function and not the way I'm storing it):
23456770 Mina Porter 3 ENEE 114 CMSC 412 ENME 515
23456Alex Alex Simpson 1 CMSC 412
*** Alex Simpson 1 CMSC 412
I've tried using fgets earlier and creating an input buffer to read each line. But since there will be variable number of course names and course codes for each student, I found fscanf and using a while loop with control condition of !feof to work better. Kind of at a loss right now of how to stop storing into the structure once I hit the endOfFileMarker. If someone can please help me out with this, that would be very appreciated. My full code is written below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define filename "studentRecords.txt"
typedef struct courseInfo
{//structure defining courseInfo elements
int courseID;
char courseName[30];
}crsInfo;
typedef struct studentInfo
{//structure defining studentInfo elements
char studentID[9];
char firstName[20];
char lastName[25];
int coursesAttended;
crsInfo cInfo[10];
struct studentInfo * next;
}stdInfo;
stdInfo * firstStdNodePointer = NULL;
stdInfo * currentStdNodePointer = NULL;
void addStudentInfo(stdInfo newStd)
{
if (firstStdNodePointer == NULL) //Create the first course node
{
firstStdNodePointer = (stdInfo *) malloc(sizeof(stdInfo));
strcpy(firstStdNodePointer->studentID, newStd.studentID);
strcpy(firstStdNodePointer->firstName, newStd.firstName);
strcpy(firstStdNodePointer->lastName, newStd.lastName);
firstStdNodePointer->coursesAttended = newStd.coursesAttended;
for(int i = 0; i < newStd.coursesAttended; i++)
{
firstStdNodePointer->cInfo[i].courseID = newStd.cInfo[i].courseID;
strcpy(firstStdNodePointer->cInfo[i].courseName, newStd.cInfo[i].courseName);
}
firstStdNodePointer->next = NULL;
currentStdNodePointer = firstStdNodePointer;
}
else // add next course to the end of the course linked list.
{
// Go to the last Course in the list to get the course ID
stdInfo * newStdNodePointer = (stdInfo *) malloc(sizeof(stdInfo));
strcpy(newStdNodePointer->studentID, newStd.studentID);
strcpy(newStdNodePointer->firstName, newStd.firstName);
strcpy(newStdNodePointer->lastName, newStd.lastName);
newStdNodePointer->coursesAttended = newStd.coursesAttended;
for(int j = 0; j < newStd.coursesAttended; j++)
{
newStdNodePointer->cInfo[j].courseID = newStd.cInfo[j].courseID;
strcpy(newStdNodePointer->cInfo[j].courseName, newStd.cInfo[j].courseName);
}
newStdNodePointer->next = NULL;
currentStdNodePointer->next = newStdNodePointer; // Link previous node with newNode
currentStdNodePointer = currentStdNodePointer->next; // Make current node as previous node
}
}
void loadStudentInfo()
{
FILE * fptr = NULL;
fptr = fopen(filename, "r+");
const char endOfFileMarker[] = "***"; //marks the end of the student record list
if(fptr == NULL)
{
printf("File can not be opened\n");
}
stdInfo newStd;//defining a new struct studentInfo variable so I can pass to the addStudent function
//char line[100] = "";
//char * strPtr;
while (!feof(fptr) && strcmp(newStd.studentID, endOfFileMarker) != 0 )
{
fscanf(fptr, "%[^,],", newStd.studentID);
printf("%s\n", newStd.studentID);
fscanf(fptr, "%[^,],", newStd.firstName);
printf("%s\n", newStd.firstName);
fscanf(fptr, "%[^,],", newStd.lastName);
fscanf(fptr, "%i,", &newStd.coursesAttended);
for(int j = 0; j < newStd.coursesAttended; j++)
{//To read each courseName and ID, you need to go according to how many courses they entered
//because the amount of records in cInfo should correspond with how many pairs of courseName
//are entered into the file
fscanf(fptr, "%[^,],", newStd.cInfo[j].courseName);
fscanf(fptr, "%i,", &newStd.cInfo[j].courseID);
}
addStudentInfo(newStd);
}
fclose(fptr);
}
void displayCourseInfo()
{
printf("------------------------------------------------\n");
stdInfo * stdListPointer = firstStdNodePointer;
//start from the beginning
while(stdListPointer != NULL) {
printf("%s %s %s\t%i\t", stdListPointer->studentID, stdListPointer->firstName, stdListPointer->lastName, stdListPointer->coursesAttended);
for(int i = 0; i < stdListPointer->coursesAttended; i++)
{
printf(" %s %i ", stdListPointer->cInfo[i].courseName, stdListPointer->cInfo[i].courseID);
}
printf("\n");
stdListPointer = stdListPointer->next;
}
printf("------------------------------------------------\n");
}
void switchCaseMenu()
{
int selection;
int menuActive = 1;
while(menuActive)
{
printf("60-141 Bonus Assignment - Ben John\n");
printf("------------\n");
printf("1. Add a new student\n");
printf("2. Delete a student\n");
printf("3. Search for a student\n");
printf("4. Display current students\n");
printf("5. Save student information to file\n");
printf("6. Exit\n");
printf("Please enter a selection: ");
scanf("%i", &selection);
switch(selection)
{
case 1:
printf("~Selected - Add a new student~\n");
break;
case 2:
printf("~Selected - Delete a student~\n");
break;
case 3:
printf("~Selected - Search for s student~\n");
break;
case 4:
printf("~Selected - Display current students~\n");
displayCourseInfo();
break;
case 5:
printf("~Selected - Save student information to file~\n");
break;
case 6:
printf("~Selected - Exit~\n");
menuActive = 0;
break;
default:
printf("Invalid Input!\n");
}
}
printf("Goodbye!\n");
}
int main(void)
{
loadStudentInfo();
switchCaseMenu();
return 0;
}