9

問題: 2 つの空白が連続して発生することを識別できるようにする必要があります。

次の質問を読みました。

\n で区切られたファイルから文字列を読み取る方法

スペースを含む scanf の読み方

そして、私はscanfの問題を認識しています: http://c-faq.com/stdio/scanfprobs.html

入力は次の形式になります。

1 5 3 2  4 6 2  1 9  0

2 つの空白は、次のデータ セットを処理してそれ自体と比較する必要があることを示します。線の長さは不明であり、各グループの数または整数は不明です。次のデータ セットを区切るには、2 つの空白が最も多くなります。

fgets とさまざまな組み込み関数を使用してこの問題を解決できますが、この時点で scanf を使用して問題を解決する方が簡単になる可能性があります。ただし、そうでない場合は、fgets、strtok、atoi を使用するとほとんどの作業を実行できますが、それでも 2 つの空白が連続して識別される必要があります。

以下は、非整数が入力されるまで整数を取ります。

while ( scanf ( "%d", &x ) == 1 )

私が必要とするのは、空白も読み取ることです.2つの連続した空白がある場合は、次のデータセットで何か違うことをするようにプログラムします.

そして、空白を取得すると、次のように言う方法がわかりません。

if ((input == "空白") && (previousInput == "空白"))
  やだやだ
else (input == "空白")
  やだやだ
そうしないと
  やだやだ

お時間をいただき、ありがとうございます。

得られた教訓: scanf の解決策が Jonathan Leffler によって以下に投稿されていますが、getc を使用した場合の解決策はもう少し簡単でした (内部の scanf、正規表現、および char に関する詳細な知識は必要ありません)。振り返ってみると、正規表現、scanf、および char についての知識が深まり、問題が解決しやすくなり、もちろん、どの関数が利用可能で、どの関数を最初から使用するのが最適であったかがわかります。

4

5 に答える 5

5

getcそしてungetcあなたの友達です

#include <stdio.h>

int main(void) {
  int ch, spaces, x;
  while (1) {
    spaces = 0;
    while (((ch = getc(stdin)) != EOF) && (ch == ' ')) spaces++;
    if (ch == EOF) break;
    ungetc(ch, stdin);
    if (scanf("%d", &x) != 1) break;
    printf("%d was preceded by %d spaces\n", x, spaces);
  }
  return 0;
}

http://ideone.com/xipm1のデモ

編集Rahhhhhhhhh ... C++ としてアップロードしました。これはまったく同じものですが、今はC99 strict( http://ideone.com/mGeVk )

于 2010-09-21T22:51:45.443 に答える
1
while ( scanf ( "%c", &x ) == 1 )

%c空白文字を読み取ることができるを使用すると、すべてのデータを読み取って配列に格納するだけで済みます。次に、割り当てて配列の先頭にchar* cptr設定cptrし、配列を分析します。10 進数を読み取りたい場合は、10 進数を読み取りたいときに単にsscanfoncptrを使用できますが、配列の適切な位置にポインターが必要です (必要な数に読んだ)

if (((*(cptr + 1)) == ' ') && ((*cptr)== ' '))
  ya da ya da
else ((*cptr)== ' '))
  ya da ya da
  sscanf(++cptr, "%d", &x);
else 
  ya da ya da
于 2010-09-21T22:42:23.033 に答える
0

これは、scanf() 関数のみを使用するソリューションです。このサンプルでは、​​ほぼ同じ機能のために sscanf() を使用しました。

#include <stdio.h>


int p_1_cnt = 0, p_2_cnt = 0;

void process_1(int x)
{
    p_1_cnt++;
}


void process_2(int x)
{
    p_2_cnt++;
}


char * input_line = "1 5 3 2  4 6 2  1 9  0";

int main(void)
{
    char * ip = input_line;

    int x = 0, ws_0 = 0, ws_1 = 0, preceding_spaces = 1, fields = -2;

    while (sscanf (ip, "%d%n %n", &x, &ws_0, &ws_1) > 0)
    {
        ip += ws_0;

        if ((preceding_spaces) == 1)
            process_1(x);
        else
            process_2(x);

        preceding_spaces = ws_1 - ws_0;
    }

    printf("\np_1_cnt = %d, p_2_cnt = %d", p_1_cnt, p_2_cnt);
    _fgetchar();

    return 0;
}
于 2015-02-03T17:44:59.797 に答える
0

scanf型機能が本当に必要な場合は、 and を使用fgetssscanf%n指定子を使用して scanf を取得し、プログラムが残りの作業を行うと同時に、各空白スパンの開始と終了のオフセットをプログラムに与えることができます。

scanfそうでなければ、家族全員を捨ててください。私の意見では、これはおそらく標準ライブラリの最も役に立たない部分です。

于 2010-09-21T23:04:19.093 に答える
0

「空白」の定義は何ですか?

scanf()率直に言って、二重の空白を識別するために使用したいとは思いません。他のほぼすべての方法ははるかに簡単です。

ただし、どうしても賢明ではないことを主張する場合は、次のコードから派生したコードを使用することをお勧めします。

#include <stdio.h>
#include <string.h>

int main(void)
{
    int d;
    char sp[3] = "";
    int n;

    while ((n = scanf("%d%2[ \t]", &d, sp)) > 0)
    {
        printf("n = %d; d = %d; sp = <<%s>>", n, d, sp);
        if (n == 2 && strlen(sp) == 2)
            printf(" end of group");
        putchar('\n');
    }
    return 0;
}

角括弧は文字クラスを囲み、その前の 2 は、クラスから最大 2 文字を主張します。改行を読み取って、文字クラスを満たすためにさらにデータを取得しようとすることについて心配する必要がある場合があります。これは、文字クラスから改行を削除することで解決できます。ただし、それは空白の定義と、グループが改行で自動的に終了するかどうかにかかっています。sp[0] = '\0';ループの最後でリセットしても問題ありません。

おそらく、数字の前にある 2 つのスペースを検出するために、フィールドを逆にしたほうがよいかもしれません。しかし、それは通常のケースでは失敗するので、単純な形式に戻って"%d"数値を読み取ることになります (それが失敗した場合は、スペースも数値も取得していないことがわかります - エラー)。%d先頭の空白 (標準で定義されている)を噛み砕くことに注意してください- それらすべて。

これを見れば見るほど好きじゃなくなってしまう「scanf()だけ」。あなたの大学では授業を受けないように注意してください。

于 2010-09-21T22:53:25.170 に答える