C语言如何读取文本文件并提取冒号后的指定内容?
解决提取配置文件冒号后内容的问题
你的现有代码存在几个关键问题:
- 用
feof作为循环条件容易导致最后一行重复读取或漏读 - 找到冒号后直接把冒号字符赋值给
r.startCash,完全没获取到冒号后面的实际内容 - 没有区分不同配置项的类型(数字/Yes/No),也没有对应到
Rules结构体的各个字段
下面是两种可靠的解决思路:
思路1:利用固定格式直接匹配读取
因为你的配置文件每行格式是固定的Key: Value,可以直接用fscanf的格式字符串精准匹配每个配置项,这种方式简单高效:
首先先正确定义Rules结构体:
#include <stdio.h> #include <string.h> // 定义规则结构体,对应配置文件的每个项 typedef struct { int startCash; int turnLimit; int playersLeftToEnd; int propertySetMultiplier; int housesBeforeHotels; int mustBuildEvenly; // 1=Yes, 0=No int putMoneyInFreeParking; // 1=Yes, 0=No int auctionProperties; // 1=Yes, 0=No int salaryMultiplierOnGo; } Rules;
然后实现读取函数:
void readRules(char* file_name) { Rules r; FILE *file = fopen(file_name, "r"); if (file == NULL) { printf("Could not open %s\n", file_name); return; } // 按固定格式读取每个配置项,跳过冒号前的文本,直接读取冒号后的值 fscanf(file, "Starting Cash: %d", &r.startCash); fscanf(file, "Turn Limit (-1 for no turn limit): %d", &r.turnLimit); fscanf(file, "Number of Players Left To End Game: %d", &r.playersLeftToEnd); fscanf(file, "Property Set Multiplier: %d", &r.propertySetMultiplier); fscanf(file, "Number of Houses Before Hotels: %d", &r.housesBeforeHotels); // 处理Yes/No类型的项,先读字符串再转成整数标记 char yesNo[4]; fscanf(file, "Must Build Houses Evenly: %3s", yesNo); r.mustBuildEvenly = strcmp(yesNo, "Yes") == 0 ? 1 : 0; fscanf(file, "Put Money In Free Parking: %3s", yesNo); r.putMoneyInFreeParking = strcmp(yesNo, "Yes") == 0 ? 1 : 0; fscanf(file, "Auction Properties: %3s", yesNo); r.auctionProperties = strcmp(yesNo, "Yes") == 0 ? 1 : 0; fscanf(file, "Salary Multiplier For Landing On Go: %d", &r.salaryMultiplierOnGo); // 测试输出读取到的内容 printf("Starting Cash: %d\n", r.startCash); printf("Turn Limit: %d\n", r.turnLimit); printf("Must Build Evenly: %s\n", r.mustBuildEvenly ? "Yes" : "No"); // 其他字段可以类似输出 fclose(file); }
思路2:逐行读取并分割键值对(更通用)
如果以后配置项可能变化,或者想做更通用的解析,可以逐行读取,然后找到冒号的位置,提取后面的内容:
void readRules(char* file_name) { Rules r; FILE *file = fopen(file_name, "r"); if (file == NULL) { printf("Could not open %s\n", file_name); return; } char line[256]; // 逐行读取,直到文件结束 while (fgets(line, sizeof(line), file) != NULL) { // 找到冒号的位置 char* colonPos = strchr(line, ':'); if (colonPos == NULL) { continue; // 跳过无效行 } // 冒号后移一位,跳过空格,得到值的起始位置 char* valueStart = colonPos + 1; while (*valueStart == ' ') { valueStart++; } // 根据行首的关键字匹配对应的字段 if (strstr(line, "Starting Cash") != NULL) { sscanf(valueStart, "%d", &r.startCash); } else if (strstr(line, "Turn Limit") != NULL) { sscanf(valueStart, "%d", &r.turnLimit); } else if (strstr(line, "Must Build Houses Evenly") != NULL) { char yesNo[4]; sscanf(valueStart, "%3s", yesNo); r.mustBuildEvenly = strcmp(yesNo, "Yes") == 0 ? 1 : 0; } // 其他字段类似添加判断 } // 输出测试 printf("Starting Cash: %d\n", r.startCash); printf("Must Build Evenly: %s\n", r.mustBuildEvenly ? "Yes" : "No"); fclose(file); }
关键注意点:
- 不要用
feof作为循环条件,应该用fgets或fscanf的返回值来判断是否读取成功 - 处理Yes/No时,用
strcmp比较字符串,转成整数存储更方便后续逻辑判断 - 读取字符串时要注意缓冲区大小,避免溢出(比如用
%3s读取Yes/No,因为最多3个字符)
内容的提问来源于stack exchange,提问作者andyong5
相关产品推荐
相关产品推荐

