如何读取文本文件中可变数量前置任务ID及标题填充Task结构体
解决可变数量前置任务与任务标题的文件读取问题
你的问题核心是处理每行中可变数量的前置任务ID,同时还要捕获可能包含空格的任务标题——原代码只读取了前三个固定字段,自然没法处理后面的可变内容。我给你提供一个实用的解决方案,用字符串分割的方式来灵活处理这些字段:
核心思路
因为每行的字段是用空格分隔的,我们可以用strtok函数把整行拆成一个个"令牌"(token),然后按顺序处理:
- 先提取前三个固定字段:任务ID、时长、前置任务数量
- 根据前置任务数量,提取对应个数的前置ID存入数组
- 把剩下的所有令牌拼接起来,作为任务标题(毕竟标题可能包含空格,比如
permis exploitation这种)
修改后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> // 根据你的需求调整这两个宏的大小 #define NMAXPREV 10 #define LGMAX 100 typedef struct{ int id; int duration; int nbPrev; /* 所需前置任务的数量 */ int prev[NMAXPREV]; /* 所需前置任务ID数组 */ char title[LGMAX]; }Task ; int readTasksFile(char* file_name, Task t[]) { FILE* f; char line[256] = {'\0'}; int taskCount = 0; // 打开文件失败的错误处理 if((f = fopen(file_name, "r")) == NULL) { perror("The file couldn't be opened"); exit(EXIT_FAILURE); } // 逐行读取文件 while (fgets(line, 256, f) != EOF) { // 去掉行尾的换行符,避免标题里带换行 size_t lineLen = strlen(line); if (lineLen > 0 && line[lineLen-1] == '\n') { line[lineLen-1] = '\0'; } Task* current = &t[taskCount]; char* token = strtok(line, " "); int tokenIdx = 0; // 读取任务ID if (token) { current->id = atoi(token); tokenIdx++; token = strtok(NULL, " "); } // 读取任务时长 if (token) { current->duration = atoi(token); tokenIdx++; token = strtok(NULL, " "); } // 读取前置任务数量 if (token) { current->nbPrev = atoi(token); tokenIdx++; token = strtok(NULL, " "); } // 读取可变数量的前置任务ID int prevIdx = 0; while (prevIdx < current->nbPrev && token) { current->prev[prevIdx] = atoi(token); prevIdx++; token = strtok(NULL, " "); } // 拼接剩余所有token作为任务标题(处理带空格的标题) current->title[0] = '\0'; while (token) { // 如果标题已有内容,先加空格分隔 if (strlen(current->title) > 0) { strcat(current->title, " "); } // 安全拼接,避免缓冲区溢出 strncat(current->title, token, LGMAX - strlen(current->title) - 1); token = strtok(NULL, " "); } taskCount++; } fclose(f); // 返回实际读取的任务数量,比返回0更有意义 return taskCount; }
关键细节说明
- 处理换行符:
fgets会把行尾的\n也读进来,我们提前去掉它,避免标题里出现不必要的换行符 - 安全拼接标题:用
strncat而不是直接strcat,防止标题过长导致缓冲区溢出 - 返回任务数量:原代码返回0没什么用,改成返回实际读取的任务数,调用者可以直接知道有多少个任务被加载
- 边界情况处理:比如前置任务数量为0的行(像第一行
0 0 0 debut),代码会直接跳过前置ID的读取,直接处理标题
内容的提问来源于stack exchange,提问作者Godrod
相关产品推荐
相关产品推荐

