【问题标题】:C - Read from .INI file and pass values to varsC - 从 .INI 文件中读取并将值传递给 vars
【发布时间】:2018-06-29 08:54:14
【问题描述】:

我正在为学校做一个项目,我需要读取一个 .INI 文件来启动我的游戏变量。问题是,我似乎无法理解 strtok 的工作原理,此时我真的很困惑。

我知道我返回的是一个空结构,因为我不知道如何将特定值放入变量中!

这是我的 read_from_config.h

#ifndef READ_FROM_CONFIG_H
#define READ_FROM_CONFIG_H
#define MAXSTR 500

typedef struct {
  unsigned int xdim;
  unsigned int ydim;
  unsigned int nzombies;
  unsigned int nhumans;
  unsigned int nzplayers;
  unsigned int nhplayers;
  unsigned int turns;
} CONFIG;

CONFIG read_config(char *argv[]);

#endif

这是我的 read_from_config.c

#include "read_from_config.h"
#include "example.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;

  fp = fopen(filename, "r");
  if (fp == NULL) {
    fprintf(stderr, "Não foi possível abrir ficheiro de configuração.");
    fprintf(stderr, "\nModo de uso: ./program_name config.ini");
  }

  while (fgets(str, MAXSTR, fp) != NULL) {
      for (int i = 0; i != '\0'; i++) {
        char *equal = strpbrk (str, "=");
        if (equal) {
          token = strtok(str, "=");
        }
      }
  }
  printf("%d", token[0]);
  CONFIG config;
  return config;
}

CONFIG.INI

; Dimension of the grid
xdim=20
ydim=20
; Inicial number of zombies and humans
nzombies=20
nhumans=20
; Number of zombies and humans controlled by players
nzplayers=0
nhplayers=1
; Number of maximum turns
maxturns=1000

【问题讨论】:

  • 使用 .ini 文件是不是强迫症?而且,自己动手?
  • 当心:你的 ini 文件让我知道分号 (;) 也需要特殊处理......你应该想知道值键周围是否允许空格并且应该去掉。

标签: c string file ini


【解决方案1】:

函数strtok 仅在第一次被调用时接受一个字符串。 全部 后续调用必须通过NULL

man strtok

#include <string.h>
char *strtok(char *str, const char *delim);

描述

strtok() 函数将字符串分成零个或多个非空标记的序列。 在第一次调用strtok() 时,要在str 中指定要解析的字符串。 在应解析相同字符串的每个后续调用中,str 必须为 NULL

例子:

char line[] = "a,b,c,d,e,f\n"; // to simulate an fgets line
char *token = strtok(line, ",\n");  // you can add \n to the separator
                                    // to get rid of the \n at the end

puts(token); // prints a
while(token = strtok(NULL, ",\n"))
    puts(token);  // prints b then c etc..

记住strtok修改了源,这会失败:

strtok("a,b,c", ",");

因为字符串文字是不可修改的。在这种情况下,您必须制作副本 到char[] 或动态分配的char*

如果您需要在解析后保持源完整,那么您肯定 需要复印。

在你的代码中你这样做:

printf("%d", token[0]);

这不是错误的,但可能不是您想要做的。这条线不 打印第一个字符,它打印第一个字符的ascii值。

这个

printf("%c", token[0]);

将打印第一个字符。

你也在做

CONFIG read_config(char *argv[]) {
    ...
    CONFIG config;
    return config;
}

您正在返回一个未初始化的 CONFIG 对象,您忽略了解析 并且您的配置对象中没有设置任何内容。

你的解析也有点奇怪。

for (int i = 0; i != '\0'; i++)

循环立即退出,因为0 == '\0'!我不明白你是什么 尝试处理它。

我将首先创建一个辅助函数来填充配置的值,请​​参阅 set_config_val。然后你可以像这样解析它:

CONFIG read_config(char *argv[]) {
    ...

    const char *delim = "=\n";
    CONFIG config;

    while (fgets(str, MAXSTR, fp) != NULL) {

        if(strchr(str, '='))
        {
            char varname[100];
            int value;

            token = strtok(line, delim);
            strcpy(varname, token);

            token = strtok(NULL, delim);
            value = atoi(token);

            set_config_val(&config, varname, value); 
        } else {
            fprintf(stderr, "Skipping line, no = found");
        }

    }

    fclose(fp);
    return config;
}


void set_config_val(CONFIG *config, const char *key, int val)
{
    if(config == NULL)
        return;

    if(strcmp(key, "xdim") == 0)
        config->xdim = val;
    else if(strcmp(key, "ydim") == 0)
        config->ydim = val;
    ...
}

【讨论】:

  • 非常感谢。它奏效了,我终于更好地理解了。
  • @RuiMartins 考虑了其他 cmets,例如来自 Serge Ballesta 的 cmets。我的解析非常基础,当你有以;# 开头的行时会中断。你应该考虑到这一点。现在您已经有了基本的代码库,您可以对其进行增强。或者您可以使用专门用于解析 ini 文件的库。有很多:google.com/…
猜你喜欢
  • 2014-02-20
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-02
  • 2015-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多