gpt4 book ai didi

c - 如何使用 sscanf 将一行读入 5 个变量

转载 作者:太空宇宙 更新时间:2023-11-04 06:57:43 24 4
gpt4 key购买 nike

我正在尝试编写一些代码,以便在格式化的行中读取并将其分解为变量。

这条线看起来像这样

label:    add    $t0,$t1,$t2

格式是

label:[tab]instruction[tab]$rd,$rs,$rt

它是一个标签,后跟一个冒号、一个制表符、一条指令、一个制表符,然后是一个寄存器列表,就这样。我有声明的字符串来保存标签、指令、目标寄存器、第一个寄存器和源寄存器。这些变量被命名为 lLabel、lInst、lrs、lrt 和 lrd。

我做的代码行是这样的

sscanf(line, "%[^:]:\t%[^\t]\t$%[^,],$%[^,]$,%[^\n]", lLabel, lInst, lrd, lrs, lrt);

我的想法是读取冒号之前的所有内容,并将其存储在 lLable 中。匹配冒号,匹配制表符。读取所有内容直到制表符,存储在 lInst 中。匹配制表符,匹配 $ 符号。读到逗号,Store in rd。匹配逗号和 $.读取逗号之前的所有内容,存储在 rs 中。匹配逗号和 $.然后读取所有内容直到换行符并存储在 rt 中。

由于某种原因,它像这样填充

Label: me
Instruction: add
rs: t1
rt:
rd: t0

这种格式哪里出错了?

编辑:我已将其更改为

sscanf(line, "%[^:]:\t%[^\t]\t$%[^,],$%[^,],$%[^\n]", lLabel, lInst, lrd, lrs, lrt);

不是这样填的

Label: me
Instruction: add
rs: t1t2t0
rt: t2t0
rd: t0

最佳答案

正如评论中所指出的,您的 sscanf 格式字符串中有一个拼写错误,以及有关您是否为将要放置的 nul-terminator 提供足够空间的问题在 sscanf 解析的每个字符串的末尾。

另外一个关键点是完全无法通过检查返回验证 sscanf 转换的结果sscanf 以确保 5 转换实际发生。在盲目处理标签、指令和 rX 变量中很可能是垃圾的内容之前,您必须验证转换。

另一个小问题是您如何处理 rt转换说明符(例如 %[^\n])。虽然这可能适用于$t2 后面没有额外空格或字符的每种情况,但它比需要的限制要多得多。由于默认情况下 %s 将提供到第一个 whitespace 个字符(包括 '\n')的转换,您可以防止通过简单地使用 %s 作为最终转换说明符,在换行符之前留出空间,例如

    if (sscanf (buf, "%[^:]:\t%[^\t]\t$%[^,],$%[^,],$%s",
label, inst, rd, rs, rt) == 5)
printf ("label: %s\ninst : %s\nrd : %s\nrs : %s\nrt : %s\n\n",
label, inst, rd, rs, rt);

最后,您需要提供一些方法来处理未通过 sscanf 转换过程的行。在这种情况下如何以及做什么取决于您,但您需要防止转换失败。

将其放在一个简短的示例中,您可以执行类似于以下的操作,读取并转换包含的每个 label:[tab]instruction[tab]$rd,$rs,$rt在作为程序的第一个参数提供的文件名中的单独行上(如果未提供文件名,则来自 stdin)。一个简单的 enum 用于为代码中使用的各种字符串长度声明常量。

#include <stdio.h>

/* constants for max 'rX', 'label/inst' and chars in line */
enum { MAXR = 8, MAXL = 32, MAXC = 128 };

int main (int argc, char **argv) {

char buf[MAXC] = "", /* initialize variables */
label[MAXL] = "",
inst[MAXL] = "",
rd[MAXR] = "",
rs[MAXR] = "",
rt[MAXR] = "";
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}

while (fgets (buf, MAXC, fp)) /* read each line */
/* (you should check that a complete line was read here) */
/* validate parse into label, inst, rd, rs, rt */
if (sscanf (buf, "%[^:]:\t%[^\t]\t$%[^,],$%[^,],$%s",
label, inst, rd, rs, rt) == 5)
printf ("label: %s\ninst : %s\nrd : %s\nrs : %s\nrt : %s\n\n",
label, inst, rd, rs, rt);
else /* handle error */
fprintf (stderr, "error: invalid conversion.\n\n");

if (fp != stdin) fclose (fp); /* close file if not stdin */

return 0;
}

示例输入文件

$ cat dat/instr.txt
label: add $t0,$t1,$t2
next: sub $r0,$r1,$r2
foo: bar
last: mul $s0,$s1,$s2

示例使用/输出

$ ./bin/sscanffmt <dat/instr.txt
label: label
inst : add
rd : t0
rs : t1
rt : t2

label: next
inst : sub
rd : r0
rs : r1
rt : r2

error: invalid conversion.

label: last
inst : mul
rd : s0
rs : s1
rt : s2

检查一下,如果您有任何其他问题,请告诉我。

关于c - 如何使用 sscanf 将一行读入 5 个变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42015912/

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