Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用fscanf逐行读取输入文件_C_Scanf - Fatal编程技术网

使用fscanf逐行读取输入文件

使用fscanf逐行读取输入文件,c,scanf,C,Scanf,我正在从一个文件中读取,该文件有15个由“|”符号分隔的特征。我正在使用:while(fscanf(文件,%*d |%s |%*s |%s |%*d |%*d |%*s |%*s |%*f |%*s |%*s |%*f |%*f”、&name、&state)==2)但当我在它上运行gdb时,我意识到它实际上从未进入循环。我使用了%*d/s,因为它告诉fscanf跳过这些值,对吗?我只想从输入中读入整行的2个值,靠近开始的两个%s。 有没有关于如何修复的建议?很抱歉没有达到最佳格式。如果您仍然被卡

我正在从一个文件中读取,该文件有15个由“|”符号分隔的特征。我正在使用:
while(fscanf(文件,%*d |%s |%*s |%s |%*d |%*d |%*s |%*s |%*f |%*s |%*s |%*f |%*f”、&name、&state)==2)
但当我在它上运行gdb时,我意识到它实际上从未进入循环。我使用了
%*d/s
,因为它告诉
fscanf
跳过这些值,对吗?我只想从输入中读入整行的2个值,靠近开始的两个%s。
有没有关于如何修复的建议?很抱歉没有达到最佳格式。

如果您仍然被卡住,举个简短的例子可能会有所帮助。查看您尝试的格式字符串,例如

"%*d|%s|%*s|%s|%*d|%*s|%*d|%*s|%*s|%*f|%*f|%*s|%*s|%*f|%*f"
您似乎希望在
name
state
中将第2和第4个字段保存为字符串值

我立即怀疑您使用的
&name,&state
是不正确的,因为假定您已将
name
state
声明为字符数组,其大小足以容纳第2和第4个字段中的数据,
name
state
已经是指针(请参阅:),因此,在变量名之前不需要使用
&
。如果它们没有声明为字符数组(或者作为指向数组的指针并分配了足够的内存),由于类型不兼容,您的解析将失败

接下来,为什么使用
fgets()
或POSIX
getline()
读取整行代码,然后使用
sscanf()
而不是使用
fscanf()
进行解析如此重要:

  • 如果与15个字段中的任何一个匹配或输入失败,您的读取将失败;及
  • 您只关心第2个和第4个字段——当您只关心其中两个字段时,不需要使读取依赖于15个字段的成功解析
  • 因此,您不必担心15个字段的正确匹配,只需要担心4个字段——您不需要关心第4个字段之后的行的其余部分

    将一个小示例与随机生成的数据放在一起(根据数据需要调整缓冲区大小),您可以执行以下操作,将第2个和第4个字段解析为字符串:

    #include <stdio.h>
    #include <string.h>
    
    #define FLDW   32   /* max field width */
    #define MAXC 1024   /* max chars in line */
    
    int main (int argc, char **argv) {
    
        char buf[MAXC],     /* line buffer */
            name[FLDW],     /* storage for name */
            state[FLDW];    /* storage for state */
    
        /* use filename provided as 1st argument (stdin by default) */
        FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
    
        if (!fp) {  /* validate file open for reading */
            perror ("file open failed");
            return 1;
        }
    
        while (fgets (buf, MAXC, fp)) { /* read each line of input */
            /* parse 2nd & 4th fields as strings - you don't care about rest */
            if (sscanf (buf, "%*d|%31[^|]|%*[^|]|%31[^|]", name, state) == 2) {
                buf[strcspn (buf, "\n")] = 0;   /* trim \n from buf */
                /* output line with parsed name and state to right */
                printf ("%s  =>  name: %s, state: %s\n", buf, name, state);
            }
        }
        if (fp != stdin) fclose (fp);   /* close file if not stdin */
    
        return 0;
    }
    

    仔细检查一下,如果有问题请告诉我。

    赋值禁止操作符是
    “*”
    修饰符,它告诉
    fscanf
    读取并丢弃转换说明符可能匹配的字符。不需要指针参数,并且返回的匹配计数中不包括任何匹配和丢弃的字符。我会用
    fgets
    将整行内容读入缓冲区,然后用
    sscanf
    解析缓冲区中的信息。如需进一步帮助,请提供。此时,您的问题可能会被关闭。
    %s
    不会在管道符号处停止<代码> %^ ^ ^ /代码>。我建议使用<代码> FGETSH()/代码>或POSIX <代码> GETLION()/代码>来读取该行,然后考虑用<代码> SCASNFF()/代码>解析该行,或者可能使用Ad Hoc方法.@ DaviC.RANKIN,因此我需要15个指针用于sSCANF吗?我只想知道2/15特性的字符串。你能更准确地解释一下sscanf的格式说明符是什么吗?当然,花点时间读一下。这可能需要一个小时来消化(在阅读时编写示例代码进行测试),但这一小时的花费将为您节省数百小时以后的挫折。基本上,除了
    “%c”
    “%[…]”
    之外,所有转换说明符都使用前导空格。填充数组时,始终使用最大字段宽度修饰符来保护数组边界。
    scanf
    不使用尾随的
    “\n”
    (也是空格)因此,请确保你处理得当。如果你被卡住了,请再次发表评论。
    $ ./bin/fgetssscanf dat/field15pipes.txt
    01|8a|0b|6c|82|1d|33|5e|4f|7.|0.|4g|3h|7.|5.  =>  name: 8a, state: 6c
    01|9a|5b|0c|42|1d|93|3e|9f|8.|0.|5g|4h|6.|5.  =>  name: 9a, state: 0c
    01|4a|5b|7c|22|0d|23|1e|1f|7.|2.|1g|5h|7.|7.  =>  name: 4a, state: 7c
    01|8a|2b|5c|72|1d|53|6e|2f|1.|1.|8g|0h|7.|6.  =>  name: 8a, state: 5c
    11|4a|6b|5c|92|2d|73|0e|6f|4.|2.|2g|7h|2.|4.  =>  name: 4a, state: 5c
    01|2a|6b|0c|02|1d|83|0e|2f|5.|2.|9g|4h|3.|8.  =>  name: 2a, state: 0c
    31|1a|0b|0c|72|2d|13|3e|3f|9.|0.|2g|5h|6.|9.  =>  name: 1a, state: 0c
    01|8a|3b|7c|92|1d|93|3e|9f|6.|1.|4g|4h|8.|3.  =>  name: 8a, state: 7c
    11|1a|4b|7c|42|2d|73|0e|5f|7.|0.|0g|5h|1.|7.  =>  name: 1a, state: 7c
    21|8a|6b|9c|22|2d|23|2e|1f|9.|0.|1g|6h|6.|8.  =>  name: 8a, state: 9c