由于文件txt分隔符逗号C,fscanf出现问题
我必须使用此文件信息由于文件txt分隔符逗号C,fscanf出现问题,c,file,struct,fill,C,File,Struct,Fill,我必须使用此文件信息 吸烟用雪茄,1,5.500000支 伍兹,用于印多尔烟囱,210000000 要填充此结构,请执行以下操作: typedef struct product{ char name[32]; char about_product[32]; int product_id; double price; }sProduct; 使用此功能: void print_prod(){ sProduct ptr; FILE *fp=fopen(
吸烟用雪茄,1,5.500000支
伍兹,用于印多尔烟囱,210000000 要填充此结构,请执行以下操作:
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);
}
但它没有bug,因为我在txt文件中使用逗号作为分隔符。这里有两个问题,都是围绕
scanf
如何处理%s
指令:
- 它扫描以空格分隔的字符串,因此它将某些输入数据中的内部空格作为分隔符
- 它扫描以空格分隔的字符串,因此不会将逗号识别为字段分隔符
scanf
将特定输入直接扫描到数据结构中,需要使用%[/code>指令而不是%s
%[
指令接受“扫描集”准确描述字段中可能出现的字符,这些字符可以包含空格。这种形式类似于正则表达式或全局字符类。相应的参数应该是指向%char
的指针,就像%s
指令一样。您还应该注意,与大多数指令不同,包括%s
e%[
指令不会跳过前导空格。对您来说,它的用法可能如下所示:
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
,以及许多类似的方法,这意味着检查返回值等于格式中的输入指令数(返回值指示成功扫描和分配的字段数):
附录:
继续说明您应该检查具有故障模式的函数中的故障,我还观察到另一个此类函数是
fopen()
。此函数完全有可能失败,在这种情况下,它会返回空指针。一个健壮的程序肯定会检查这种情况,并使用类似于我为scanf()
描述的模式优雅地处理它。但是,这与您询问的特定错误行为无关。(归功于@RobertSsupportsMonicaCellio。)这里有两个问题,都围绕着scanf
如何处理%s
指令:
- 它扫描以空格分隔的字符串,因此它将某些输入数据中的内部空格作为分隔符
- 它扫描以空格分隔的字符串,因此不会将逗号识别为字段分隔符
scanf
将特定输入直接扫描到数据结构中,需要使用%[/code>指令而不是%s
%[
指令接受“扫描集”准确描述字段中可能出现的字符,这些字符可以包含空格。这种形式类似于正则表达式或全局字符类。相应的参数应该是指向%char
的指针,就像%s
指令一样。您还应该注意,与大多数指令不同,包括%s
e%[
指令不会跳过前导空格。对您来说,它的用法可能如下所示:
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
,以及许多类似的方法,这意味着检查返回值等于格式中的输入指令数(返回值指示成功扫描和分配的字段数):
附录:
继续说明您应该检查具有故障模式的函数中的故障,我还观察到另一个此类函数是
fopen()
。此函数完全有可能失败,在这种情况下,它会返回空指针。一个健壮的程序肯定会检查这种情况,并使用类似于我为scanf()
描述的模式优雅地处理它。但是,这与您询问的特定错误行为无关。(归功于@RobertSsupportsMonicaCellio。)%s
不适用于空格。我建议改为使用fgets()
然后使用strtok()
在逗号处拆分字符串。如果流打开成功与否,您不需要证明fp
是否为NULL
。这一点非常重要。如果流打开失败,而您不及时处理,您将在以后遇到一大堆麻烦。请重新阅读。特别是,interpre