c - csv 文件中的指针和结构

标签 c file pointers struct nodes

我需要读入 .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/

相关文章:

c - 使用 mmap 写文件

c - Windows 上出现段错误,但 Linux 上没有(包括 GDB 信息)- C

c# - 不断将数据写入文件

c++ - 使用指向 typedef 固定长度数组的指针执行 memcpy 时是否需要取消引用?为什么或者为什么不?

c - 在函数中重新分配指向 char 数组的指针

c - MISRA C 2012 规则 16.1 所有 switch 语句都应格式正确

c - 这个指针应该这样操作吗?基础C

php - 是否有一个有效的单线程序来获取目录中的第一个文件?

ios - ios开发中获取文档文件夹后的路径

c++ - head->next 不为空