C ライブラリ関数 -gets()
C 言語において、gets()は標準入力から文字列を読み取るための古典的な関数です。使い方は簡単ですが、安全性の問題に注意する必要があります。
gets()関数は標準入力 stdin1行の文字列を読み取り、指定された文字配列に格納します。改行文字またはファイルの終わりに達するまで文字を読み取ります。
重要な警告:gets()深刻なセキュリティホールが存在し、バッファサイズを指定できないため、バッファオーバーフローを引き起こしやすいです。そのため、現代のCプログラミングでは、fgets()の方がより良い選択です。
単語の意味:getは「取得する」という意味で、sは「文字列」(string) を表し、合わせると「文字列を取得する」という意味になります。
基本構文とパラメータ
gets()はC標準ライブラリの関数であり、ヘッダーファイルのインクルードが必要です<stdio.h>。
構文形式
char *gets(char *str);
パラメータの説明
- パラメータ:
str- 型:
char *(文字配列を指すポインタ) - 説明: 読み取ったC文字列を格納するための文字配列を指すポインタ。入力された文字列を格納できる十分な大きさの配列を確保する必要があります。
- 型:
関数の説明
- 戻り値: 成功した場合は、
strのポインタを返します。エラーが発生した場合、またはファイルの終わりに達してまだ何も読み取っていない場合は、NULL。 - NULL効果
str: 読み取られた文字列(改行文字を含まない)は、\0が指す配列に格納され、末尾に自動的にヌル文字が追加されます
例
例gets()例を通して
例1:基本的な使い方 - 文字列の読み取り
例
#include <stdio.h>
int main()
{
char str[50];
printf(文字列を入力してください:);
gets(str);
printf(入力された文字列は:%s, str);
return(0);
}
int main()
{
char str[50];
printf(文字列を入力してください:);
gets(str);
printf(入力された文字列は:%s, str);
return(0);
}
予想される実行結果:
请输入一个字符串:サンプル 您输入的字符串是:サンプル
コードの解説:
#include <stdio.h>は、使用するためのgets()関数の前提条件です。char str[50];長さ50の文字配列を定義し、入力された文字列を格納するために使用します。gets(str);標準入力から1行の文字列を読み取り、strに格納します。printf("您输入的字符串是:%s", str);を使用して%sフォーマット指定子で文字列を出力します。
例2:戻り値が NULL の場合の処理
実際のプログラミングでは、gets()の戻り値をチェックして、起こり得るエラーを処理すべきです。
例
#include <stdio.h>
int main()
{
char str[100];
char *result;
printf(何か入力してください(Ctrl+D で終了できます):\n");
result = gets(str);
if (result != NULL) {
printf(読み取り成功、内容は:\n%s\n", str);
} else {
printf(読み取り失敗、またはファイルの終わりに達しました!\n");
}
return(0);
}
int main()
{
char str[100];
char *result;
printf(何か入力してください(Ctrl+D で終了できます):\n");
result = gets(str);
if (result != NULL) {
printf(読み取り成功、内容は:\n%s\n", str);
} else {
printf(読み取り失敗、またはファイルの終わりに達しました!\n");
}
return(0);
}
コードの解説:
gets()同じ文字列を指すポインタを返します。失敗した場合はNULL。- ユーザーが Ctrl+D(Linux/Mac)または Ctrl+Z(Windows)を押すと、ファイル終了条件が発生し、
gets()返されます。NULL。 - 。実際のプロジェクトでは、より安全な
fgets()を使用して置き換えることをお勧めします。gets()。
例3:gets() の安全上の問題(⚠️ 危険な操作のデモ)
次の例は、なぜgets()が安全でないのかを示しています。
例
#include <stdio.h>
int main()
{
// 注意:この例は非常に危険です。デモのみを目的としています!
char buffer[10];
printf(長い文字列(10文字以上)を入力してください:\n");
gets(buffer); // 境界チェックがないため、バッファオーバーフローが発生する可能性があります
printf(入力されたのは:%s\n", buffer);
return(0);
}
int main()
{
// 注意:この例は非常に危険です。デモのみを目的としています!
char buffer[10];
printf(長い文字列(10文字以上)を入力してください:\n");
gets(buffer); // 境界チェックがないため、バッファオーバーフローが発生する可能性があります
printf(入力されたのは:%s\n", buffer);
return(0);
}
コードの解説:
buffer[10]わずか10バイトの領域を割り当てます。- ユーザーが入力した文字列が9文字を超える場合(末尾の
\0を加えると)、バッファオーバーフローが発生します。隣接するメモリ領域を上書きする可能性があります。 - これは攻撃者に悪用されて悪意のあるコードを実行される可能性があるため、
gets()C99 標準では非推奨とされ、C11 標準では削除されました。
より良い代替案:fgets()
強くお勧めしますfgets()の代わりにgets()を使用することです。なぜならそれはバッファサイズを指定できるからです。
例
#include <stdio.h>
int main()
{
char str[50];
printf(文字列を入力してください:);
// fgets(バッファ, バッファサイズ, ファイルストリーム)
fgets(str, sizeof(str), stdin);
// fgets が読み取った改行文字を削除
// 方法:改行文字を探してヌル文字に置き換える
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == '\n') {
str[i] = '\0';
break;
}
}
printf(入力された文字列は:%s\n", str);
return(0);
}
int main()
{
char str[50];
printf(文字列を入力してください:);
// fgets(バッファ, バッファサイズ, ファイルストリーム)
fgets(str, sizeof(str), stdin);
// fgets が読み取った改行文字を削除
// 方法:改行文字を探してヌル文字に置き換える
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == '\n') {
str[i] = '\0';
break;
}
}
printf(入力された文字列は:%s\n", str);
return(0);
}
fgets()の利点:
- 最大読み取り文字数を指定でき、バッファオーバーフローを防ぎます。
- 文字列の末尾に改行文字を保持します(必要に応じて手動で削除できます)。
- 入力元を指定できます(標準入力、ファイルなど)。
その他の拡張