You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

学生游戏项目:读取INI文件赋值变量时strtok及结构体赋值困惑

解决INI文件读取与strtok使用问题

嘿,我来帮你搞定这个学校项目的INI读取问题!你当前的代码存在几个逻辑错误,而且对strtok的用法理解不到位,导致没法把INI里的值正确赋值给CONFIG结构体。咱们一步步来修复:

先梳理你代码里的核心问题

  • 无意义的for循环:for (int i = 0; i != '\0'; i++)这个循环完全没用,i是整数,和字符'\0'比较会导致逻辑混乱,甚至无限循环
  • 只提取了键,没处理值:你用strtok拿到了xdim这类键,但没继续提取后面的20这类值,更没把值赋值给结构体成员
  • 结构体未初始化:你最后返回的CONFIG config;是未赋值的,所以成员都是随机值或者0(取决于编译器)
  • 未处理注释和无效行:INI里的注释行(以;开头)和空行应该跳过,不然会干扰解析
  • 文件打开失败后未终止程序:如果fopen失败,后续操作fp会导致未定义行为
  • 非法访问token:循环外的printf("%d", token[0]);可能在token为NULL时崩溃

搞懂strtok的工作原理

strtok是用来分割字符串的工具,规则很简单:

  1. 第一次调用:传入要分割的字符串和分隔符,它会找到第一个分隔符,把分隔符换成'\0',返回分割后的第一个子串(键)
  2. 后续调用:传入NULL和分隔符,它会从上次分割的位置继续,返回下一个子串(值)

注意:strtok会修改原字符串,所以如果需要保留原字符串,要先复制一份

修正后的完整代码

read_from_config.c

#include "read_from_config.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

CONFIG read_config(char *argv[]) {
    char str[MAXSTR];
    FILE *fp = NULL;
    char *filename = argv[1];
    char *token;
    char *value_str;
    CONFIG config = {0}; // 初始化结构体所有成员为0

    // 打开配置文件
    fp = fopen(filename, "r");
    if (fp == NULL) {
        fprintf(stderr, "Não foi possível abrir ficheiro de configuração.\n");
        fprintf(stderr, "Modo de uso: ./program_name config.ini\n");
        exit(EXIT_FAILURE); // 打开失败直接退出,避免后续错误
    }

    // 逐行读取文件
    while (fgets(str, MAXSTR, fp) != NULL) {
        // 跳过空行和注释行(以;开头)
        if (str[0] == ';' || str[0] == '\n' || str[0] == '\r') {
            continue;
        }

        // 查找等号,找不到则跳过该行
        char *equal_sign = strpbrk(str, "=");
        if (!equal_sign) {
            continue;
        }

        // 分割键:从开头到等号
        token = strtok(str, "=");
        if (!token) {
            continue;
        }
        // 去掉键末尾的空格(比如如果有"xdim = 20"这种情况)
        token[strcspn(token, " \t")] = '\0';

        // 分割值:从等号后面到换行/空格
        value_str = strtok(NULL, "\n \t");
        if (!value_str) {
            continue;
        }

        // 将值转换为unsigned int,赋值给对应结构体成员
        unsigned int value = strtoul(value_str, NULL, 10);
        if (strcmp(token, "xdim") == 0) {
            config.xdim = value;
        } else if (strcmp(token, "ydim") == 0) {
            config.ydim = value;
        } else if (strcmp(token, "nzombies") == 0) {
            config.nzombies = value;
        } else if (strcmp(token, "nhumans") == 0) {
            config.nhumans = value;
        } else if (strcmp(token, "nzplayers") == 0) {
            config.nzplayers = value;
        } else if (strcmp(token, "nhplayers") == 0) {
            config.nhplayers = value;
        } else if (strcmp(token, "maxturns") == 0) {
            config.turns = value; // 注意INI里是maxturns,结构体里是turns,对应上
        }
    }

    fclose(fp); // 记得关闭文件!
    return config;
}

关键修复点解释

  1. 结构体初始化:CONFIG config = {0};确保所有成员初始为0,避免随机值
  2. 跳过无效行:判断行首是否为;或换行,直接跳过注释和空行
  3. 键值分割:先用strtok拿键,再用strtok(NULL, "\n \t")拿值,同时去掉值的换行和空格
  4. 安全转换数值:用strtoul把字符串转成unsigned int,比atoi更适合无符号类型
  5. 键值匹配:用strcmp判断键名,把对应的值赋值给结构体成员(注意INI里的maxturns对应结构体的turns)
  6. 关闭文件:读取完成后关闭文件,避免资源泄漏

测试代码(可选)

你可以在主函数里加一段测试,验证读取是否正确:

#include "read_from_config.h"
#include <stdio.h>

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Modo de uso: ./program_name config.ini\n");
        return 1;
    }
    CONFIG cfg = read_config(argv);
    printf("xdim: %u\n", cfg.xdim);
    printf("ydim: %u\n", cfg.ydim);
    printf("nzombies: %u\n", cfg.nzombies);
    printf("nhumans: %u\n", cfg.nhumans);
    printf("nzplayers: %u\n", cfg.nzplayers);
    printf("nhplayers: %u\n", cfg.nhplayers);
    printf("turns: %u\n", cfg.turns);
    return 0;
}

这样运行后就能看到INI里的所有值都正确读取到结构体里啦!

内容的提问来源于stack exchange,提问作者Rui Martins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:48:59