由于文件 txt 分隔符逗号 C,fscanf 出现问题

Problem with fscanf because of file txt divider comma C

我要用这个文件信息
香烟,吸烟用,1,5.500000
伍兹,对于室内烟囱,2,100.000000

要填充此结构:

typedef struct product{
    char name[32];
    char about_product[32];
    int product_id;
    double price;
}sProduct;

使用这个函数:

void print_prod(){
    sProduct ptr;
    FILE *fp=fopen("product.txt", "r");
    int cnt=1;
    do{
        fscanf(fp, "%s,%s,%d,%g\n", ptr.name, ptr.about_product, &ptr.product_id, &ptr.price);
        cnt++;
    }while(!feof(fp));  
    fclose(fp);
}

但它不会出错,因为我在 txt 文件中使用逗号作为分隔符。

这里有两个问题,都围绕着 scanf 如何处理 %s 指令:

  • 它会扫描以空格分隔的 字符串,因此它会将某些输入数据中的内部空格作为分隔符
  • 它扫描 以空格分隔的 字符串,因此它不会将逗号识别为字段分隔符

您可以通过多种方式完成您设置的输入任务,但要继续使用 scanf 将您的特定输入直接扫描到您的数据结构中,您需要 %[ 指令而不是 %s.

%[ 指令接受 "scanset" 描述字段中可能出现的字符,其中可以包含空格。这采用类似于正则表达式或 glob 字符 class 的形式。相应的参数应该是指向 char 的指针,就像 %s 指令一样。您还应该知道,与大多数指令(包括 [=14=)不同,%[ 指令不会跳过前导空格。对你来说,它的用法可能是这样的:

        fscanf(fp, "%[^,],%[^,],%d,%g\n", ptr.name, ptr.about_product, &ptr.product_id, &ptr.price);

那里的两个 %[^,] 字段描述符各自扫描除逗号 (,) 之外的任意数量的字符。

此外,您最好指定字段宽度,以避免在数据中出现太长的字段时超出数组的范围。由于您提供了 32 字节的数组,并且每个数组中的一个字节必须保留用于字符串终止符,因此可能是这样的:

        fscanf(fp, "%31[^,],%31[^,],%d,%g\n", ptr.name, ptr.about_product, &ptr.product_id, &ptr.price);

而且,对于几乎所有具有任何失败模式的函数,您还应该以编程方式检查函数是否成功。您需要主动且始终如一地执行此操作,否则您的程序可能会以微妙且令人惊讶的方式失败。对于 scanf 和许多类似的用法,这意味着检查 return 值是否等于格式中输入指令的数量(return 值表示有多少字段成功扫描并分配):

        int fields;
        fields = fscanf(fp, "%31[^,],%31[^,],%d,%g\n", ptr.name, ptr.about_product,
                &ptr.product_id, &ptr.price);
        if (fields != 4) {
            // handle input error ...
        }

附录:

继续您应该检查具有故障模式的函数中的故障这一点,我还观察到另一个这样的函数是 fopen()。这个函数完全有可能失败,在这种情况下它 return 是一个空指针。一个健壮的程序肯定会检查这种情况并优雅地处理它,使用类似于我为 scanf() 描述的模式。但是,这与您询问的具体不当行为无关。 (归功于@RobertSsupportsMonicaCellio。)