我正在尝试在标准C中读取包含变量和值的数据文件,并将每个值和变量分配给它们自己的数组。
数据文件如下所示:
recipName=Fork
friend=Cup
sonName=Spork
......等等。我想将变量存储在一个数组中的=之前,将值存储在另一个数组中。我不想使用2D数组,因为我后来有一个需要单独项目的功能。最终目标是使用数据文件中提供的值替换模板文件中的所有变量,但由于=符号,我无法弄清楚如何将它们从数据文件中取出。我使用fgets()来检索模板文件,但我不知道如何继续这里。
答案 0 :(得分:1)
您可以使用strtok来标记字符串,如下所示:
char *opt;
char *par;
char myString[20] = "recipName=Fork";
/**
* tokenise the string at the = character...
*/
opt = strtok(myString, "=");
/**
* The initial call to strtok returns the first token, everything up
* to the first = character. The next call to strtok returns the
* next token, etc.
*/
par = strtok(NULL, "=");
/**
* You can now reference your option/lvalue in opt and the parameter/rvalue
* using par.
*/
printf("%s = %s\n", opt, par);
如果每一行都是相同的格式 - 选项=值,这很好。如果您的文件包含更复杂的行,您可能需要使用诸如flex之类的内容来查看。
这是一个非常模糊的答案,我知道 - 抱歉,这个问题非常广泛。对我来说,了解文件,它可能包含的值和数据,它有多大等等,并从那里设计合适的东西是很重要的。如何存储数据等...我建议你使用strtok()并可能查看正则表达式和/或flex / bison。
但根据您提供的信息,希望它有所帮助。
答案 1 :(得分:1)
避免使用strtok。 (阅读手册页中的BUGS section。)
根据您的问题,这是一个版本,它将变量名称和值读入两个独立的数组vars
和vals
。
解析文件时动态重新分配数组。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fp;
char buf[1024];
char *p;
void *tmp;
int cnt = 0;
int ret = 1;
int i;
char **vars = NULL;
char **vals = NULL;
if (!(fp = fopen("data", "r"))) {
perror("opening data");
return ret;
}
while (fgets(buf, sizeof(buf), fp)) {
buf[strcspn(buf, "\n")] = 0;
if (!(p = strchr(buf, '=')))
continue;
*p++ = 0;
/* disallow empty names and values */
if (!strlen(buf) || !strlen(p))
continue;
if (!(tmp = realloc(vars, (cnt + 1) * sizeof(char*))))
goto out;
vars = (char**)tmp;
if (!(tmp = realloc(vals, (cnt + 1) * sizeof(char*))))
goto out;
vals = (char**)tmp;
vars[cnt] = strdup(buf);
vals[cnt] = strdup(p);
cnt++;
if (!vars[cnt-1] || ! vals[cnt-1])
goto out;
}
ret = 0;
printf("successfully parsed %d values:\n", cnt);
for (i = 0; i < cnt; i++)
printf("variable [%s] has value [%s]:\n", vars[i], vals[i]);
out:
fclose(fp);
if (vars)
for (i = 0; i < cnt; i++)
free(vars[i]);
if (vals)
for (i = 0; i < cnt; i++)
free(vals[i]);
free(vars);
free(vals);
return ret;
}
答案 2 :(得分:0)
如果你有一个需要单独项目的功能,那么strtok可能就没有了。 strtok用于定位字符串中的子字符串,其最常见的用途是将字符串解析为标记,就像编译器解析代码行一样。
让我们来看看下面的例子。
char str[20] = "recipName=Fork";
char *one = NULL;
char *two = NULL;
第一个参数是要解析的字符串;第二个是用于解析第一个字符串的一组分隔符。 Strtok首先跳过所有前导分隔符字符。如果字符串中的所有字符都是分隔符,那么它将终止并返回空指针。但是,当它找到非分隔符时,它会更改其搜索并跳过不在该集合中的所有字符;也就是说,strtok将搜索,直到找到分隔符。找到分隔符后,它将更改为空字符(&#39; \ 0&#39;),标记令牌的结尾,并返回指向新令牌字符串的指针。
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+----+
str -> | r | e | c | i | p | N | a | m | e | = | F | o | r | k | \0 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+----+
像这样调用strtok
one = strtok( str, "=" );
导致以下内容(&#34; =&#34;现在是空字符)
+---+---+---+---+---+---+---+---+---+----+---+---+---+---+----+
str -> | r | e | c | i | p | N | a | m | e | \0 | F | o | r | k | \0 |
+---+---+---+---+---+---+---+---+---+----+---+---+---+---+----+
^
|
one -----+ (first token)
再次致电strtok
two = strtok( NULL, "=" );
导致以下
+---+---+---+---+---+---+---+---+---+----+---+---+---+---+----+
str -> | r | e | c | i | p | N | a | m | e | \0 | F | o | r | k | \0 |
+---+---+---+---+---+---+---+---+---+----+---+---+---+---+----+
^ ^
| |
one -----+ (first token) two -----+ (second token)
到目前为止,所有事情都是花花公子。不过,如果你使用strlen函数,你会遇到麻烦。另外,如果你要修改&#34;一个&#34;的值。和&#34;两个&#34;,你很可能会覆盖他们的数据。
您可以通过逐字符阅读来避免这些问题。
我希望这会有所帮助。 :)