gpt4 book ai didi

c - 使用 fscanf 从输入文件中逐行读取

转载 作者:行者123 更新时间:2023-11-30 14:39:56 25 4
gpt4 key购买 nike

我正在从一个文件中读入,该文件包含 15 个由“|”分隔的特征象征。我正在使用: while(fscanf(file, "%*d|%s|%*s|%s|%*d|%*s|%*d|%*s|%*s|%* f|%*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"

您似乎想要将第二个和第四个字段保存为 namestate 中的字符串值。

我立即怀疑您使用 &name, &state 是不正确的,因为假设您已将 namestate 声明为足够大小的字符数组为了保存第二个和第四个字段中的数据, namestate 已经是指针(参见: C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) ),因此不需要 ' &' 位于变量名称之前。如果它们没有声明为字符数组(或指向数组的指针并分配足够的内存),则您的解析将由于类型不兼容而失败。

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

  1. 如果 15 个字段中的任何一个出现匹配输入失败,您的读取将会失败;和
  2. 您只关心第二个和第四个字段 - 当您只关心其中两个字段时,无需使您的读取依赖于对 15 个字段的成功解析。

因此,您不必担心 15 个字段的正确匹配,而只需担心 4 个字段 - 您不必关心第 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;
}

(注意:使用field-width修饰符来保护namestate的数组边界> 与 %31[^|]。使用 strcspn 只是从 末尾删除 '\n' buf 因此 namestate 值将在输出 buf 之后打印在同一行。如果您不打印 buf ,那么您根本不需要该调用来进行解析)

示例使用/输出

生成的最小数据与您的格式字符串匹配。解析第二个和第四个值将在 namestate 中产生所需的字符串,例如

$ ./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

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

关于c - 使用 fscanf 从输入文件中逐行读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55822355/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com