fprintf中的字符串是错误的数据类型(%s)

时间:2016-07-02 12:35:30

标签: c arrays string char printf

我确定这个问题经常出现,但我发现搜索时没有像这样的问题。 我的问题是,当我使用函数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);

1 个答案:

答案 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