gcc環境下不能使用gets怎麼辦?

我在codingground下編譯c,想輸入一句帶空格的句子,因此不能用scanf,用gets函數報錯warning: the `gets" function is dangerous and should not be used,然後用fgets函數,但是fgets只能輸入n個字元(n要求自己輸入),可是要輸入整句話,而我不知道整句話多少字元,何解?

抱歉沒說明白,很多人問我為啥不知道string長度,其實我是要寫的是使用者輸入一句話,然後轉換成大寫問題(各位大神應該看好多次了),所以這句話是使用者輸入的,咱在編譯時不知道啊,我想做的就是用一個函數接受這句話的輸入(以前用的scanf),就醬


可以手動判斷輸入字元串的倒數第二個字元是不是換行,不是就說明沒讀完,那就再來一次唄


可是要輸入整句話,而我不知道整句話多少字元

這話自相矛盾。

不知道多少個字元怎麼可能用gets呢?


用C++一切引刃而解:getline(cin, output, "
")


如果是在 Linux 下,你可以直接去 read() stdin ,從而避免標準輸入輸出下空格,回車,EOF等的不確定性。


Linux的話,你可以安裝libreadline-dev包,然後引入頭文件

#include &

你就可以得到這麼一個函數:

char *result = readline("please input a line");

輸入的一行內容會通過result返回給你,注意這塊內存是malloc出來的,用完記得free

其他的類似庫有非常好用的linenoise(可以去github搜索一下),用法類似。

不想引入第三方庫的話,一個辦法是限制長度了:

#define LINE_MAX 80
char buff[LINE_MAX];
if (fgets(buff, LINE_MAX, stdin) != NULL) {
...
}

缺點有好幾個:fgets不去掉
,所以需要你自己處理。通常就是buff[strlen(buff)-1] = "";這樣。但是用戶還是有可能輸入超過80字的,這時候其實就有點麻煩了= =

另外一個辦法是考慮直接getchar幹活吧:

char buff[LINE_MAX]; /* 定義見上 */
int len = 0, ch;
while ((ch = getchar()) != "
" ch != EOF) {
if (len &< LINE_MAX-1) buff[len++] = ch; } buff[len] = "";

優勢是清楚簡單,隨時可書寫,而且也相對比較實用:如果輸入過長,後面的內容會被忽略,不會造成任何嚴重危害。

鑒於自己發明輪子各種麻煩,還是考慮readline或者類似庫吧……如果不想有依賴,就自己寫一個readline吧,完全不難的:

#include &
#include &

char *my_readline(const char *prompt) {
size_t capacity = 80; /* initial value */
int ch, len = 0;
char *p = (char*)malloc(capacity);
if (p == NULL) return NULL;
fprintf(stderr, "%s", prompt);
while ((ch = getchar()) != "
" ch != EOF) {
if (len == capacity) {
char *newp = (char*)realloc(p, capacity*=2);
if (newp == NULL) {
free(p);
return NULL;
}
p = newp;
}
p[len++] = ch;
}
p[len] = "";
return p;
}

其實和上面那個看上去差不多對不對?

聲明:上面所有代碼都未調試,如果有問題請留言 :)

就醬~


n的大小就是你緩衝區大小好了。如果你用gets,而長度超出你緩衝區,你程序就崩了。


誰告訴你 warning 是錯誤的?

它只是出於善意警告一下而已。

gcc 不是操作系統,但是 gets 緩衝區遇到字元串太長炸的事情啊,它見得多了。類 UNIX 開源界的哪一行 C 它沒有編譯過?你呀有一個好,至少會瞥一眼 warning,但是問來問去的問題啊,都 too simple 啊,sometimes na?ve。它現在是作為一個長者,告訴你一些前輩的失敗經驗。

另外我似乎不記得 scanf %s 會被空格嚇到啊(其實是會的),不過這樣做你開字元串——我是說以 結尾的字元數組——的時候還是要猜長度。好消息是你只需要猜最大長度。(唔,是會停住的…)

嗯…如果你真的不喜歡 scanf 又害怕 gets 闖禍的話…嗯…唔……用 getchar() 吧。還記得當年的 while ((c=getchar())!=EOF) 嗎?


能不用就不用唄,又不是沒其他方法。

話說gets這玩意在c11標準被廢除了。。。


  • char * fgets (char * string, int n, FILE *stream);

//不保留回車符可以用這個
#include &

char * fget_string (char * string, int n, FILE *stream)
{
char * temp;

fgets (string, n, stream);
temp = strchr (string, "
");
if (*temp)
*temp = "";

return string;
}

  • while (fgets () * != EOF) //寫入很多字元好像用這個也行


scanf %[^
]


可以不用字元串的

#include&

#include&

int main()

{

int c;

do putchar(toupper(c = getchar())); while (c != "
");

return 0;

}

linux下測試正常

補充:如果在用linux且一定要用字元串的話可以試試

char *p;

scanf("%m[^
]",p); //動態分配

puts(p); //輸出

free(p); //釋放內存


[0] 那不是報錯,那是warning;

[1] fgets()函數第二個參數是用來限定最多讀入字元的個數,不是「只能輸入n個字元」;

[2] fgets()函數不會自動將"
"轉成""


這個是真的最好別用……學了也不是好習慣

找新標準,有個較安全的替代函數,好像是限制了長度吧


gets()不安全,在c11里被刪除了,替代的貌似為gets_s()。或者你可以加上參數-std=ansi?


only dangerous.不商用的程序,不與外界通信的程序,隨便用,no problem!


內存管理是你C程序員要做的一個重要的事,預測一下你的一句話最長有多長不就行了嗎?緩衝區就定義成512應該可以滿足你的要求吧,不行的話1024總該可以了吧。就用fgets,沒什麼不好的

==補充=================

聲明字元串時不是有個長度嗎,作為nbyte就可以了呀(安全起見,還是減1吧,然後手動給最後一個字元賦值成0),目測題主對標準I/O和字元串的基礎還不是很牢固,多看看書了解一下 x_x


fgets長度就是你的字元串變數的長度-1啊


用gets難道不用知道句子有多少字元?開數組的時候不是已經定了


推薦閱讀:

怎麼理解C語言的複雜聲明?
C語言中的指針為什麼要區別出指向不同數據類型的指針?
怎樣判斷浮點數是否相等並保證同一性?
對於一個很複雜的常量表達式,編譯器會算出結果再編譯嗎?
面向對象和面向過程分別是什麼?

TAG:Linux | C編程語言 | GCC |