gets()fgets()

3239 ワード

まずは自問自答、間違い!fgets()にも落とし穴があります!
実のところhttp://www.cplusplus.com/reference/clibrary/cstdio/gets/はっきり言いました
Notice that gets does not behave exactly as fgets does with stdin as argment: 
First,the ending newline character is not includ withgets while with fgets it is. 
Second、 gets does not let you specify a limit on how many characters arters to be read、so you must be careful with the size of the array pointed by str to avoid buffer overflows.
まず、getsの問題(英語のSecondに対応しています.多くの人がよく知っているでしょう.)を見てみましょう.
古い譚は言っていないかもしれませんが、K&Rは言っていないかもしれません.しかし、もう少しCの深いところに行きたいなら、「CSAPP」を開いて、「C専門家プログラミング」を開けてください.
ゲツ関数には重大な潜在的危険があり、無数のメモリオーバーフロー攻撃を引き起こしたことがあります.
getsは入力長さをチェックしたり制限したりしないので、入力長さが文字配列を超えていると、getsはメモリに書き込み続け、思わぬ問題が発生します.
はい、この時これらの本や大神さんたちがゲツの代わりにfgetsを使って教えてくれます.
簡単に字数を制限すれば終わりですか?事情はそうではない.
またgets()の迷惑なところ(英語のFirstに対応):
当節の多くの命令ラインシステムは行走査方式を採用しています.一回の回車で一回の入力を送ります.
通常、このエコーは変数に読み込まれません.しかし、fgetsは例外です.
簡単にファイルを開く例を作ると、この問題が浮き彫りになります.
#include   
2.  
3.int main()  
4.{  
5.    FILE *fp;  
6.    char name[40];  
7.  
8.    fgets(name, 40, stdin);  
9.  
10.    if ( (fp = fopen(name, "rb")) == NULL)  
11.    {  
12.        perror("open file");  
13.        return -1;  
14.    }  
15.  
16.    fclose(fp);  
17.    return 0;  
18.}  
私のディレクトリの下にtest.sというファイルがあります.しかし、入力した後にエラーメッセージのopen file:No such file or directoryが発生しました.
printfプリントname文字列に問題はありませんでした.出力は「test.s」です.
そこでGDBでこのコードを調整して、nameの内容を追跡する時、問題を発見しました.
(gdb)s test.s 10    if((fp=fopen)==NULL)1:name=「test.s\000\261\205\004\bP\204\004\b\000\000\333;\026\000\263*\000\364\257\000\000\000
案の定併呑された.
次のように修正します
#include   
2.  
3.int main()  
4.{  
5.    FILE *fp;  
6.    char name[40], buf[40];  
7.  
8.    fgets(buf, 40, stdin);  
9.    memcpy(name, buf, strlen(buf) - 1);  
10.  
11.    if ( (fp = fopen(name, "rb")) == NULL)  
12.    {  
13.        perror("open file");  
14.        return -1;  
15.    }  
16.  
17.    fclose(fp);  
18.    return 0;  
19.}  
以上は転載して
http://blog.csdn.net/qwb492859377/article/details/48323443
次は ACMでgets()関数を使って遭遇した問題
このような経験がありますか?getsを使って、めちゃくちゃなwaができますが、scanfを使ってまた正しいです.
 windowsの改行は\rで、linuxの改行はただ、windowsシステムの下でgetsを使って1行の一番後ろの\rを飲み込みますが、linuxの下でgetsで最後の1つだけを飲み込みます. 
 問題が来ました.もしデータはwindows環境下で構築され、改行符は\rを使っていますが、サーバーはlinuxです.管理人は直接windows下で生成したデータを処理せずにlinuxのサーバに移動しました.
 それはojの評価では、各行の最後にもう一つの\rがありますので、時々うっかりしてしまいます.
ですから、ここのgets()の使用には注意しなければなりません.使わなくても大丈夫です.しかし、ここにも処理方法があります.
bool safe_gets(char *S){  
2.    int n = strlen(S);  
3.    if(!gets(S)) return false;  
4.    if(n && S[n - 1] =='\r') S[n - 1] = 0;  
5.    return true;  
6.}  
この関数を使えばいいです.
int mygets(char s[])  
{  
    int i = 0;  
    char c;  
  
    while((c = getchar()) && c != '
' && c != EOF) if(isalpha(c) || isdigit(c) || c == '.' || c == ',' || c == ' ') s[i++] = c; s[i] = '\0'; return i > 0 || c != EOF; }