使用C将其从文本文件扫描到2个数组中

问题描述 投票:1回答:2

在将这样的内容解析到数组时遇到麻烦。

所以我的文本文件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部分的帮助谢谢

c parsing scanf
2个回答
2
投票

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();

0
投票

正如他在回答中提供的@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数组,但是下面的简化示例对charsnums使用了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修饰符输出最终数字的输出,以确保列与您的数据保持对齐)

查看所有答案中的内容,如果还有其他问题,请告诉我们。

© www.soinside.com 2019 - 2024. All rights reserved.