[英]Problem with fscanf because of file txt divider comma C
I have to use this file information我必须使用这个文件信息
Cigaretas,For Smoking,1,5.500000香烟,吸烟用,1,5.500000
Woods,For indor chimneys,2,100.000000伍兹,用于室内烟囱,2,100.000000
To fill this structure:要填充此结构:
typedef struct product{
char name[32];
char about_product[32];
int product_id;
double price;
}sProduct;
Using this function:使用这个 function:
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);
}
But it doesn't bugs because I use comma for a divider in the txt file.但它没有错误,因为我在 txt 文件中使用逗号作为分隔符。
There are two issues here, both revolving around how scanf
processes %s
directives:这里有两个问题,都围绕
scanf
如何处理%s
指令:
There are several ways you could go about the input task you have set, but to continue to use scanf
to scan your particular input directly into your data structure, you want the %[
directive instead of %s
.有几种方法可以 go 关于您设置的输入任务,但要继续使用
scanf
将您的特定输入直接扫描到数据结构中,您需要%[
指令而不是%s
。
The %[
directive accepts a "scanset" describing exactly which characters may appear in the field, which can include whitespace. %[
指令接受一个“扫描集”,准确描述字段中可能出现的字符,其中可以包括空格。 This takes a form similar to a regex or glob character class.这采用类似于正则表达式或全局字符 class 的形式。 The corresponding argument should be a pointer to
char
, just as for a %s
directive.对应的参数应该是指向
char
的指针,就像%s
指令一样。 You should also be aware that unlike most directives, including %s
, the %[
directive does not skip leading whitespace.您还应该知道,与大多数指令(包括
%s
)不同, %[
指令不会跳过前导空格。 For you, its use might look like this:对您来说,它的使用可能如下所示:
fscanf(fp, "%[^,],%[^,],%d,%g\n", ptr.name, ptr.about_product, &ptr.product_id, &ptr.price);
The two %[^,]
field descriptors there each scan any number of characters other than a comma ( ,
).那里的两个
%[^,]
字段描述符分别扫描除逗号 ( ,
) 以外的任意数量的字符。
Additionally, you would be wise to specify field widths, so as to avoid overrunning your arrays' bounds in the event that too-long fields appear in your data.此外,明智的做法是指定字段宽度,以避免在数据中出现过长字段时超出数组的边界。 Since you provide 32-byte arrays, and one byte of each must be reserved for a string terminator, that could be this:
由于您提供了 32 字节的 arrays,并且每个字节必须为字符串终止符保留一个字节,因此可能是这样的:
fscanf(fp, "%31[^,],%31[^,],%d,%g\n", ptr.name, ptr.about_product, &ptr.product_id, &ptr.price);
But also, as with substantially all functions that have any failure modes, you should also check , programmatically, whether the function succeeded.而且,与几乎所有具有任何故障模式的功能一样,您还应该以编程方式检查function 是否成功。 You need to do this proactively and consistently, else your programs may fail in subtle and surprising ways.
您需要主动且始终如一地执行此操作,否则您的程序可能会以微妙而令人惊讶的方式失败。 For this use of
scanf
, and many similar ones, that means checking that the return value is equal to the number of input directives in the format (the return value indicates how many fields were successfully scanned and assigned):对于
scanf
和许多类似的使用,这意味着检查返回值是否等于格式中输入指令的数量(返回值表示成功扫描和分配了多少字段):
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 ...
}
Addendum:附录:
Continuing with the point that you should check for failures in functions that have failure modes, I also observe that another such function is fopen()
.继续您应该检查具有故障模式的函数中的故障,我还观察到另一个这样的 function 是
fopen()
。 It is entirely possible for this function to fail, in which case it returns a null pointer.这个 function 完全有可能失败,在这种情况下,它会返回一个 null 指针。 A robust program would definitely check for this case and handle it gracefully, using a pattern similar to the one I described for
scanf()
.一个健壮的程序肯定会检查这种情况并优雅地处理它,使用类似于我为
scanf()
描述的模式。 This, however, is not related to the specific misbehavior you asked about.但是,这与您询问的具体不当行为无关。 (Credit to @RobertSsupportsMonicaCellio.)
(归功于@RobertSsupportsMonicaCellio。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.