C言語データ入力メモ2

またもやscanf系の入力でハマったのでメモ。

問題:
ステップ1.整数の入力を1つ、scanfで受け取る
ステップ2.ステップ1で受け取った整数が0ならば終了、0以外ならば文字列をgetsで受け取ってputsで出力し、ステップ1に戻る

例えば、次のコードは正しく動作するだろうか?

#include <cstdio>
#include <algorithm>
const int MAX_BUFSIZE(128);

int main(){
    int n;
    while(true) {
        scanf("%d", &n);
        if(n == 0) break;
        else {
            char buf[MAX_BUFSIZE]; std::fill(buf, buf + MAX_BUFSIZE, 0); 
            gets(buf);
            puts(buf);
        }   
    }   
}

答えはNoである。
getsで新しい文字列を標準入力から受け取るつもりが、scanfで受け取ってない分のストリームが残っていて、こっちを先に受け取ってしまう。

次に、scanfの部分で%dの直後に空白を入れたコードを考える。

#include <cstdio>
#include <algorithm>
const int MAX_BUFSIZE(128);

int main(){
    int n;
    while(true) {
        scanf("%d ", &n); //%dの次に空白
        if(n == 0) break;
        else {
            char buf[MAX_BUFSIZE]; std::fill(buf, buf + MAX_BUFSIZE, 0); 
            gets(buf);
            puts(buf);
        }   
    }   
}

これによって、整数を入力した後の改行が区切れとみなされて、正常にgetsが受け付けられるようになる。ただ、この変更後の問題は、整数として0を入力した時で、何故か思い通りに動かない。この理由はいまだにわからないので詳しい方教えてください。。。

結局、思い通りに動くとわかったのは次のコード

#include <cstdio>
#include <algorithm>
const int MAX_BUFSIZE(128);

int main(){
    int n;
    while(true) {
        scanf("%d", &n);
        getchar(); //getcharで改行を受け取る
        if(n == 0) break;
        else {
            char buf[MAX_BUFSIZE]; std::fill(buf, buf + MAX_BUFSIZE, 0); 
            gets(buf);
            puts(buf);
        }   
    }   
}

ちなみにこの入力フォーマットは競技プログラミングでよく出くる。なので、これが出来ないとスタート地点にも立ててないということになる。ぐぬぬ。

その他、C++は標準でsplitが使えないのでstringstrem+STLコンテナで疑似splitやる必要があったり何かと大変である。

C言語入門 (ASCII SOFTWARE SCIENCE Language)

C言語入門 (ASCII SOFTWARE SCIENCE Language)