gpt4 book ai didi

c - 解析配置文件中带有前导和终止空格的简单名称/值对设置 - C

转载 作者:行者123 更新时间:2023-11-30 17:09:30 25 4
gpt4 key购买 nike

这是我到目前为止编写的代码。如果我的缓冲区大小过大,我深表歉意。

这个想法是读取整个配置文件(在本例中,它是 file.conf),现在我们假设它存在。稍后我会添加错误检查。

一旦文件被读入堆栈空间,getcfg()函数就会在配置数据中搜索指定的名称,如果找到,则返回相应的值。当配置文件在名称或值之前包含前导空格时,我的函数起作用;此类空格将被忽略。

假设这是我的配置文件:

something=data
apples=oranges
fruit=banana
animals= cats
fried =chicken

我的代码将与配置文件的前四个条目一起正常工作。例如,如果我使用“something”作为名称,那么将返回“data”。

由于“fried”之后和 = 之前的尾随空格,最后一项目前还无法工作。我也希望能够让我的函数自动删除这些空格,特别是在选项格式如

的情况下
somethingelse = items

开始使用。 (请注意 = 符号两侧的空格。)

如何制作一个 CPU 密集度较低的程序版本,在处理名称和值时还可以检测并删除名称和值中的尾随空格?

这是我当前的代码:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int getcfg(char* buf, char *name, char *val) {
int fl = 0, n = 0;
char cfg[1][10000], *p = buf;

memset(cfg, 0, sizeof(cfg));
while (*p) {
if (*p == '\n') {
if (strcmp(cfg[0], name) == 0) {
strcpy(val, cfg[1]);
return 1;
}
memset(cfg, 0, sizeof(cfg));
n = 0;
fl = 0;
} else {
if (*p == '=') {
n = 0;
fl = 1;
} else {
if (n != 0 || *p != ' ') {
cfg[fl][n] = *p;
n++;
}
}
}
p++;
}

return 0;
}

int main() {
char val[10000], buf[100000]; //val=value of config item, buf=buffer for entire config file ( > 100KB config file is nuts)

memset(buf, 0, sizeof(buf));
memset(val, 0, sizeof(val));

int h = open("file.conf", O_RDONLY);

if (read(h, buf, sizeof(buf)) < 1) {
printf("Can't read\n");
}
close(h);

printf("Value stat = %d ", getcfg(buf, "Item", val));
printf("Result = '%s'\n", val);

return 0;
}

最佳答案

Behold 是一个小型(约 15 行)基于 sscanf 的 read_params() 函数,它可以完成这项工作。作为奖励,它理解评论并提示错误行(如果有):

$ cat config_file.c 
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/errno.h>

#define ARRAY_SIZE(a) ((sizeof (a)) / (sizeof (a)[0]))

enum { MAX_LEN=128 };

struct param {
char name[MAX_LEN];
char value[MAX_LEN];
};

void strtrim(char *s)
{
char *p = s + strlen(s);

while (--p >= s && isspace(*p))
*p = '\0';
}

int read_params(FILE *in, struct param *p, int max_params)
{
int ln, n=0;
char s[MAX_LEN];

for (ln=1; max_params > 0 && fgets(s, MAX_LEN, in); ln++) {
if (sscanf(s, " %[#\n\r]", p->name)) /* emty line or comment */
continue;
if (sscanf(s, " %[a-z_A-Z0-9] = %[^#\n\r]",
p->name, p->value) < 2) {
fprintf(stderr, "error at line %d: %s\n", ln, s);
return -1;
}
strtrim(p->value);
printf("%d: name='%s' value='%s'\n", ln, p->name, p->value);
p++, max_params--, n++;
}

return n;
}

int main(int argc, char *argv[])
{
FILE *f;
struct param p[32];

f = argc == 1 ? stdin : fopen(argv[1], "r");
if (f == NULL) {
fprintf(stderr, "failed to open `%s': %s\n", argv[1],
strerror(errno));
return 1;
}

if (read_params(f, p, ARRAY_SIZE(p)) < 0)
return 1;

return 0;
}

让我们看看它是如何工作的(为了清楚起见,引号标记了每行的开头和结尾):

$ cat bb | sed -e "s/^/'/" -e "s/$/'/" | cat -n
1 'msg = Hello World! '
2 'p1=v1'
3 ' p2=v2 # comment'
4 ' '
5 'P_3 =v3'
6 'p4= v4#comment'
7 ' P5 = v5 '
8 ' # comment'
9 'p6 ='
$ ./config_file bb
1: name='msg' value='Hello World!'
2: name='p1' value='v1'
3: name='p2' value='v2'
5: name='P_3' value='v3'
6: name='p4' value='v4'
7: name='P5' value='v5'
error at line 9: p6 =

注意:作为额外的奖励,该值可以是任何内容,除了 #\n\r 字符,包括空格,如上面的“Hello World!”所示。例子。如果不需要,请在第二个 sscanf() 处的值的异常(exception)列表中添加空格和制表符(或在此处指定接受的字符)并删除 strtrim() 函数。

关于c - 解析配置文件中带有前导和终止空格的简单名称/值对设置 - C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33268023/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com