Skip to content

Instantly share code, notes, and snippets.

@cms-codes
Created November 18, 2018 17:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cms-codes/7d1314ac3851786660446bd6141485dc to your computer and use it in GitHub Desktop.
Save cms-codes/7d1314ac3851786660446bd6141485dc to your computer and use it in GitHub Desktop.
Solution using structures and linked list
/********* Lab6 *******
* Course: PROG1955-1
* Title: Lab 6
* Purpose: Store the last name and first name of students in a dynamic
* structure using a linked list
* Date: 2018-11-10
* Author: Christopher Slothouber
* File: Lab6.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// INPUT_LEN must be large enough to acquire a full line of console input
// via fgets, therefore at least n+1, where n is the maximum number of
// characters to be read at one time (not including '\r' and/or '\0').
#define INPUT_LEN 50
// NAME_LEN is the length of each name, not including the null terminator.
#define NAME_LEN 20
// Common helper functions
/********* GetInput *******
* Gets a series of characters from the user via the console and stores
* the input in the input array for further processing.
* Inputs: a pointer to the first element of an initialized char array.
* Outputs: none.
*/
void GetInput(char input[]);
/********* GetName *******
* Reads up to NAME_LEN characters, including spaces.
* Inputs: a pointer to the first element of an initialized char array.
* Outputs: none.
*/
void GetName(char arrName[]);
/********* GetValue *******
* Reads a single integer value from the console into the supplied pointer.
* Inputs: an integer pointer.
* Outputs: none.
*/
void GetValue(int *value);
/********* GetInput *******
* Gets a series of characters from the user via the console and stores
* the input in the input array for further processing.
* Inputs: a pointer to the first element of an initialized char array.
* Outputs: none.
*/
void GetInput(char input[])
{
// Input is read from the console into a temporary input[] array.
// This array is then passed on to sscanf_s() for processing.
fgets(input, INPUT_LEN, stdin);
return;
}
/********* GetName *******
* Reads up to NAME_LEN characters, including spaces.
* Inputs: a pointer to the first element of an initialized char array.
* Outputs: none.
*/
void GetName(char arrName[])
{
int ret = 0;
int len = 0;
// INPUT_LEN must be large enough to acquire a full line of console input
// via fgets, therefore at least n+1, where n is the maximum number of
// characters to be read at one time (not including '\r' and/or '\0').
// This input array is a temporary buffer processed by sscanf_s().
char input[INPUT_LEN] = { 0 };
printf("Please enter up to %d characters\n", NAME_LEN);
do
{
printf(" : ");
// Calling fgets() - but this could be any other input method.
GetInput(&input[0]);
// Read in a string from the input acquired via GetInput()
// sscanf_s() returns 1 when successful
ret = sscanf_s(input, "%20c", arrName, NAME_LEN);
} while (ret = 0);
// By reading in characters instead of a string, we allow names with
// spaces. But the side-effect is \n newline is also read. So here we
// get rid of the newline. The null terminator is taken care of in the
// strBuf[] array in the main() loop.
len = strlen(arrName);
if (arrName[len - 1] == '\n')
arrName[len - 1] = 0;
return;
}
/********* GetValue *******
* Reads a single integer value from the console into the supplied pointer.
* Inputs: an integer pointer.
* Outputs: none.
*/
void GetValue(int *value)
{
int ret = 0;
// INPUT_LEN must be large enough to acquire a full line of console input
// via fgets, therefore at least n+1, where n is the maximum number of
// characters to be read at one time (not including '\r' and/or '\0').
// This input array is a temporary buffer supplied to sscanf().
char input[INPUT_LEN] = { 0 };
do
{
printf(" : ");
// Calling fgets() - but this could be any other input method.
GetInput(&input[0]);
// Read in an integer from the input acquired via GetInput()
// sscanf_s() returns 1 when successful
ret = sscanf_s(input, "%d", value);
} while (ret = 0);
return;
}
// Define the structure that will hold the necessary fields for each student
// record.
struct studentRecord
{
char *firstName;
char *lastName;
struct studentRecord *nextPtr;
};
typedef struct studentRecord StudentRecord;
/********* createRecord *******
* Created a record (struct) using the supplied character pointers. This
* function allocates dedicated memory for the struct and character fields.
* Inputs: a char pointer to a first name and a char pointer to a last name.
* Outputs: a pointer to an allocated StudentRecord type (struct).
*/
StudentRecord * createRecord(char *firstName, char *lastName);
/********* printRecord *******
* Prints out the fields associated with this StudentRecord.
* Inputs: a pointer to a StudentRecord struct.
* Outputs: none.
*/
void printRecord(StudentRecord *r);
/********* insertRecord *******
* Appends a record to the linked list.
* Inputs: a pointer to the first struct in a linked list,
* a pointer to a StudentRecord type (struct).
* Outputs: none.
*/
void insertRecord(StudentRecord **headPtr, StudentRecord *r);
/********* listRecords *******
* Displays the details for reach record in the StudentRecords linked list.
* Inputs: a pointer to the first struct in a linked list.
* Outputs: none.
*/
void listRecords(StudentRecord **headPtr);
/********* freeRecords *******
* Empties the list of all records, freeing the allocated memory.
* Inputs: a pointer to the first struct in a linked list.
* Outputs: none.
*/
void freeRecords(StudentRecord **headPtr);
StudentRecord * createRecord(char *firstName, char *lastName)
{
StudentRecord *r = malloc(sizeof(StudentRecord));
if (r == NULL)
{
puts("Could not allocate memory!");
exit(-1);
}
char *fN = NULL;
char *lN = NULL;
// strdup() calls malloc()
fN = _strdup(firstName);
lN = _strdup(lastName);
if (fN == NULL || lN == NULL)
{
puts("Could not allocate memory!");
exit(-1);
}
r->firstName = fN;
r->lastName = lN;
r->nextPtr = NULL;
return r;
}
void printRecord(StudentRecord *r)
{
printf("First name: %s, Last name: %s\n", r->firstName, r->lastName);
}
void insertRecord(StudentRecord **headPtr, StudentRecord *r)
{
StudentRecord *previousPtr = NULL;
StudentRecord *currentPtr = *headPtr;
// Find the last item in the list.
while (currentPtr != NULL)
{
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
if (previousPtr == NULL)
// This is the first record to be added to the list.
{
r->nextPtr = *headPtr;
*headPtr = r;
}
else
{
// Append the new item to the end of the list, with the
// last item becoming the second-last item.
previousPtr->nextPtr = r;
r->nextPtr = currentPtr;
}
return;
}
void listRecords(StudentRecord **headPtr)
{
StudentRecord *currentPtr = NULL;
int counter = 0;
currentPtr = *headPtr;
if (currentPtr == NULL)
// No records in this list.
{
puts("Empty.");
return;
}
do
{
printRecord(currentPtr);
currentPtr = currentPtr->nextPtr;
counter++;
} while (currentPtr != NULL);
printf("%d records listed.\n", counter);
puts("End of list.");
return;
}
void freeRecords(StudentRecord **headPtr)
{
StudentRecord *currentPtr = NULL;
StudentRecord *nextPtr = NULL;
currentPtr = *headPtr;
if (currentPtr == NULL)
// No records in this list.
{
return;
}
do
{
// Keep track of the next record in the list.
nextPtr = currentPtr->nextPtr;
// Free all allocated memory - first the struct members,
// then the struct itself.
free(currentPtr->firstName);
free(currentPtr->lastName);
free(currentPtr);
// Advance to the next item in the list.
currentPtr = nextPtr;
} while (currentPtr != NULL);
}
int main()
{
int numStudents = 0;
// Temporary buffers to hold input - these are copied to an allocated portion of
// memory for each name when creating the record in createRecord().
char fBuf[NAME_LEN + 1] = { 0 };
char lBuf[NAME_LEN + 1] = { 0 };
// This is the pointer to the first record in our list.
StudentRecord *headPtr = NULL;
puts("PROG1955 Lab 6 - A program to store and display first and last names of students");
puts("Please enter the number of students");
// Prompt for the size of the class.
GetValue(&numStudents);
for (int i = 0; i < numStudents; i++)
{
// First we zero out our temporary first and last names buffer arrays.
memset(fBuf, 0, NAME_LEN + 1 * sizeof(char));
memset(lBuf, 0, NAME_LEN + 1 * sizeof(char));
// Now we get the first and last name.
printf("Please enter the first name for student #%d:\n", i + 1);
GetName(fBuf);
printf("Please enter the last name for student #%d:\n", i + 1);
GetName(lBuf);
// Record is appended to the list.
insertRecord(&headPtr, createRecord(fBuf, lBuf));
}
puts("Student records listing:");
listRecords(&headPtr);
printf("Freeing allocated memory... ");
freeRecords(&headPtr);
puts("Done.");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment