scanfで苦戦した

まえおき

C言語の話。
コンパイラgcc
scanfを複数回実行すると入力バッファに改行文字が残って意図しない動作をすることがある。
その回避策として以下の2つがあった。

  • 代入抑止文字を使う方法
scanf("%c%*c",&c);
  • 空白文字を使う方法
scanf(" %c",&c);

ほんだい

目的

上記の方法を使って以下のようなことを実現する。

  • 入力されたもののうち先頭にある文字だけを読み取る。
  • どんな入力に対しても対処できるようにする。

実装

  • 代入抑止文字を使う方法
scanf("%c%*[^\n]%*c", &ch);

先頭の文字を読み取り、入力バッファに残ってるものを読み捨てる。

#include <stdio.h>

int main(void) {
  char ch;
  while (1) {
    scanf("%c%*[^\n]%*c", &ch);
    printf("ch:%c;%d\n", ch, ch);
    printf("--------------------\n");
  }
  return 0;
}

実行結果

q
ch:q;113
strchr(str, ch):;4196100
--------------------
w
ch:
;10
strchr(str, ch):;0
--------------------
e
ch:e;101
strchr(str, ch):;4196102
--------------------
rty
ch:
;10
strchr(str, ch):;0
--------------------

うまくいかない。

  • 空白文字を使う方法
scanf(" %c%*[^\n]", &ch);

先頭の空白文字と改行を読み捨ててから、先頭の文字を読み取り、入力バッファに残っている改行文字までを読み捨てる。

#include <stdio.h>

int main(void) {
  char ch;
  while (1) {
    scanf(" %c%*[^\n]", &ch);
    printf("ch:%c;%d\n", ch, ch);
    printf("--------------------\n");
  }
  return 0;
}

実行結果

q
ch:q;113
strchr(str, ch):;4196100
--------------------
w
ch:w;119
strchr(str, ch):;4196101
--------------------
e
ch:e;101
strchr(str, ch):;4196102
--------------------
rty
ch:r;114
strchr(str, ch):;4196103
--------------------

よさそう。

まとめ

scanfはなるべく使いたくない