一般に、C言語でgets
を使うことは危険だと言われています。
危険なコードは書きたくないが、万が一課題などでどうしてもgets
を使わなければならないとしたら、どうすればいいでしょうか?
使えばいいのです。あくまで標準ライブラリのgets
関数が危険なのであって、gets
というトークン自体には何の危険性もありません。
以下にgets
を使ったサンプルコードを示します。
use_gets.c
#include <stdio.h>
/* 行を読み込んだら真、読み込めなかったら偽を返す */
int read_line(char *b, size_t s) {
size_t gets = 0;
if (s == 0) return 0; /* バッファが0バイトしかなかったら、読み込めない */
for (;;) {
int c = getchar();
if (c == EOF) {
b[gets] = '\0';
return gets > 0; /* 1文字以上入力していたら有効な入力、0文字なら入力なしと判定する */
} else if (c == '\n') {
b[gets] = '\0';
return 1;
} else {
b[gets++] = (char)c;
if (gets + 1 >= s) {
/* バッファがいっぱいになるので、その場で読み込みを打ち切る */
b[gets] = '\0';
return 1;
}
}
}
}
int main(void) {
char line[20];
int count = 1;
while (read_line(line, sizeof(line))) {
printf("%d: %s\n", count++, line);
}
return 0;
}
入力例
0123456789012345678901234567890
abcdefg
hijklmnopqrstuvw
xyz
この入力例に対する出力
1: 0123456789012345678
2: 901234567890
3: abcdefg
4: hijklmnopqrstuvw
5: xyz
出力の内容はともかく、きちんとバッファオーバーランが回避できています。