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は例外です.
簡単にファイルを開く例を作ると、この問題が浮き彫りになります.
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
案の定併呑された.
次のように修正します
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()の使用には注意しなければなりません.使わなくても大丈夫です.しかし、ここにも処理方法があります.
実のところ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;
}