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&int main()
{ int c; do putchar(toupper(c = getchar())); while (c != ""); return 0;}
linux下測試正常
補充:如果在用linux且一定要用字元串的話可以試試char *p;scanf("%m[^
]",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語言中的指針為什麼要區別出指向不同數據類型的指針?
※怎樣判斷浮點數是否相等並保證同一性?
※對於一個很複雜的常量表達式,編譯器會算出結果再編譯嗎?
※面向對象和面向過程分別是什麼?