fgets函数及其用法,C语言fgets函数详解
? ? ? 雖然用 gets() 時有空格也可以直接輸入,但是 gets() 有一個非常大的缺陷,即它不檢查預留存儲區是否能夠容納實際輸入的數據,換句話說,如果輸入的字符數目大于數組的長度,gets 無法檢測到這個問題,就會發生內存越界,所以編程時建議使用 fgets()。
fgets() 的原型為:
# include <stdio.h>
char *fgets(char *s, int size, FILE *stream);
fgets() 雖然比 gets() 安全,但安全是要付出代價的,代價就是它的使用比 gets() 要麻煩一點,有三個參數。它的功能是從 stream 流中讀取 size 個字符存儲到字符指針變量 s 所指向的內存空間。它的返回值是一個指針,指向字符串中第一個字符的地址。
其中:s 代表要保存到的內存空間的首地址,可以是字符數組名,也可以是指向字符數組的字符指針變量名。size 代表的是讀取字符串的長度。stream 表示從何種流中讀取,可以是標準輸入流 stdin,也可以是文件流,即從某個文件中讀取,這個在后面講文件的時候再詳細介紹。標準輸入流就是前面講的輸入緩沖區。所以如果是從鍵盤讀取數據的話就是從輸入緩沖區中讀取數據,即從標準輸入流 stdin 中讀取數據,所以第三個參數為 stdin。
下面寫一個程序:
輸出結果是:
請輸入一個字符串:i love you
i love
我們發現輸入的是“i love you”,而輸出只有“i love”。原因是 fgets() 只指定了讀取 7 個字符放到字符數組 str 中。“i love”加上中間的空格和最后的 '\0' 正好是 7 個字符。
那有人會問:“用 fgets() 是不是每次都要去數有多少個字符呢?這樣不是很麻煩嗎?”不用數!fget() 函數中的 size 如果小于字符串的長度,那么字符串將會被截取;如果 size 大于字符串的長度則多余的部分系統會自動用 '\0' 填充。所以假如你定義的字符數組長度為 n,那么 fgets() 中的 size 就指定為 n–1(這里貌似有問題),留一個給 '\0' 就行了。
以上是從c語言中文網復制過來的,但是看下面的例子:
#include <stdio.h> int main() { char arr[5]; char *p = arr; //按照上面的敘述,這里4賦值給fget中間的參數size fgets(p,4,stdin); for(int i = 0;i != 5; ++ i){if(arr[i] == '\0')printf("\\0");else if(arr[i] == '\n')printf("\\n");elseprintf("%c",arr[i]);}return 0; }按照上面的說法, 輸入abcd后,輸出結果卻是:abc\0
abcd abc\0? ? ? ? 結果發現,賦值4后,編譯器直接把輸入字符串當成長度是3字符串了(算上結尾的\0是4個),這和我們的預期是不同的,我們分配的字符數組長度是5的,當然希望使用總長度5個字符空間。所以,如果用fgets為字符數組獲取值,fgets的中間size參數直接賦值字符數組長度即可,不必是n-1。(如果有錯,希望各位指正)
但是需要注意的是,如果輸入的字符串長度沒有超過 n–1,那么系統會將最后輸入的換行符 '\n' 保存進來,保存的位置是緊跟輸入的字符,然后剩余的空間都用 '\0' 填充。所以此時輸出該字符串時 printf 中就不需要加換行符 '\n' 了,因為字符串中已經有了。
下面寫一個程序看一下:
輸出結果是:
請輸入字符串:i love studying C語言
i love studying C語言
我們看到,printf 中沒有添加換行符 '\n',輸出時也自動換行了。
所以 fgets() 和 gets() 一樣,最后的回車都會從緩沖區中取出來。只不過 gets() 是取出來丟掉,而 fgets() 是取出來自己留著。但總之緩沖區中是沒有回車了!所以與 gets() 一樣,在使用 fgets() 的時候,如果后面要從鍵盤給字符變量賦值,那么同樣不需要清空緩沖區。下面寫一個程序驗證一下。
輸出結果是:
請輸入字符串:i love you
i love you
Y
ch = Y
反饋:
1.sizeof()作用在字符串上不記結尾\0。也就是返回除去結尾\0后的長度。
2.sizeof()作用在數組上是數組的實際長度,無論數組里面元素是否賦值,結果都是數組長度。
3.fgets()給字符數組賦值的時候,會把末尾的回車鍵也放入到字符數組中(前提是有地方放),字符數組最后一個字符一定是\0補充。例如:
#include <stdio.h> int main() { char arr[5]; char *p = arr; fgets(p,5,stdin); for(int i = 0;i != 5; ++ i){if(arr[i] == '\0')printf("\\0");else if(arr[i] == '\n')printf("\\n");elseprintf("%c",arr[i]);}return 0; } a a\n\0\0\0 ab ab\n\0\0 abc abc\n\0 abcd abcd\0 abcde abcd\04.字符數組實際接受輸入字符長度是:字符數組長度- 1。如果輸入字符串長度大于
字符數組長度 - 1,那么其余部分不會丟棄,會繼續留在內存緩存中。如下:
#include <stdio.h> int main() { char arr[5]; char *p = arr; fgets(p,5,stdin); for(int i = 0;i != 5; ++ i){if(arr[i] == '\0')printf("\\0");else if(arr[i] == '\n')printf("\\n");elseprintf("%c",arr[i]);} char ch; scanf("%c",&ch); printf("%c",ch);return 0; }第一行是輸入,第二行是輸出,可以看到,程序中即使有2個接收輸入的語句(分別是fgets和scanf)語句,但是第一次輸入abcdefghijklmn后,沒等第二次輸入后,程序已經運行出結果了,因為fgets只能讀取5-1=4個字符,從e一直到最后一個字符在第一次輸入后就留在緩存中了,程序運行到scanf函數的時候,scanf發現從緩存中可以讀取字符,所以不提示輸入立刻就讀取了e,然后輸出結果。
abcdefghijklmn abcd\0er再次,其實只要程序輸入字符數<= 4個,scanf()函數都不會有提示,為何?比如輸入abcd后,那么接著用戶會輸入\n,所以實際上已經輸入了5個字符,fgets會接受前面4個,最后面的\n留在緩存中了,等到scanf運行時候,會直接讀取\n。所以此時scanf也不會提示。準確點來說,第一次輸入字符數<=3個,scanf就會提示,否則不會提示。
無論哪個輸入流,都不會忽略\n,哪怕是scanf也是如此。
例如:
scanf("%c",&ch1); scanf("%c",&ch2); printf("%c",ch1); printf("%c\n",ch2);如果這段代碼輸入2個回車,程序立刻會結束,輸入2個回車。因為回車也是字符。
總結
以上是生活随笔為你收集整理的fgets函数及其用法,C语言fgets函数详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于scanf
- 下一篇: 关于文件操作的\r\n问题。