日記

日本語の勉強のためのブログ

【C言語】scanf時の改行の処理に苦労した

AtCoder Beginner Contest 191のC - Digital GraffitiをC言語で解いたときのはなし。
例として以下の入力が与えられていた。

5 5
.....
.###.
.###.
.###.
.....

これを以下のコードで読み込もうとすると、最終行(.....の部分)を読み込むことができなかった。

int h, w, i, j;
char s[10][10];
scanf("%d %d", &h, &w);
for (i = 0; i < h; i++) {
  for (j = 0; j < w; j++) {
    scanf("%c", &s[i][j]);
    printf("%c", s[i][j]);
  }
}
//読み込み結果

.....
.###.
.###.
.###.

これはscanfでchar型変数を読み込む際、改行も1文字として読み込んでしまうことが原因である(上の読み込み結果を反転表示してもらえば、改行が読み込まれていることがわかるだろう)。

さらに次にscanfを使う場合に備えて,残った改行は%*cで読み飛ばします。これで保持されていた入力データはすべて処理されたことになります。但し,次に読み取るものが%dなど数値である場合には,これをしなくても特に影響はありません。
標準入力から安全に文字列を受け取る方法いろいろ - Qiitaより引用)

この解説に従い、以下のようにコードを書き換えると、改行を無視して読み込むことができた。

int h, w, i, j;
char s[10][10];
scanf("%d %d%*c", &h, &w);
for (i = 0; i < h; i++) {
  for (j = 0; j < w; j++) {
    scanf("%c", &s[i][j]);
    printf("%c", s[i][j]);
  }
  scanf("%*c");
}
/* 読み込み結果 */
......###..###..###......