gets,fgets,scanfと文字列の物語

5617 ワード

1.gets


getsは標準入力装置から文字列を読み出す関数であり、関数プロトタイプchar*gets(char*str);C言語を勉強し始めたばかりの頃、getsという関数はscanfより短く、スペースのある文字列を入力できるので、かなり使いやすいと思っていました.しかし後学に進むと,C言語でgets関数を用いたソースファイルをGCCでコンパイルし,コンパイラが警告する.
warning: implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]

 : the `gets' function is dangerous and should not be used.

 
なぜならgetsは無限に読み取ることができ、上限を判断することができず、無限入力がスタック空間をオーバーフローさせ、プログラムが戻ると正常に戻るアドレスを見つけることができず、プログラムは予測不可能な動作を起こすからである.getsを使うと、私たちが今書いているような小さなプログラムはPC側でフラッシュバックする可能性がありますが、大規模なプロジェクトでは深刻な損失をもたらします.そこでgets関数の使用はできるだけ避けるべきである.ちなみに2011年12月、ANSIはISO/IEC 9899:2011規格を採用し、規格ではgets()関数を削除し、新しいより安全な関数gets_を使用した.s()代替.

getsで文字列を入力しない場合は、fgetsとscanfを使用します。


2.fgets


関数プロトタイプchar*fgets(char*buf,int bufsize,FILE*stream);buf:得られたデータを格納するためのアドレスを指す文字型ポインタ.bufsize:格納データのサイズを示す整数データ.*stream:ファイル構造体ポインタ、読み込むファイルストリーム.
fgets関数の呼び出し形式は、fgets(str,n,fp);ここで、fpはファイルポインタである.strは文字列に格納された開始アドレスである.nはintタイプ変数です.関数の機能は、fpが指すファイルからn-1文字を読み込んでstrが先頭アドレスの空間内に入れることである.n-1文字未満で改行またはEOF(ファイル終了フラグ)が1つ読み取られた場合、今回の読み取り操作を終了し、読み込まれた文字列に最後に読み込まれた改行が含まれます.したがって、正確には、fgets関数を呼び出すと、最大n-1文字しか読み込めません.読み込みが終了すると、システムは自動的に最後に'0'を追加し、成功すると、関数は同じstrパラメータを返します.ファイルの最後に到達したり、文字が読み込まれなかったりした場合、strの内容は変更されず、空のポインタが返されます.
次に例を示します.
#include 

int main()
{
   FILE *fp;
   char str[60];

   fp = fopen("file.txt" , "r");
   if(fp == NULL) {
      perror(" ");
      return(-1);
   }
   if( fgets (str, 60, fp)!=NULL ) {
      puts(str);
   }
   fclose(fp);
   
   return(0);
}

ファイルがあるとします.txt  .彼の内容は以下の通りです.
Xiyou Linux Group!

上記のコードをコンパイルすると、結果が得られます.
Xiyou Linux Group!

3.scanf


関数プロトタイプint scanf(char*format[,argument,...]);scanf()関数は、標準入力装置(キーボード)から入力された情報を読み出す汎用端末フォーマット入力関数である.任意の固有のタイプのデータを読み込み、自動的に数値を適切な機内フォーマットに変換できます.呼び出しフォーマットはscanf(""");scanf()関数は、正常に割り当てられたデータ項目数を返し、エラーが発生した場合はEOFを返します.空白文字はscanf()関数を読み取り操作で入力の1つ以上の空白文字を省略し、空白文字はspace、tab、newlineなどであり、最初の非空白文字が現れるまで使用できます.空白以外の文字は、scanf()関数が読み込み時にこの空白以外の文字と同じ文字を削除します.
では、scanfで文字列を入力するにはどうすればいいのでしょうか.次の2つのフォーマットを使用できます.
%c入力文字ごと%s全体1回入力文字列
例を挙げる
 
#include 
int main()
{
    char a[18];
    int i;
    for(i=0;i<17;i++){
        scanf("%c",&a[i]);
    }
    for(i=0;i<17;i++){

       printf("%c",a[i]);
    }
    printf("
"); }

上のコードは%cで文字を1つずつ入力する場合、%cには大きな限界があります.入力文字数はループの回数と等しくなければならないので、自動的に終了記号0は加算されません.いくつかのデータを使用してテストします.
input:xiyou linux group
output:xiyou linux group

input:abcdefghigklmnopqrstuvwxyz
output:abcdefghigklmnopq

input:abc                     
output:abc

第1グループのデータはちょうど17文字で、出力に成功した.第2のグループのデータは配列サイズを超えており、ループ時に予想入力文字数が設定されているため、超えた部分は入力されていない.3番目のグループのデータは3文字しか表示されませんが、入力を正常に終了するには、後ろにスペースを補充する必要があります.
そして%s
#include 
int main()
{
  char a[20];
  scanf("%s",a);
  printf("%s
",a); }

 
いくつかのテストデータを入力します.
input:xiyoulinuxgroup
output:xiyoulinuxgroup



input:xiyou linux group
output:xiyou

input:qwertyuiopasdfghjklz
output:qwertyuiopasdfghjklz
*** stack smashing detected ***:  terminated
  ( )

これらのグループのデータから,%sで入力すると配列サイズを超えない任意の文字を入力できるが,scanf()では複数の文字列の区切り文字であるため,この方法で1つの文字配列にスペース付き文字列を入力しようとすると,最初のスペースより前の文字列のみが有効であることがわかる.
では、scanf()でスペース付き文字列を入力するにはどうすればいいのでしょうか.(%cは使用しません)
今はscanfスキャン集って使いやすいな~~~
次にscanf()のスキャンセットについて説明します.getsをfgetsに置き換えて入力文字列にスペースを含めることも、scanfのスキャンセットで実現することもできます.
#include 
 
int main( int argc,char *argv[] )
{
    char str[20];
    printf("input:");
    scanf("%[^
]",str); printf("output:%s
",str); return 0; }
inout:xiyou linux group
output:xiyou linux group

スペース付き文字列の入力に成功しました!
上のコードは実はscanfスキャンセットの1つの使い方ですが、scanfスキャンセットとは何ですか?
スキャンセットは、scanf()によって許容される文字を読み込み、対応する文字配列に割り当てる文字セットを定義します.スキャンセットは、相手のカッコの文字列で定義され、左のカッコの前にパーセント記号を付けなければなりません.
具体的な役割は、入力した文字が括弧内の文字列のいずれかに属する場合、その文字を抽出することです.属しないことが判明すると抽出を終了する.この方法では、抽出された文字の後ろに自動的に'0'が追加されます.
次に例を示します.
#include 
 
int main( int argc,char *argv[] )
{
    char str[10];
    printf("input:");
    scanf("%[abc]",str);
    printf("output:%s
",str); return 0; }

実行結果:
input:abcdefg
output:abc

結果から,scanfはabcの3文字のみを受け入れ,角カッコ内文字以外の文字は受け入れていないことが分かった.また,出力時にabcのみが出力され,他の乱符号は出力されず,abc後に自動的に'0'が加わったことがわかる.
「[]」には、「^」という役割を修飾する別の文字を追加することもできます.この記号は「補完セット」と理解できます.すなわち、角カッコ内の他の文字をスキャンします.入力した文字が角カッコ内の文字列のいずれかに属していない場合、その文字を抽出します.入力された文字がその文字に属していることが判明すると、終了します.次に、上記の例を少し修正して、この「補集」の使い方を見てみましょう.
#include 
 
int main( int argc,char *argv[] )
{
    char str[10];
    printf("input:");
    scanf("%[^abc]",str);
    printf("output:%s
",str); return 0; }

実行結果:
input:1234cba
output:1234

この例では,補完セットにおいては改行終了入力までスキャンし,スペースを読み込むことができることが明らかになった.