0

入力用の fgets() 関数を説明するために設計されたコード セグメントの機能に問題があります。先に進む前に、I/O とストリームに関する私の理解が正しいこと、および完全に的外れではないことを確認したいと思います。

C の入力と出力には、文字列を操作するための特定の実行可能な機能はありません。文字列の操作に固有の関数の 1 つに 'gets()' 関数があります。この関数は、char 配列の制限を超えて入力を受け入れ (したがって、下位互換性を除いて事実上違法になります)、バッファ オーバーフローを作成します。

ここでストリームの話題が持ち上がります。これは、私の理解の範囲では、プログラム内の I/O を説明するためのモデルです。小川は、プログラムによって利用されるデータが伝達される「流れる水」と見なされます。リンクを参照してください: (コンベヤーベルトとしても)

ストリームの概念を説明できますか? ストリームとは

C 言語では、標準入出力用に 3 つの定義済み ANSII ストリームがあり、Windows または DOS を使用している場合は次の 2 つの追加ストリームがあります。

  • 標準入力 (キーボード)
  • stdout (画面)
  • stderr (画面)
  • stdprn (プリンター)
  • stdaux (シリアルポート)

私が理解しているように、物事を管理しやすくするために、これらをオペレーティングシステムに存在する川と考えても問題ありません。プログラムは I/O 関数を使用してデータを入れたり、取り出したり、方向を変えたりします。ストリームが流れています (ファイルの読み取りや書き込みが必要になるなど)。ストリームの「開始」または「終了」について考えないでください。これは、オペレーティング システムによって処理されます。心配する必要があるのは、水がデータを取得する場所であり、それは特定の関数 ( 、 、 、 など) の使用によって仲介printf()puts()gets()ますfgets()

ここから私の疑問が形になり始めます。今、fgets()関数とそれがストリームにどのように結びついているかを把握することに興味があります。fgets()'stdin' ストリームを (自然に) 使用し、組み込みのフェイル セーフ (以下を参照) を備えているため、ユーザー入力が入力の格納に使用される配列を超えることはありません。関数のプロトタイプではなく、関数の概要を次に示しfgets()ます (関数を宣言する必要がある理由がわかりません)。

char *fgets(char *str , int n , FILE *fp);

fgets 関数が取る 3 つのパラメーターに注意してください。

p1 は、入力が格納されているアドレスです (ポインター。おそらく、使用する配列の名前になります。たとえば、'buffer')

p2 は入力する文字の最大長です (これが私の質問の場所だと思います!)

p3 は、入力ストリームを指定します。このコードでは、これは「stdin」です (いつ違うのでしょうか?)

さて、以下のコードを使用すると、心ゆくまで文字を入力できます。Return キーを押すと、入力は、2 番目のパラメーターから 1 を引いた長さ (MAXLEN -1) の行で画面に出力されます。他のテキストなしで return を入力すると、プログラムは終了します。

#include <stdio.h>

#define MAXLEN 10

int main(void)
{
char buffer[MAXLEN];

puts("Enter text a line at a time: enter a blank line to exit");

while(1)
{
        fgets(buffer, MAXLEN, stdin);    //Read comments below. Note 'buffer' is indeed a pointer: just to array's first element.

        if(buffer[0] == '\n')
        {
            break;

        }
        puts(buffer);           
}
return 0;
}

さて、ここに私の質問があります:

1) このプログラムでは無制限の文字を入力できますか? 入力を格納している配列のサイズが限られているため (この場合は 256)、fgets()より安全なメカニズムがわかりません。私が見gets()ている唯一のことは、入力の長い文字列が MAXLEN - 1 スライスに解析されていることですか? gets() が停止しないバッファ オーバーフローを停止すると、何が表示されないのですか? フェールセーフが存在する場所のパラメーターが表示されません。fgets()fgets()

2) プログラムが入力を MAXLEN ではなく MAXLEN-1 の行に出力するのはなぜですか?

fgets()3)関数の 2 番目のパラメーターの意味は何ですか? プログラムを実行すると、好きなだけ文字を入力できます。MAXLEN はバッファ オーバーフローを防ぐために何をしていますか? 私が推測できることから、ユーザーが大きな長い文字列を入力すると、ユーザーがリターンを押すと、MAXLEN は文字列を MAXLEN サイズのバイト/バイトに切り刻み (両方ともここで実際に動作します 笑)、配列に送信します。ここで重要な何かが欠けていると確信しています。

それは一口でしたが、この非常に重要な主題を理解していないために、コードが脆弱になっています。

4

3 に答える 3