C语言程序运行与调试输出不一致问题求助
问题现象
- 程序功能:从
input.txt读取学生信息存入链表,按出生年份排序后打印 - 运行时输出无意义数字,每次结果不同
- 调试时输出完全正确
运行时输出
Student names in ascending order by birthday:
-2013265920000
M-2013265920-2013265920-2013265920-2013265920
Ali Pehlivan;2005
-2013265920-2013265920-20132659200
调试时输出
Student names in ascending order by birthday:
Ali Pehlivan;2005
Selami Kilic;2002
Esma Sultan;2001
Mehmet Ali Sarsil;2000
input.txt内容
040160811;Ali Pehlivan;2005 040180224;Mehmet Ali Sarsil;2000 820190040;Esma Sultan;2001 150190207;Selami Kilic;2002
完整代码
#include <stdio.h> #include <stdlib.h> struct n { char number[9]; char name; int year; struct n* next; }; typedef struct n node; struct s_node { char* number; struct s_node *next; }*stack = NULL; int isLetter(char character); int isNumber(char character); int charToInt(char character); node** sortAndPrintByBirth(node* *list); node** sortAndPrintByFaculty(node* *list); int length(node** list); void push(char* value); char* pop(); void display(); int main() { node* Student; Student = (node *) malloc(sizeof(node)); node* head1; node* head; head = Student; head1 = head; node* Students[100]; FILE* file; file = fopen("C:\\Users\\PC\\CLionProjects\\untitled1\\input.txt", "r"); char fchar; fchar = fgetc(file); int switchNY = 0; // 0 for school number, 1 for birth year int studentCounter = 0; while(fchar != EOF){ if(isLetter(fchar)){ head1->name = fchar; head1->year = (int) NULL; head1->next = malloc(sizeof(node*)); head1 = head1->next; fchar = fgetc(file); }else if(isNumber(fchar)){ if(switchNY == 0){ for(int i = 0; i < 9; i++){ head1->number[i] = fchar; head1->year =(int) NULL; head1->number[i+1] = (char) NULL; fchar = fgetc(file); } }else { for (int i = 0; i < 4; i++) { head1->year = charToInt(fchar); head1->next = malloc(sizeof(node *)); head1 = head1->next; fchar = fgetc(file); } if (fchar == EOF) { Students[studentCounter] = head; Students[studentCounter + 1] = NULL; fchar = fgetc(file); Student = (node *) malloc(sizeof(node)); head = Student; head1 = head; studentCounter++; } switchNY = 0; } }else if(fchar == '\n'){ Students[studentCounter] = head; Students[studentCounter+1] = NULL; fchar = fgetc(file); Student = (node *) malloc(sizeof(node)); head = Student; head1 = head; studentCounter++; }else if(fchar == ';'){ head1->year = (int) NULL; if(switchNY == 1){ head1->name = fchar; } switchNY = 1; fchar = fgetc(file); head1->next = malloc(sizeof(node*)); head1 = head1->next; } } fclose(file); sortAndPrintByBirth(Students); //sortAndPrintByFaculty(Students); return -1; } int isLetter(char character) { return ((character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z') || (character == ' ')); } int isNumber(char character) { return (character >= '0' && character <= '9'); } int charToInt(char character) { if (character >= '0' && character <= '9') { return character - '0'; } else { return -1; } } node** sortAndPrintByBirth(node* *list) { int i = length(list); node* result[i]; for(int a=0; a<i; a++){ result[a] = list[a]->number; } for(int count = 0; count < i-1; count++){ for(int step = 0; step < i-1 ; step++){ node *iter1; node *iter2; iter1 = result[step]; iter2 = result[step+1]; int year1 = 0,year2 = 0; while (iter2 != NULL){ while ((void *) iter1->next->year == NULL) { iter1 = iter1->next; } while ((void *) iter2->next->year == NULL) { iter2 = iter2->next; } for (int j = 0; j < 4; ++j) { iter1 = iter1->next; year1 = 10 * year1 + iter1->year; } for (int j = 0; j < 4; ++j) { iter2 = iter2->next; year2 = 10 * year2 + iter2->year; } break; } if(year1 < year2){ node* temp; temp = result[step]; result[step] = result[step+1]; result[step+1] = temp; }else if(year2 == year1){ continue; } } } node* iter3; printf("Student names in ascending order by birthday:\n"); for (int j = 0; j < i; ++j) { iter3 = result[j]->next; while(iter3->year == (int )NULL){ printf("%c",iter3->name); iter3 = iter3->next; } for (int k = 0; k < 4; ++k) { printf("%d",iter3->year); iter3 = iter3->next; } printf("\n"); } return result; } node** sortAndPrintByFaculty(node* *list){ int i = length(list); node* result[i]; char* temp[i]; for(int a=0; a<i; a++){ temp[a] = list[a]->number; } for(int count = 0; count < i-1; count++){ for(int step = 0; step < i-1 ; step++){ for(int digit = 0; digit < 3 ; digit ++){ if(charToInt(temp[step][digit]) < charToInt(temp[step+1][digit])){ char* c; c = temp[step]; temp[step] = temp[step+1]; temp[step+1] = c; break; }else if(charToInt(temp[step][digit]) == charToInt(temp[step+1][digit])){ continue; }else{ break; } } } } for (int j = 0; j < i; ++j) { push(temp[j]); } printf("School numbers by the faculty codes in ascending order:\n"); for (int j = 0; j < i; ++j) { printf("%s\n", pop()); } return result; } int length(node** list){ int value = 0; while(list[value] != NULL){ value++; } return value; } void push(char* value) { struct s_node *m; m=(struct s_node*)malloc(sizeof(struct s_node )); m->number= value ; m->next=stack; stack=m; } void display() { struct s_node *temp=stack; while(temp!=NULL) { printf("%s\t", temp->number); temp=temp->next; } } char* pop() { struct s_node *temp ; if (stack == NULL) { printf("\nSTACK is Empty."); } else { char* i = stack->number; temp = stack; stack = stack->next; free(temp); return i; } return NULL; }
问题分析与修复
1. 核心错误:指针类型不匹配与非法内存访问
sortAndPrintByBirth函数中,result[a] = list[a]->number;存在致命问题:
list[a]是node*类型,list[a]->number是char[9]数组,会被隐式转为char*指针result是node*数组,将char*赋值给node*导致类型完全不匹配,后续把字符串地址当成链表节点地址访问,读取的内容完全不符合预期,引发乱码。
修复:
将result数组改为直接存储节点指针:
for(int a=0; a<i; a++){ result[a] = list[a]; }
2. 链表节点内存分配错误
原代码中head1->next = malloc(sizeof(node*));分配的是指针大小的内存,而非node结构体的完整大小,导致内存不足,访问结构体成员时越界。
修复:
改为分配结构体大小的内存:
head1->next = malloc(sizeof(node));
3. 年份读取逻辑冗余且易出错
原代码将年份的每个数字单独存入一个节点的year字段,后续需要遍历4个节点拼接年份,逻辑复杂且容易出错。
修复:
读取时直接拼接为完整年份值存入单个节点:
else if(isNumber(fchar)){ if(switchNY == 0){ // 学号读取逻辑不变 }else { int year = 0; for (int i = 0; i < 4; i++) { year = year * 10 + charToInt(fchar); fchar = fgetc(file); } head1->year = year; head1->next = malloc(sizeof(node)); head1 = head1->next; switchNY = 0; } }
4. 无效的NULL赋值
head1->year = (int) NULL;是错误用法,NULL是指针类型,强制转为int会得到平台相关值,无法作为有效标记。
修复:
用特殊值(如-1)标记未初始化的年份:
head1->year = -1;
5. 文件路径转义错误
原文件路径中的反斜杠未转义,会被解析为转义字符,导致文件无法打开。
修复:
转义路径中的反斜杠:
file = fopen("C:\\Users\\PC\\CLionProjects\\untitled1\\input.txt", "r");
内容的提问来源于stack exchange,提问作者çağatay dişli

