读取文本文件并通过分隔符将其分解

时间:2015-05-20 23:15:05

标签: c arrays chars

我正在尝试阅读具有以下结构的文本文件:

Item 1 - 50, Item 2 - 400, Item 3 - 120, Item 4 - 15;

在循环文件时,我想将价格和商品名称存​​储在两个字符串中。 为了更清楚,我有int credit我想与价格进行比较,如果信用额度更大,我打印价格。

我设法使用此功能打印所有产品:

int credit = 1000; //For the example purpose
int displayProducts(){

    int row=0;
    char line[MAX_LINE_SIZE + 1]; // ptr to the current input line
    FILE *fp;

    fp = fopen("machinedata.txt", "r");
    if (fp == NULL)
    {
        printf("Error while opening the file.\n");
    //  exit(EXIT_FAILURE);
    }

    while (fgets(line, MAX_LINE_SIZE, fp)) {
        char *next_item;  // ptr to the next item extracted from the current line
        char* name = NULL;
        int price;

        next_item = strtok(line, " ,");

        while (next_item != NULL){
            printf("%s\n", next_item);
            next_item = strtok(NULL, " ,");
            /*WHAT CAN I DO HERE TO EXTRACT EACH PRICE AND COMPARE WITH CREDIT??*/
        }
    }

    fclose(fp);
    return 1;
}

我正在迈出C语言的第一步,我无法弄清楚如何做到这一点。 有什么帮助吗?

1 个答案:

答案 0 :(得分:0)

在您正在阅读一行时,您需要将其拆分为项目条目。由于您使用strtok(),我认为您不需要识别分隔符。此外,不喜欢strtok()并且更喜欢微软strtok_s()在Windows和POSIX strtok_r()其他地方的原因之一就是你不能对strtok()进行嵌套调用,但是你需要它们。或者您需要使用scanf()或其他一些技术。

警告:这些代码都不在编译器附近!

char *next_ptr = NULL;
char *next_item = strtok_r(line, ",;", &next_ptr);

while (next_item != NULL){
    char *item_ptr = NULL;
    char *name = strtok_r(next_item, "-", &item_ptr);
    if (name == NULL)
    {
        fprintf(stderr, "Failed to scan name out of [%s]\n", next_item);
        break;
    }
    int price;
    next_item = strtok_r(NULL, " ,", &item_ptr);
    assert(next_item != NULL);
    if (sscanf(next_item, "%d", &price) != 1)
        fprintf(stderr, "Failed to convert [%s] to integer\n", next_item);
    else
        printf("Item: [%s] price %d\n", name, price);
    next_item = strtok_r(NULL, ",;", &next_ptr);
}

错误break是因为我很懒。理想情况下,您应该继续执行该行中的下一个项目,但这涉及将循环重写为for循环:

for (next_item = strtok_r(line, ",;", &next_ptr);
     next_item != NULL;
     next_item = strtok_r(NULL, ",;", &next_ptr))
{
    ...body of loop except for final call to strtok_r()...
}

现在您可以使用continue并执行next_item = strtok_r(NULL, ",;", &next_ptr)语句,这一点至关重要。分号后你可能需要担心空项目;将&& *next_item != '\0'添加到循环条件中。

如果由于某种原因(什么?)无法使用strtok_r()strtok_s(),那么您可以考虑使用:

char name[30];
int price;
if (sscanf(next_item, "%29[^-] - %d", name, &price) != 2)
{
    fprintf(stderr, "Failed to extract item name and price from [%s]\n", next_item);
    continue; // Or break!
}

还有其他选择 - 实际上很多都是。

请注意strtok()及其亲属all(a)销毁输入字符串,(b)不告诉你哪个字符标记了结尾,(c)将多个分隔符视为一个,所以你不能在两个分隔符之间发现空项(在此示例中不是问题)。破坏是通过在找到分隔符的位置插入空字节来将原始字符串切割成较短的子字符串。

请注意,如果项目名称包含短划线,则您需要使用此系统。您将'Vacuum-24'解释为名为'Vacuum'的项目,其价格为24。您也可以解决这个问题,但这更难(例如,strstr()认为" - "(空白,短划线,空白)作为项目名称和价格之间的分隔符。“