在将这样的内容解析到数组时遇到麻烦。
所以我的文本文件test.txt具有以下行:(1231212A,1231212B)(1231212C,321128D)
im试图将其扫描到一个数组中,但需要分成几部分
int类型的part1应该是:123
第2部分:12
第3部分:12
第4部分(字符):A
而且我需要在一行中执行4次
这里是我的代码,但无法正常工作
{
int nums[1][12];
char chars[1][4];
FILE *file;
file = fopen("test.txt", "r");
if (file != NULL){
fscanf(file , "%*s%3d %2d %2d %s %*s %2d %2d %2d %s%*s %*s%3d %2d %2d %s%*s %2d %2d %2d %s%*s"
, &nums[0][0],&nums[0][1],&nums[0][2],&chars[0][0],&nums[0][3],&nums[0][4],&nums[0][5],&chars[0]
[1],&nums[0][6],&nums[0][7],&nums[0][8],&chars[0][2],&nums[0][9],&chars[0][10],&nums[0][11],&chars[0]
[3]);
}
当我打印这些数组时,它们没有打印正确的数字和字符。我需要fscanf部分的帮助谢谢
用fgets()
从文件中读取行后,用sscanf()
包括"%n"
解析string以检测扫描了多少。
使用字符串文字格式的串联也有帮助。
// v---not s
#define GROUP_FMT "%3d%2d%2d%c"
int n = 0;
sscanf(line, " (" GROUP_FMT " ," GROUP_FMT " ) (" GROUP_FMT " ," GROUP_FMT " ) %n",
&nums[0][0], &nums[0][ 1], &nums[0][ 2], &chars[0][0],
&nums[0][3], &nums[0][ 4], &nums[0][ 5], &chars[0][1],
&nums[0][6], &nums[0][ 7], &nums[0][ 8], &chars[0][2],
&nums[0][9], &nums[0][10], &nums[0][11], &chars[0][3], &n);
// Did scanning reach the %n and was that the end of the string?
if (n && line[n] == '\0') Success();
else Fail();
正如他在回答中提供的@chux一样,密钥是将格式字符串与要解析的数据正确匹配,然后根据预期的转换次数严格验证返回值。 格式字符串中的主要错误是不必要地包含了%s %*s
(尝试跳过逗号)和%s%*s %*s
(尝试跳过") "
在多个位置具有读取和丢弃效果) ","
或")"
,跳过所有空格,然后读取并丢弃其后的数字,例如"1231212B)"
或" (1231212C"
,依此类推。
更紧密的匹配如@chux的答案所示,或简单地为:
"(%3d%2d%2d%c, %3d%2d%2d%c) (%3d%2d%2d%c, %3d%2d%2d%c)"
((仅在不提供额外的空白并且不读取消耗的字符数方面有所不同)
[虽然您使用的是1行的2D数组,但是下面的简化示例对chars
和nums
使用了1D数组,可以通过如下方式编写以通过fgets()
将缓冲区传递到sscanf()
来读取验证返回值,或者输出收集的值,或者如果解析失败,则显示错误:
#include <stdio.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
char buf[MAXC], chars[4];
int nums[12];
/* 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 line into buf with fgets() */
/* parse with sscanf -- validate 16 conversion take place */
if (sscanf (buf, "(%3d%2d%2d%c, %3d%2d%2d%c) (%3d%2d%2d%c, %3d%2d%2d%c)",
&nums[0], &nums[1], &nums[2], &chars[0],
&nums[3], &nums[4], &nums[5], &chars[1],
&nums[6], &nums[7], &nums[8], &chars[2],
&nums[9], &nums[10], &nums[11], &chars[3]) == 16) {
/* output result */
printf ("%d %d %2d %c\n%d %d %2d %c\n%d %d %2d %c\n%d %d %2d %c\n",
nums[0], nums[1], nums[2], chars[0],
nums[3], nums[4], nums[5], chars[1],
nums[6], nums[7], nums[8], chars[2],
nums[9], nums[10], nums[11], chars[3]);
} /* or handle error */
else
fprintf (stderr, "error parsing data from: %s\n", buf);
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
}
示例输入文件
$ cat dat/splitintoarr.txt
(1231212A, 1231212B) (1231212C, 321128D)
示例使用/输出
$ ./bin/splitintoarr <dat/splitintoarr.txt
123 12 12 A
123 12 12 B
123 12 12 C
321 12 8 D
(使用field-width修饰符输出最终数字的输出,以确保列与您的数据保持对齐)
查看所有答案中的内容,如果还有其他问题,请告诉我们。