我需要读入 .csv
文件并打印其内容、学生的姓名和年龄。实际输出是正确的,但附加了垃圾字符。程序也会因段错误而终止!由于某种原因,这些问题不会出现在 OSX 上,但会出现在 Windows 上。
到目前为止的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_LINE_LENGTH 80
#define MAX_NUM_STUDENTS 500
#define MAX_NAME_SIZE 50
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];
Student* student = NULL;
char* inputLine = fgets(buffer, MAX_LINE_LENGTH, file);
if (inputLine != NULL) { // Proceed only if we read something
char* commaPos = strchr(buffer, ',');
if (commaPos != NULL && commaPos > buffer) {
int age = atoi(commaPos + 1);
*commaPos = '\0'; // null-terminate the name
student = newStudent(buffer, age);
}
}
return student;
}
int precedes(const Student* new, const Student* old)
{
int final = strcmp(old->name, new->name);
if (final == 0) {
if (old->age <= new->age) {
final = -1;
} else {
final = 1;
}
}
return final;
}
Student* insert(Student* student, Student* list)
{
Student* current = list;
if (list == NULL) {
student->next = list;
list = student;
} else if (precedes(current, student) < 0) {
student->next = current;
current = student;
list = current;
} else {
while(current->next && precedes(student, current->next) < 0) {
current = current->next;
}
student->next = current->next;
current->next = student;
}
return list;
}
Student* readStudents(FILE *file)
{
Student* student_list;
Student* student = readOneStudent(file);
while (student != NULL) {
student_list = insert(student, student_list);
student = readOneStudent(file);
}
return student_list;
}
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);
}
}
输入:
Zaphod Beeblebrox,250
Albert Einstein,133
Albert Einstein,7
输出按学生姓名的字母顺序排序,然后按年龄递增。
预期输出:
Albert Einstein (7)
Albert Einstein (133)
Zaphod Beeblebrox (250)
在 Windows 上,输出附加:
p @ (0)
然后出现段错误。
最佳答案
student_list
是一个未初始化的堆栈变量。在某些机器上它可能是 0 (NULL),但这不一定是真的。一般来说,您应该期望初始化的堆栈变量包含该内存位置中的任何垃圾。
这是简单的修复:
Student* readStudents(FILE *file)
{
Student* student_list = NULL;
Student* student = readOneStudent(file);
while (student != NULL) {
student_list = insert(student, student_list);
student = readOneStudent(file);
}
return student_list;
}
该错误是在此处的插入方法中触发的:
if (list == NULL) {
student->next = list;
list = student;
}
无论变量list
指向什么,都将用于排序。在您的情况下,它看起来比所有合法输入“更大”,并且垃圾进入了链接列表的后面。然后,打印函数将继续取消引用未初始化的 next
指针,直到触发 SIGSEGV
。
要调试此类问题,您可能需要查看 valgrind .
关于c - csv 文件中的指针和结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51939253/