C言語文字列読み出し関数gets()とfgets()


c言語で文字列を読み取るには、scanf()と%sを組み合わせて使用するなど、さまざまな方法がありますが、スペースなどの空の文字に遭遇すると返される単語は1つしか取得できません.1行の文字列を読み込む場合は、次のようにします.
I love BIT
この場合、scanf()はどうしようもありません.このとき私たちが最初に思いついたのはgets()で読み取ることです.
gets()関数は標準入力(キーボード)から1行のデータを読み込み、1行を読み出すと改行に遭遇して返されます.gets()関数は改行文字'''を読み込まず、c言語文字列の終了のフラグとして改行文字'0'に置き換えられます.
gets()関数はputs()関数とよくペアで使用され、puts()関数は文字列を表示し、文字列の後ろに改行フラグ'''を自動的に追加します.
#include 

#include 

//                 
int main()
{
    char str[1000];
    const char *d = " ";
    while (gets(str) != NULL) {
        printf("%s
"
, str); char *p; p = strtok(str, d); while(p) { printf("%s
"
, p); p = strtok(NULL, d); } } return 0; }

gets()関数には深刻な欠陥があります.この欠陥は、配列が下入力行を入れることができるかどうかを検査しないことです.
例:
配列char srcを定義し[5]、gets(src)を呼び出して標準入力から文字列を読み出すと、gets()関数のパラメータが配列名であることがわかり、配列名はポインタ、すなわち配列のヘッダアドレスに相当することが知られています.このときI love BITのような5文字以上の入力をすると、gets()関数はsrcが指すアドレスから順に各文字を入力しますが、srcには5バイトの空間しか割り当てられておらず、この5つの空間を満たすとgets()関数は割り当てられていないメモリ空間にアクセスし、この空間にデータが格納されている場合、プログラムがエラーして中断します.
gets()関数のこの欠陥により,C 99規格ではgets()関数の使用は推奨されなくなり,C 11ではこの関数を直接放棄した.
実はgets()の代わりにc言語のfgets()関数を使うことができます.
まず、関数のプロトタイプ宣言を見てみましょう.
char *fgets(char *buf, int bufsize, FILE *stream);
2番目のパラメータbufsizeに注意すると、このパラメータは読み出した文字の個数を制限し、gets()関数の欠陥を解決することができます.
fgets()関数は主にファイルの読み取りに使用されることを知っています.キーボードを読み込む場合はstreamパラメータがstdinである必要があります.
bufsizeがnに設定されている場合、fgets()関数はn-1文字まで読み取ります.「最大」という言葉を使うのは、前に改行文字に遭遇した場合、fgets関数も返されるからです.
もう1つは、fgets()関数は改行文字(gets関数とは異なる)を読み出し、読み出しが終了すると、fgets関数はbufの末尾に文字列の終了として空の文字を追加します.
簡単な例を見てみましょう
#include 
#include 
#define LEN 6
int main(int argc,char* argv[])
{
    char src[LEN];
    printf("please enter:
"
); fgets(src,LEN,stdin); printf("your enter is:
"
); fputs(src,stdout); }

このプログラムでは、配列の長さを6に設定し、まず入力と出力のセットを見てみます.please enter:zhan you enter is:zhan Press any key to continue入力はzhanとリターン(’’)で、全部で5文字です.fgetsはこの5文字を読み出し、最後に文字列終了フラグ'0'を追加します.fputs()関数は改行を自動的に追加しないことは知っていますが、出力結果は改行してPress any...、これは、fgets()関数が改行文字を読み出すことを示しています.
入力出力のセットを見ています:please enter:zhang you enter is:zhangPress any key to continue
今回はzhangと折り返し行を入力しましたが、fgets関数は依然として5文字(LEN-1文字)を読み出しています.このときfgets()はzhangを読み込んで、すでに5文字なので、折り返し行は読み込まれず、最後にfgets()は文字列終了フラグ'0'を追加しますので、出力を見るとPress any...折り返し出力ではなく、zhangと同じ行になります.