4

固定数の列に整数を含むテキストを解析しようとしています。たとえば、入力ファイルは次のようになります。

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

ここで、=記号は入力内のスペースを表します。入力ファイルに等号がありません。説明のためにそこに置いただけです。各整数はゼロ パディングなしで 2 つの列に含まれているため、3 行目はタイプミスではありません: 8、9、そして 10 です。

最初にスペースを削除してからフォーマット文字列を適用するため、標準sscanfは機能しません。たとえば、私は試しました:

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

しかし、最終的に 3 行目を 8、91、および 0 として解析します。

データ列を手動で列ごとに引き出すことに頼らずにこれを行う方法はありますか?

4

4 に答える 4

1

これはさまざまな方法で行うことができます。sscanf(または)を使用strtolすると、(少なくとも) 次の 2 つのオプションがあります。

  • 列のコピーを作成してから、次の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"変換指定子を使用して、2 文字を適切にゼロで終了する配列に読み込み、それを 10 進数に変換することができます (withstrtol()またはそのようなもの)...しかし、それは醜いです。繰り返しになりますが、フォーマット自体よりも醜いわけではありません。

一般的に言えば、*scanf()入力の構文解析には非常に適していません。これは、入力が不正な形式である場合にやや扱いにくい動作になるためです。長期的には、ファイルを内部バッファーに読み込み、独自のカスタム解析/エラー処理を行う方がよいでしょう。

于 2012-05-15T13:19:15.050 に答える