我确定这个问题经常出现,但我发现搜索时没有像这样的问题。 我的问题是,当我使用函数fprintf(“%s”,string [20])时,我得到了错误的数据类型。 我怎样才能获得正确的数据类型?
代码:
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *CSV;
int anz;
char name[20];
char gesch;
CSV = fopen(argv[1], "r");
while((fscanf(CSV,"%d,%s,%c\n", &anz,&name[20],&gesch)) != EOF )
fprintf(stdout,"Anzahl:%d\tName:%s\tGeschlecht:%c\n", anz, name[20], gesch);
return EXIT_SUCCESS;
}
错误:
help.c:在函数'main'中:help.c:24:8:警告:格式'%s'需要 'char *'类型的参数,但参数4的类型为'int'[-Wformat =] fprintf(stdout,“Anzahl:%d \ tName:%s \ tGeschlecht:%c \ n”,anz,name [20],gesch);
答案 0 :(得分:4)
你有两个问题,或者可能是三个问题。
关于printf
调用警告的第一个问题是因为您使用name[20]
作为"%s"
的参数。这是数组中元素21处的单个字符。除了超出范围外,单个字符将转换为int
,从而产生警告消息。它也不起作用,因为printf
函数会将这个未知字符(记住它在数组之外)视为要打印的字符串的地址,指针,因为它很可能不是任何有效的在该角色指向的地址处,您可能会得到非常奇怪的输出。事实上,它是未定义的行为。
第二个问题与您的fscanf
电话有关。 scanf
family of functions期望获得指向您提供的数组中第一个元素的指针。要获得指向第一个元素的指针,请使用&name[0]
或仅使用普通name
(数组会自然地衰减到指向其第一个元素的指针)。
表达式&name[20]
导致指向元素编号21的指针,该指针超出了数组的末尾。当fscanf
使用此指针写入时,它将写出越界,并且您将具有未定义的行为。
还可能存在第三个问题,具体取决于文件的输入。如果名称后面的逗号没有与带空格的名称分隔,则"%s"
格式将读取该名称作为名称的一部分。 "%s"
的{{1}}格式在空白区域(例如空格,制表符,换行符)上分隔,而不是在格式字符串中提供的任意分隔符上。
要解决该问题,您必须使用一种模糊的scanf
格式,告诉"%["
读取一组字符。在这种情况下,您希望告诉scanf
读取所有但逗号,这将导致格式为scanf
。 "%[^,],"
字符表示字符集被否定,并且读取除提供的集之外的所有字符集。尾随逗号实际上是在字符串后面读取(和跳过)逗号,因为^
只会读取但不包括逗号。
您还应该保护"%[^,]"
超出您提供的数组的范围,并且通过告诉scanf
数组的宽度scanf
来实现。此格式最多可将19个字符和终止零写入数组。
您还应该在读取文件时检查可能的格式错误,并通过检查"%19[^,],"
函数能够读取和解析的提供格式的数量来执行此操作。通过比较fscanf
函数的返回值和格式数来检查这一点,在您的情况下为三。
最后,您不需要fscanf
格式字符串中的尾随"\n"
。实际上,如果输入文件没有被空格和某些其他非空格字符终止,它甚至可能导致程序“挂起”。无论如何它都会正常工作,因为几乎所有格式(包括fscanf
)都会跳过前导空格,就像上一次调用"%d"
时留下的换行符一样。
要把所有这些放在一起,你的循环可能看起来像
fscanf