4

我正在尝试解析包含固定列数中的整数的文本。例如,我的输入文件可能如下所示:

=1=2=3
=4=5=6
=8=910

其中=符号表示输入中的空格。等号不在输入文件中;我只是为了说明的目的把它放在那里。每个整数包含在没有零填充的两列中,因此第三行不是拼写错误:它是 8、9 和 10。

该标准sscanf不起作用,因为它首先消除空格,然后应用格式字符串。例如,我试过:

sscanf(buf, "%2d%2d%2d", &int1, &int2, &int3)

但它最终将第三行解析为 8、91 和 0。

有没有办法做到这一点,而无需手动逐列提取数据?

4

4 回答 4

1

您可以通过许多不同的方式来做到这一点。使用sscanf(或strtol),您(至少)有以下两个选项:

  • 复制该列,然后复制sscanf它:

    char temp[COL_SIZE+1] = {'\0'};  /* last character will always be NUL */
    for (i = 0; i < col_count; ++i)
    {
        memcpy(temp, buf + i * COL_SIZE, COL_SIZE * sizeof(*buf)); /* "* sizeof" actually unnecessary */
        sscanf(temp, "%d", &num[i]); /* or use strtol */
    }
    
  • 您也可以更高效地执行此操作,因为您不会在常量字符串上执行此操作,特别是永远不会在字符串文字上执行此操作:

    for (i = 0; i < col_count; ++i)
    {
        char temp;
        int column_beg = i * COL_SIZE;
        int column_end = column_beg + COL_SIZE;
        temp = buf[column_end];
        buf[column_end] = '\0';
        sscanf(buf + column_beg, "%d", &num[i]); /* or use strtol */
        buf[column_end] = temp;
    }
    

    它的作用是'\0'在每列之后插入一个,读取它,然后恢复原始字符。如果在字符串文字上完成,这将是未定义的行为。

我个人推荐第一种方法。

于 2012-05-15T13:11:18.027 回答
1

您可以逐个字符地执行此操作:

#include <ctype.h>
#include <stdio.h>

int main(void) {
  int val;
  char input[] = "=8=910";
  char *p = input;

  while (*p) {
    val = 0;
    if (isdigit((unsigned char)*p)) val = *p - '0'; // 1st digit
    p++;
    val *= 10;                                      // 2nd
    val += *p++ - '0';                              // digit
    printf("val: %d\n", val);
  }
  return 0;
}
于 2012-05-15T13:16:38.327 回答
0

不使用scanf. 应该快...

void parse_columns(const char *line)
    {
    char buf[3];
    buf[2] = '\0';

    int i = 0;
    for (const char *c = &line[0]; *c; c++, i++)
        {
        buf[i] = *c;
        if (1 == i)
            {
            printf("%d\n", atoi(buf));
            i = -1;
            }
        }
    }
于 2012-05-15T13:28:49.927 回答
0

您可以使用scanf()"%2c"转换说明符将两个字符读入一个以零结尾的正确数组,然后将其转换为十进制(使用strtol()或类似的东西)......但这很丑陋。再说一次,并不比格式本身丑。

一般来说,*scanf()解析输入是一个非常糟糕的选择,因为如果输入格式错误,它的行为会有些敏感。从长远来看,您最好将文件读入内部缓冲区并进行自己的自定义解析/错误处理。

于 2012-05-15T13:19:15.050 回答