C从文件中读取字符串,并拆分为数组

时间:2016-01-23 22:30:41

标签: c arrays string variables io

我正在尝试在标准C中读取包含变量和值的数据文件,并将每个值和变量分配给它们自己的数组。

数据文件如下所示:

 recipName=Fork
 friend=Cup
 sonName=Spork

......等等。我想将变量存储在一个数组中的=之前,将值存储在另一个数组中。我不想使用2D数组,因为我后来有一个需要单独项目的功能。最终目标是使用数据文件中提供的值替换模板文件中的所有变量,但由于=符号,我无法弄清楚如何将它们从数据文件中取出。我使用fgets()来检索模板文件,但我不知道如何继续这里。

3 个答案:

答案 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。)

根据您的问题,这是一个版本,它将变量名称和值读入两个独立的数组varsvals。 解析文件时动态重新分配数组。

#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;,你很可能会覆盖他们的数据。

您可以通过逐字符阅读来避免这些问题。

我希望这会有所帮助。 :)