如何在c中读取文件中的单词后存储值

时间:2018-04-02 00:39:26

标签: c arrays string file

我正在尝试用C读取文件,然后在读取某个单词后存储值。例如,在我的input.txt文件中,以下是内容:

GREETINGS
Hello 13
Namaste 24
Hola 36
FLAVORS
Vanilla 23
Chocolate 78

我想阅读过去GREETINGS,然后存储Hello及其值13,然后Namaste及其值24等。然后阅读过去FLAVORS并存储Vanilla及其值23等等等等......

我知道如何打开文件但不知道如何从那里继续。

void readInput() {

    char input_file[100];

    FILE *fp;

    printf("Please enter the name of the file you would like to read: \n");
    scanf("%s", input_file);
    printf("You entered: %s\n", input_file);

    fp = fopen(input_file, "r");

    if (fp == NULL) {
        printf("File does not exist.\n");
            exit(1);
    }
    else
        printf("This file exists!\n");
}

2 个答案:

答案 0 :(得分:0)

我不确定您选择要跳过哪些行的确切标准,但阅读行的下一步是使用fscanffgetsThis tutorial should help you get started with reading files in C.

编辑,在评论后使其更具相关性:

fgets可能是更好的选择。您需要读取每一行,然后循环遍历每个字符,以检查它们是否全部为大写。 如果它们不是大写的,您可以使用格式为fscanf的{​​{1}}来扫描数据行。

答案 1 :(得分:0)

从您的示例数据中,不清楚具有数据的行是否始终具有相同的格式。所以我 建议您在变量中存储当前模式(即GREETINGSFLAVOR等),然后调用 每种模式的特定解析函数,取决于当前值 模式。

我先创建这个枚举

typedef enum {
    MODE_GREETINGS = 0,  // <-- important that this value is 0
    MODE_FLAVORS,
    ...
    MODE_INVALID
} Modes;

和一个变量(这可以是一个全局变量),所有模式:

const char *modes_lookup[] = {
    "GREETINGS",
    "FLAVORS",
    ...
};

然后我会编写一个返回模式的函数:

Modes get_mode(const char *src)
{
    if(src == NULL)
        return MODE_INVALID;

    for(size_t i = 0; i < sizeof modes_lookup / sizeof modes_lookup[0]; ++i)
    {
        if(strcmp(src, modes_lookup[i]) == 0)
            return i;
    }

    return MODE_INVALID;
}

现在您可以像这样解析文件:

char line[1024];

Modes mode = MODE_INVALID;

size_t lineno = 0;
while(fgets(line, sizeof line, fp))
{
    lineno++;
    // removing newline
    line[strcspn(line, "\n")] = 0;

    Modes newmode = get_mode(line);

    // check if line is a GREETINGS, FLAVOR, etc line
    if(newmode != MODE_INVALID)
    {
        // sets the new mode and continue with the next line
        mode = newmode;
        continue;
    }

    // parsing depending on the current mode

    if(mode == MODE_GREETINGS)
    {
        if(parse_greetings(line) == 0)
        {
            fprintf(stderr, "Cannot parse data on line %zu\n", lineno);
            break;
        }

        continue;
    } 

    if(mode == MODE_FLAVORS) {
        if(parse_flavor(line) == 0)
        {
            fprintf(stderr, "Cannot parse data on line %zu\n", lineno);
            break;
        }

        continue;
    }

    // more (if mode == MODE_xxx) cases as needed

    if(mode == MODE_INVALID)
    {
        // mode == MODE_INVALID
        fprintf(stderr, "File does not start with a mode line.\n");
        break;
    }

}

然后你必须编写parse_greetingsparse_flavorparse_xxx函数。就像我说的 之前,从您的样本中不清楚格式是否总是如此 同样,这取决于您使用strtok还是sscanf的格式。也 您对如何以及在何处存储值的描述非常模糊,因此 我不知道什么对你最好。 最简单的是sscanf,如果数据线变得更复杂,那么就可以 使用strtok

例如sscanf

int parse_greetings(const char *line)
{
    if(line == NULL)
        return 0;

    char name[20];
    int val;

    if(sscanf(line, "%19s %d", name, val) != 2)
        return 0;


    // do whatever you need with 'name' and 'val'

    return 1;
}

使用strtok

int parse_greetings(char *line)
{
    if(line == NULL)
        return 0;

    char name[20];
    int val;

    const char *delim = " \t\r\n";

    char *token = strtok(line, NULL);

    // line has only delimiters
    if(token == NULL)
        return 0;

    strncpy(name, token, sizeof name / sizeof name[0]);
    name[(sizeof name / sizeof name[0]) - 1] = 0;

    token = strtok(NULL, delim);

    if(token == NULL)
        return 0;

    char *end;

    val = strtol(token, &end, 0);

    // check if token is a number
    if(*end != '\0')
        return 0;

    // do whatever you need with 'name' and 'val'

    return 1;
}