C语言使用strtok、fgets读取进程文件做Round Robin调度时进程名错误
问题根因
你的代码存在3个核心错误导致进程名读取异常:
- 你直接将
strtok()返回的指针赋值给process[process_count].name:strtok()返回的指针指向栈上的临时缓冲区string,每次循环调用fgets()时都会覆盖string的内容,所有进程的name指针最终都会指向同一块被反复覆盖的内存,自然读取不到正确的进程名。 - 你错误地提前读取了第一行文件内容解析时间片:按照你给出的示例,文件第一行就是进程数据
P1 0 3,但代码上来就调用fgets(string, 150, file)读取第一行去解析时间片,直接丢弃了第一行的进程数据,同时如果第一行没有=和+字符,解析出来的time_quantum也是非法值。 - 没有处理
fgets()读取到的行尾换行符:行尾的\n会被带入分词逻辑,可能导致最后一个字段解析异常。
修复方案
第一步 调整结构体存储逻辑
如果你的Process结构体中name是char*类型,需要为每个进程名单独分配内存存储,不能直接复用string缓冲区的指针。
第二步 对齐文件格式逻辑
如果你的文件第一行确实是时间片配置行(格式例如quantum=4),请确保第一行不是进程数据;如果文件全是进程行,删掉提前读第一行解析时间片的逻辑,或者将时间片配置放在其他位置。
第三步 增加换行符处理、字符串拷贝逻辑
修复后的代码如下:
#include <string.h> #include <stdlib.h> #include <stdio.h> // 假设Process结构体定义如下,根据你的实际定义调整 typedef struct Process { char* name; int starting_time; int remaining_time; } Process; // 队列相关定义你自己保留 void RoundRobin(char *filename) { // Queue *q = initQueue(); char string[MAX_SIZE]; FILE *file; Process process[20]; char *token; file = fopen(filename, "r"); if (!file) { printf("File Cannot Be Opened"); return; // 打开失败直接返回,避免后续空指针操作 } // --- 时间片解析逻辑,如果你的文件第一行不是时间片请删掉这段 --- fgets(string, 150, file); // 先去掉行尾换行 string[strcspn(string, "\n")] = '\0'; token = strtok(string, "="); token = strtok(NULL, "+"); int time_quantum = atoi(token); // --- 时间片解析逻辑结束 --- int process_count = 0; while (fgets(string, 150, file) && process_count < 20) { // 加数组边界判断避免越界 // 先去掉行尾的换行符 string[strcspn(string, "\n")] = '\0'; char *token1; token1 = strtok(string, " "); // 单独分配内存拷贝进程名,不要直接用strtok返回的指针 process[process_count].name = malloc(strlen(token1) + 1); strcpy(process[process_count].name, token1); token1 = strtok(NULL, " "); process[process_count].starting_time = atoi(token1); token1 = strtok(NULL, " "); process[process_count].remaining_time = atoi(token1); process_count++; } for (int i = 0; i < process_count; i++) { printf("%s %d %d\n", process[i].name, process[i].starting_time, process[i].remaining_time); // 最后不用的时候记得free掉name的内存避免内存泄漏 free(process[i].name); } fclose(file); }
额外注意事项
- 操作数组时加边界判断,避免进程数超过20时数组越界。
- 文件打开失败后要直接返回,不要继续执行后续读文件逻辑。
- 动态分配的
name内存使用完后要记得释放,避免内存泄漏。
内容的提问来源于stack exchange,提问作者HosnyyHanyy
相关产品推荐
相关产品推荐

