Reputation: 193
I am new to C. I have just learned pointers and struct
.I am trying to modify the following program so that each student read is inserted at the front of the list of students, not at the end. How can I achieve it?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_LINE_LENGTH 80 // The longest line this program will accept
#define MAX_NUM_STUDENTS 500 // The maximum number of students this program can handle
#define MAX_NAME_SIZE 50 // The maximum allowable name length
typedef struct student_s Student;
struct student_s {
char name[MAX_NAME_SIZE];
int age;
Student* next; // Pointer to next student in a list
};
Student studentPool[MAX_NUM_STUDENTS]; // The student pool
int firstFree = 0;
Student* newStudent(const char* name, int age)
{
Student* student = NULL;
if (firstFree < MAX_NUM_STUDENTS) {
student = &studentPool[firstFree];
firstFree += 1;
strncpy(student->name, name, MAX_NAME_SIZE);
student->name[MAX_NAME_SIZE - 1] = '\0'; // Make sure it's terminated
student->age = age;
student->next = NULL;
}
return student;
}
Student* readOneStudent(FILE* file)
{
char buffer[MAX_LINE_LENGTH]; // Buffer into which we read a line from stdin
Student* student = NULL; // Pointer to a student record from the pool
// Read a line, extract name and age
char* inputLine = fgets(buffer, MAX_LINE_LENGTH, file);
if (inputLine != NULL) { // Proceed only if we read something
char* commaPos = strchr(buffer, ',');
if (commaPos != NULL) {
int age = atoi(commaPos + 1);
*commaPos = '\0'; // null-terminate the name
student = newStudent(buffer, age);
}
}
return student;
}
Student* readStudents(FILE *file)
{
Student* first = NULL; // Pointer to the first student in the list
Student* last = NULL; // Pointer to the last student in the list
Student* student = readOneStudent(file);
while (student != NULL) {
if (first == NULL) {
first = last = student; // Empty list case
} else {
last->next = student;
last = student;
}
student = readOneStudent(file);
}
return first;
}
void printOneStudent(Student student)
{
printf("%s (%d)\n", student.name, student.age);
}
void printStudents(const Student* student)
{
while (student != NULL) {
printOneStudent(*student);
student = student->next;
}
}
int main(void)
{
FILE* inputFile = fopen("studlist.txt", "r");
if (inputFile == NULL) {
fprintf(stderr, "File not found\n");
} else {
Student* studentList = readStudents(inputFile);
printStudents(studentList);
}
}
Upvotes: 0
Views: 185
Reputation: 754280
You currently have this code to insert at the end (of a non-empty list):
if (first == NULL) {
first = last = student; // Empty list case
} else {
last->next = student;
last = student;
}
To insert at the front of a non-empty list, you simply need to make the new student into the first student each time, by making its next
pointer point to the current first
student, and making the first
pointer point at the new student.
if (first == NULL) {
first = last = student; // Empty list case
} else {
student->next = first;
first = student;
}
Draw the boxes; connect them with arrows. It should become obvious.
Also, you could simply use:
student->next = first;
first = student;
If first
is null, student->next
will be (re)set to null, so there's no need for a special case on first
. Since last
was only used within the function for adding to the end of the list, when inserting at the front, there's no need for last
at all. These two observations make the code still simpler than the first version proposed.
Upvotes: 4