#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <stdlib.h>
#define GREETING "\n Student Record System\n ---------------------\n"
#define MAX_NUM_RECORDS 25
//struct NAME fields:
#define MAX_LEN_NAME_FIRST 15
#define MAX_LEN_NAME_LAST 15
#define ID_MIN 001
#define ID_MAX 999
//struct MARK fields
#define MIN_MARK 0
#define MAX_MARK 100
#define ASSIGN_W 0.60
#define EXAM_W 0.40
#define PASS 40
//-----------------------
//User-Define Data Types:
//-----------------------
struct NAME
{
char FirstName[MAX_LEN_NAME_FIRST];
char LastName[MAX_LEN_NAME_LAST];
int StudentID;
};
struct MARK
{
struct NAME Student;
int AssignMark;
int ExamMark;
float ModMark;
char ModGrade[5];
};
//--------------------
//Function prototypes:
//--------------------
//Menu:
void ShowMainMenu();
//Array - Record handling:
void DisplayRecordsAll(struct MARK AllRecords[], int NumRecords);
void DisplayRecordsSelected(struct MARK AllRecords[], int NumRecords, int MaxNumRecords);
void AddRecords(struct MARK AllRecords[], int *pNumRecords, int MaxNumRecords);
void UpdateRecords(struct MARK AllRecords[], int *pNumRecords);
//Generic Functions:
int GetValidatedInteger(int Min, int Max);
void Pause();
char GetValidatedString(char ValidatedString[], int MinLength, int MaxLength);
char GetValidatedYesNo();
float GetValidatedFloat2(float Min, float Max, int Precision);
int main()
{
system("mode CON: COLS=150 "); int MenuChoice = 0;
struct MARK AllRecords[MAX_NUM_RECORDS];
int NumRecords = 0; //ACTUAL Number of Records
do
{
//Clear screen, display menu and get user-selected menu item
ShowMainMenu();
MenuChoice = GetValidatedInteger(0, 5);
//Action user-selected menu item
switch (MenuChoice)
{
case 1:
AddRecords(AllRecords,&NumRecords, MAX_NUM_RECORDS);
break;
case 2:
DisplayRecordsAll(AllRecords, NumRecords);
break;
case 3:
DisplayRecordsSelected(AllRecords, NumRecords, MAX_NUM_RECORDS);
break;
case 4:
UpdateRecords(AllRecords, NumRecords);
break;
case 5:
break;
case 0:
Pause();
break;
}
} while (MenuChoice != 0);
return(0);
}
void ShowMainMenu()
{
printf("\n MAIN MENU\n ----------"); printf("\n 1. Add record(s) "); printf("\n 2. Display all records"); printf("\n 3. Display selected record(s)"); printf("\n 4. Update record(s)"); printf("\n 5. Display Cohort Average(s)"); printf("\n\n Enter your choice: "); }
//STUBS
void DisplayRecordsAll(struct MARK AllRecords[], int NumRecords)
{
int i = 0;
if (NumRecords == 0)
{
printf("\nThere are no records to display. "); Pause();
}
else
{
printf("\n ID number | Name | Assignment mark | Exam Mark | Module grade"); for (i = 0; i < NumRecords; i++)
{
printf("\n%.3d %s %s %d %d %1.2f %s \n", AllRecords[i].Student.StudentID,
AllRecords[i].Student.FirstName,
AllRecords[i].Student.LastName,
AllRecords[i].AssignMark,
AllRecords[i].ExamMark,
AllRecords[i].ModMark,
AllRecords[i].ModGrade);
}
Pause();
}
}
void DisplayRecordsSelected(struct MARK AllRecords[], int NumRecords,int MaxNumRecords)
{
int i = 0;
int IDSearch = 0;
char AddAnother = 'Y';
do
{
if (NumRecords == 0)
{
printf("\nThere are no records to display. "); Pause();
return;
}
printf("\nEnter Student's ID: "); IDSearch = GetValidatedInteger(0, ID_MAX);
for (i = 0; i < NumRecords; i++)
{
if (IDSearch == AllRecords[i].Student.StudentID)
{
printf("\n ID Number | Name "); printf("\n --------- | ---- ");
printf("\n %.3d%s %s", AllRecords
[i
].
Student.
StudentID, AllRecords[i].Student.FirstName,
AllRecords[i].Student.LastName);
}
}
printf("\nDo you want to view another record?(Y/N): "); AddAnother = GetValidatedYesNo();
} while (AddAnother == 'Y');
}
void AddRecords(struct MARK AllRecords[], int *pNumRecords, int MaxNumRecords)
{
char AddAnother; // 'Y' or 'N'
int ID = 0;
float ModMark = 0;
// ADD NEW RECORDS(S) TO ARRAY (until user finished or arry full)
do
{
if (*pNumRecords == MaxNumRecords)
{
printf("\nThe system is full. You cannot add another record. Returning to main menu. "); Pause();
ShowMainMenu();
}
AllRecords[*pNumRecords].Student.StudentID = *pNumRecords + 1;
printf("\nEnter the Students's First Name: "); GetValidatedString(AllRecords[*pNumRecords].Student.FirstName, 1, MAX_LEN_NAME_FIRST);
printf("\nEnter the Student's Last Name: "); GetValidatedString(AllRecords[*pNumRecords].Student.LastName, 1, MAX_LEN_NAME_LAST);
printf("\nEnter the Exam mark (%d - %d): ", MIN_MARK
, MAX_MARK
); AllRecords[*pNumRecords].ExamMark = GetValidatedInteger(MIN_MARK, MAX_MARK);
printf("\nEnter the Assignment mark (%d - %d): ", MIN_MARK
, MAX_MARK
); AllRecords[*pNumRecords].AssignMark = GetValidatedInteger(MIN_MARK, MAX_MARK);
ModMark = (AllRecords[*pNumRecords].ExamMark * EXAM_W) + (AllRecords[*pNumRecords].AssignMark * ASSIGN_W);
AllRecords[*pNumRecords].ModMark = ModMark;
if (AllRecords[*pNumRecords].ModMark < PASS)
{
strcpy_s(AllRecords[*pNumRecords].ModGrade, sizeof(AllRecords[*pNumRecords].ModGrade), "FAIL");
}
else
{
strcpy_s(AllRecords[*pNumRecords].ModGrade, sizeof(AllRecords[*pNumRecords].ModGrade), "PASS");
}
// Update number of records (i.e. Add 1 to *pNumRecords)
*pNumRecords = *pNumRecords + 1;
// Add another?
AddAnother = 'N'; //Re-initialise
if (*pNumRecords < MaxNumRecords)
{
printf("\n Do you want to add another records (Y/N) ? "); AddAnother = GetValidatedYesNo();
if (AddAnother == 'Y')
{
//Clear screen below [menu + user choice]
//(Actually: delete + re-display menu + user choice).
ShowMainMenu();
}
}
else
{
printf("\nThe system is storing the maximum number of records. Returning to main menu. "); Pause();
ShowMainMenu();
}
} while (AddAnother == 'Y');
}
void UpdateRecords(struct MARK AllRecords[], int *pNumRecords)
{
int i = 0;
int NumChoice = 0;
int NumChoice2 = 0;
char AddAnother;
float ModMark = 0;
if (pNumRecords == 0)
{
printf("\nThere are no records to display. "); Pause();
return;
}
printf("\n ID number | Name | Assignment mark | Exam Mark | Module grade"); for (i = 0; i < pNumRecords; i++)
{
printf("\n%.3d %s %s %d %d %1.0f %s \n", AllRecords[i].Student.StudentID,
AllRecords[i].Student.FirstName,
AllRecords[i].Student.LastName,
AllRecords[i].AssignMark,
AllRecords[i].ExamMark,
AllRecords[i].ModMark,
AllRecords[i].ModGrade);
printf("\n\nEnter the record number you wish to update: "); NumChoice = GetValidatedInteger(1, MAX_NUM_RECORDS) - 1;
printf("\n 3. Assignment Mark");
printf("\n\nEnter the number of field you wish to edit: "); NumChoice2 = GetValidatedInteger(1, 4);
switch (NumChoice2)
{
case 1:
printf("\nEnter the Student's First Name: "); GetValidatedString(AllRecords[NumChoice].Student.LastName, 1, MAX_LEN_NAME_FIRST);
break;
case 2:
printf("\nEnter the Sutdent's Surname: "); GetValidatedString(AllRecords[NumChoice].Student.FirstName, 1, MAX_LEN_NAME_LAST);
break;
case 3:
printf("\nEnter the Assignemt Mark (0-100): "); AllRecords[NumChoice].AssignMark = GetValidatedInteger(MIN_MARK, MAX_MARK);
break;
case 4:
printf("\nEnter the Exam Mark (0-100): "); AllRecords[NumChoice].ExamMark = GetValidatedInteger(MIN_MARK, MAX_MARK);
break;
}
AddAnother = 'N';
printf("\nDo you want to update another field?(Y/N): "); AddAnother = GetValidatedYesNo();
if (AddAnother == 'Y')
{
UpdateRecords(AllRecords, pNumRecords);
}
}
}
int GetValidatedInteger(int Min, int Max)
{
//DECLARATIONS + INITILISATION of values
// Local Constants:
const int cTrue = 1, cFalse = 0;
// Input Variables:
float Input = 0; // NB Input read into a FLOAT
// Intermediate Variables:
int ItemRead = cFalse; //Flag
int Valid = cFalse; //Flag - Mandatory initialisation to cFalse
// Output Variables:
// None
//-----------------------------------------------------------
do
{
ItemRead = scanf_s("%f", &Input);
if (ItemRead == cFalse)
{
printf("Invalid - must be a number! Please try again (%d-%d): ", Min
, Max
); }
/* Validate - Not whole number? */
else if (Input != (int)Input)
{
printf("Invalid - must be an integer! Please try again (%d-%d): ", Min
, Max
); }
else if ((Input < Min) || (Input > Max))
{
printf("Invalid - out-of-range! Please try again (%d-%d): ", Min
, Max
); }
else
{
Valid = cTrue;
}
} while (Valid == cFalse);
return((int)Input);
}
void Pause()
{
printf("\n\n Press the ENTER key."); }
char GetValidatedString(char ValidatedString[], int MinLength, int MaxLength)
{
//Initialising True and False variables
const char cFalse = 0, cTrue = 1;
char Success = cFalse;
char YesorNo;
char Input[255];
size_t InputArrayMaxLen = sizeof(Input) - 2;
size_t Length;
if (MaxLength > (int)InputArrayMaxLen)
{
printf("\n\nRequired maximum lenfth for called GetValidatedString() function" " \nCannot exceed %d characters", (int)InputArrayMaxLen);
printf("\nData not read. Please contact developer."); Pause();
return(Success);
}
do
{
do
{
YesorNo = 'Y';
Input[InputArrayMaxLen + 1] = 'z';
Input[InputArrayMaxLen] = 'z';
fgets(Input
, sizeof(Input
), stdin
);
if ((Input[InputArrayMaxLen + 1] == '\0') && (Input[InputArrayMaxLen] != '\n'))
{
printf("\n\nRequired maximum length for called GetValidatedString() function " "\ncannot exceed %d characters", InputArrayMaxLen);
printf("\n\nDo you wish to try again (Y?N)?: "); YesorNo = GetValidatedYesNo();
if (YesorNo == 'N')
{
printf("Data not read. Please contact developer."); Pause();
return(Success); //returns cFalse
}
else
{
printf("\nRe-enter (%d - %d characters): ", MinLength
, MaxLength
); }
}
else
{
YesorNo = 'N';
}
} while (YesorNo == 'Y');
Length
= strlen(Input
) - 1; // length contains the correct updated string length Input[Length] = '\0';
//String length validation (MinLength -> Maxlength)
if ((Length < (size_t)MinLength) || (Length >(size_t)MaxLength))
{
printf("Invalid! Please try again (Length %d-%d): ", MinLength
, MaxLength
); }
else
{
Success = cTrue;
}
} while (Success == cFalse);
//Transfer validated string to ValidatedString
strcpy_s(ValidatedString, MaxLength + 1, Input);
return(Success); // Returns cTrue
}
char GetValidatedYesNo()
{
//Local Constants:
const int cTrue = 1, cFalse = 0;
//Input Variables:
char Input = 0;
//Intermediate Variables:
char ItemRead = cFalse;
int Valid = cFalse;
//CONDITIONAL Do loop for Validating 'Y' or 'N'
do
{
ItemRead = scanf_s("%c", &Input);
if ((Input == 'Y') || (Input == 'N') || (Input == 'y') || (Input == 'n'))
{
Valid = cTrue;
}
else
{
printf("Invalid input! Please try again:"); }
} while (Valid == cFalse);
// Switches lowercase to uppercase should they enter y/n
}
float GetValidatedFloat2(float Min, float Max, int Precision)
{
//DECLARATIONS + INITILISATION of values
// Local Constants:
const int cTrue = 1, cFalse = 0;
// Input Variables:
float Input = 0; // NB Input read into a FLOAT
// Intermediate Variables:
int ItemRead = cFalse; //Flag
int Valid = cFalse; //Flag - Mandatory initialisation to cFalse
// Output Variables:
// None
//-----------------------------------------------------------
do
{
ItemRead = scanf_s("%f", &Input);
if (ItemRead == cFalse)
{
printf("Invalid - must be a number! Please try again (%f-%f): ", Min
, Max
); }
/* Validate - Not whole number? */
else if (Input != (int)Input)
{
printf("Invalid - must be a float! Please try again (%f-%f): ", Min
, Max
); }
else if ((Input < Min) || (Input > Max))
{
printf("Invalid - out-of-range! Please try again (%f-%f): ", Min
, Max
); }
else
{
Valid = cTrue;
}
} while (Valid == cFalse);
return((float)Input);
}