次のコマンドを使用して、Ubuntu 4.6.1 および SUSE 4.6.2 で gcc を使用しています。
gcc gets_s.c
私のソースコードは
// Read and Display Lines
// gets_s.c
#include <stdio.h>
int main(void)
{
char first_name[11];
char last_name[11];
printf("First Name : ");
gets_s(first_name, 11);
printf("Last Name : ");
gets_s(last_name, 11);
puts(first_name);
puts(last_name);
return 0;
}
私の質問について詳しく説明します。
私にとっての主な問題は、入力された行と保存された行の間の 1 対 1 の対応です。
成功した場合、fgets と gets_s の違いは、fgets には改行ターミネータが含まれているのに対し、gets_s は改行ターミネータを null ターミネータに置き換えて、行入力と gets_s への成功した呼び出しとの間の 1 対 1 の対応を維持することです。
バッファー長をオーバーフローする入力の場合、fgets はバッファーに収まる数の文字を受け入れ、残りを次の fgets のために入力バッファーに残します。
標準 (K.3.5.4.1) では、(gets とは異なり) gets_s を使用する場合、改行、EOF、または n-1 文字以内の読み取りエラーが必要であると規定されています。したがって、オーバーフローは実行時制約違反です。実行時制約違反がある場合、バッファ内の最初の文字がヌル文字に設定され、stdin 入力バッファ内の文字が読み取られ、改行文字が読み取られるまで破棄されます。ファイルの終わりが発生します。または読み取りエラーが発生します。
したがって、成功した場合、私は次のことを期待しました。
>fgets
First Name : Chris
Last Name : Szalwinski
Chris
Szalwinski
>
>gets_s
First Name : Chris
Last Name : Szalwinski
Chris
Szalwinski
>
オーバーフローでは、fgets と gets_s とは異なる動作を期待していました。言い換えると、
>fgets
First Name : Christopher
Last Name : Christophe
r
>
>gets_s
First Name : Christopher
Last Name : Szalwinski
Szalwinski
>
gets_s が入力の最初の行の内容を完全に削除することを期待していたことに注意してください。
主な問題が入力行と保存行の間の 1 対 1 の対応である場合、これはデバッグにおいて重要ですが、独自の関数を記述する必要があります (K&R の getline と同様)。
char *gets_s(char *s, int n)
{
int i, c;
for (i = 0; i < n - 1 && (c = getchar()) != EOF && c != (int)'\n'; i++)
s[i] = c;
s[i] = '\0';
while (n > 1 && c != EOF && c != (int)'\n')
c = getchar();
return c != EOF ? s : NULL;
}
このような関数では、1 対 1 の対応が維持され、バッファが飽和し、実行時制約違反は発生しません。
この結論を導き出すことは正しいでしょうか。