<<戻る

scanfを使ってはいけない理由

 

scanfは一般的に使うべきではないというが、なぜか検証してみる。

テスト環境

Red Hat Linux release 8.0 gcc v3.2

scanfはscan formatted関数の略称。
scanfでの空白文字とは、ブランク、タブ、改行、復帰、垂直タブ、改ページである。

検証1

scanfの"%d"は改行の前の数字だけ取得する。入力ストリームには改行コードが残る。getsはその改行コードを入力としてしまう。

int main(int argc, char *argv[]) {
   int input;
   char string[5];
 scanf("%d", &input);
   gets(string);
   printf("%s", string);
   return 0;
   }

検証2

scanfは数字以外に出くわすと処理を終了し、かつそれら不必要なデータを
入力ストリームに放置する。以下がサンプルソースコード。

int main(int argc, char *argv[]) {
   int input1;
   int input2;
   char string [2];
 /* ここで数字以外を入力してみる。*/
 scanf("%d", &input1); /* 数字ではないので処理を終了 */
   scanf("%d", &input2); /* 数字ではないので処理を終了 */
   scanf("%s", string); /* 文字なので個々でscanする */
   printf("%s", string);
   }

検証3


下記の"%s"の場合は、入力ストリームにゴミを残していない。

int main(int argc, char * argv[]) {
   char string1 [5];
   char string2 [5];
   scanf("%s", string1);
   gets(string2);
   printf("string1=%d", strlen(string1));
   printf("string2=%d", strlen(string2));
   return 0;
   }

$ ./a.out
aa
string1=2string2=0


つまり%dと%sでは、挙動が異なる。

scanf("%s", string1)で、分かるようにscanfはバッファ量を決めることができない。
つまりどんな大きなデータも詰め込める。つまりオーババッファフローが可能である。


対応策

scanfではなくfgetsで標準入力からデータを取得し、sscanf(string scan function)で
取得したデータを利用する。