C語言通過gets和gets_s分別實(shí)現(xiàn)讀取含空格的字符串
導(dǎo)讀
在刷Oj題時(shí),遇到包含空格的字符串輸入,如何讀取呢?如果使用scanf以%s格式去讀取輸入的字符串,遇到空格就讀取結(jié)束了,顯然這樣是讀取不了的。當(dāng)然,scanf也是可以讀取含空格字符串的,但操作起來相對較難,對C語言初學(xué)者并不友好。下面開始介紹兩個(gè)可以對含空格字符串讀取的庫函數(shù)------gets和gets_s函數(shù)
gets函數(shù)
函數(shù)聲明
char * gets ( char * str );
函數(shù)介紹
頭文件
#include<stdio.h>
從stdin獲取字符串
從標(biāo)準(zhǔn)輸入(stdin)中讀取字符(包括空格,Tab),并將其作為C字符串存儲到str中,直到到達(dá)換行符或文件結(jié)尾。
如果找到換行符,則不會將其復(fù)制到str中。
在復(fù)制到str的字符之后,將自動追加終止的空字符。
請注意,gets與fgets完全不同:gets不僅使用stdin作為源,而且在結(jié)果字符串中不包含結(jié)尾的換行符,并且不允許指定str的最大大?。ㄟ@可能導(dǎo)致緩沖區(qū)溢出)。
參數(shù)
str
指向內(nèi)存塊(字符數(shù)組)的char*型指針,其中讀取的字符串作為C字符串復(fù)制。
返回值
成功時(shí),函數(shù)返回str(返回輸入字符串的起始位置)。
讀取結(jié)束(讀取到'\n')或讀取失敗時(shí),函數(shù)返回空指針(NULL)。
以下兩行了解即可
如果在嘗試讀取字符時(shí)遇到文件結(jié)尾,則設(shè)置EOF指示符(FEOF)。如果在讀取任何字符之前發(fā)生這種情況,則返回的指針為空指針(NULL)(str的內(nèi)容保持不變)。
如果發(fā)生讀取錯誤,將設(shè)置錯誤指示符(ferror),并返回空指針(NULL)(但str指向的內(nèi)容可能已更改)。
兼容性
C標(biāo)準(zhǔn)的最新修訂版(2011年)已明確將該功能從其規(guī)范中刪除。
該函數(shù)在C++中被禁止(如2011個(gè)標(biāo)準(zhǔn),它遵循C9+TC3)。
用法實(shí)例
(在DEV-C++編譯器環(huán)境底下,Visual Studio 2019并不支持gets函數(shù))
eg1:多組輸入含空格字符串,輸出其字符串長度和字符串
#include<stdio.h> #include<string.h> int main() { char str[100] = { 0 }; int len=0; while(gets(str) != NULL) //gets函數(shù)的多組輸入寫法,讀取結(jié)束或失敗時(shí)返回NULL,注意和scanf函數(shù)的多組輸入結(jié)束或失敗返回值EOF區(qū)分開 { len = strlen(str); printf("輸入的字符串%s長度是%d\n", str, len); } return 0; }
eg2:使用動態(tài)內(nèi)存分配函數(shù)返回的指針接收輸入的含空格的字符串
#include<stdio.h> #include<string.h> #include<stdlib.h> int main() { char* str = (char*)calloc(100, sizeof(char)); //char* str = (char*)malloc(100 * sizeof(char)); int len=0; if(str != NULL) { while(gets(str) != NULL) //gets函數(shù)的多組輸入寫法,讀取結(jié)束或失敗時(shí)返回NULL,注意和scanf函數(shù)的多組輸入結(jié)束或失敗返回值EOF區(qū)分開 { len = strlen(str); printf("輸入的字符串%s長度是%d\n", str, len); } free(str); str=NULL; } return 0; }
eg3:由于目標(biāo)指針str不允許指定str的最大大?。ㄟ@里指內(nèi)存空間大?。ㄟ@可能導(dǎo)致緩沖區(qū)溢出)
#include<stdio.h> #include<string.h> #include<stdlib.h> int main() { char str[3] = { 0 };//創(chuàng)建可以存放三個(gè)字符的數(shù)組 int len=0; //輸入字符串a(chǎn)bcdef(超過str數(shù)組長度) 這種情況下的輸出依然可以得到期望的值。 //但是,這也體現(xiàn)了gets函數(shù)在某些情況下可能會導(dǎo)致緩沖區(qū)溢出,這是一個(gè)不安全的函數(shù) while(gets(str) != NULL) //gets函數(shù)的多組輸入寫法,讀取結(jié)束或失敗時(shí)返回NULL,注意和scanf函數(shù)的多組輸入結(jié)束或失敗返回值EOF區(qū)分開 { len = strlen(str); printf("輸入的字符串%s長度是%d\n", str, len); } return 0; }
gets_s函數(shù)
函數(shù)聲明
char * gets_s( char * buffer,? size_t? sizeInCharacters );
函數(shù)介紹
頭文件
#include<stdio.h>
參數(shù)
buffer
輸入字符串的存儲位置,char*型指針。
sizeInCharacters
緩沖區(qū)的大小。
返回值
如果成功,則返回 buffer。 NULL 指針指示錯誤或文件尾條件。 使用 ferror 或 feof 來確定發(fā)生了哪一個(gè)。
注解
gets_s 函數(shù)從標(biāo)準(zhǔn)輸入流 stdin 中讀取一個(gè)行并將該行存儲在 buffer中。 該行由所有字符組成,其中包含第一個(gè)換行符 ( " \n " ) 。 gets_s 然后,在返回行之前,將換行符替換為空字符 ( " \0 " ) 。 相反, fgets_s 函數(shù)將保留換行符。
如果讀取的第一個(gè)字符是文件尾字符,則空字符將存儲在 buffer 的開頭,并返回 NULL。
_getws_s 是 gets_s 的寬字符版本;其參數(shù)和返回值都是寬字符字符串。
如果 buffer 為 NULL 或 sizeInCharacters 小于或等于零,或者如果緩沖區(qū)太小,無法包含輸入行和 null 終止符(小寫的null即空字符 ( " \0 " )),這些函數(shù)將調(diào)用無效參數(shù)處理程序,如buffer中所述。 如果允許執(zhí)行繼續(xù),則這些函數(shù)返回 NULL 并將 errno 設(shè)置為 ERANGE。
以下兩行了解即可
在C++ 中,使用這些函數(shù)由模板重載簡化;重載可以自動推導(dǎo)出緩沖區(qū)長度 (不再需要指定大小自變量),并且它們可以自動用以更新、更安全的對應(yīng)物替換舊的、不安全的函數(shù)。 有關(guān)詳細(xì)信息,請參閱安全模板重載。
默認(rèn)情況下,此函數(shù)的全局狀態(tài)的作用域限定為應(yīng)用程序。 若要更改此項(xiàng),請參閱 CRT 中的全局狀態(tài)。
用法實(shí)例
(由于gets_s是Visual Studio 編譯器提供的安全gets函數(shù),因此僅在該編譯器環(huán)境底下可以使用)
eg1:多組輸入,多組輸出,求含空格字符串長度,以char類型型數(shù)組存放
#include<stdio.h> #include<string.h> #define SZ 10 //根據(jù)實(shí)際輸入情況定義最長字符串長度+1即可,增加1是為了給'\0'留位置,這里最長可輸入9長度的字符串 int main() { int len = 0; char str[SZ] = { 0 }; while (gets_s(str, SZ) != NULL)//這里只能輸入不超過SZ-1長度的字符串,否則程序崩潰,這也體現(xiàn)出gets_s函數(shù)的安全性極高 { len = strlen(str); printf("輸入的字符串%s長度為%d", str, len); } return 0; }
eg2:多組輸入,多組輸出,輸入處理含空格的字符串,以動態(tài)內(nèi)存分配函數(shù)形式
#include<stdio.h> #include<stdlib.h> #include<string.h> #define SZ 10 //根據(jù)實(shí)際輸入情況定義最長字符串長度+1即可,增加1是為了給'\0'留位置,這里最長可輸入9長度的字符串 int main() { int len = 0; char* str = (char*)malloc(SZ * sizeof(char)); // char* str = (char*)calloc(SZ, sizeof(char)); while (gets_s(str, SZ) != NULL)//這里只能輸入不超過SZ-1長度的字符串,否則程序崩潰,這也體現(xiàn)出gets_s函數(shù)的安全性極高 { len = strlen(str); printf("輸入的字符串%s長度為%d", str, len); } free(str); str=NULL; return 0; }
學(xué)習(xí)小結(jié)
這兩個(gè)函數(shù)給我們提供了一種新的讀取字符串的方式,與scanf函數(shù)讀取字符串的區(qū)別就在于它們可以讀取含空格,Tab的字符串。解決關(guān)于字符串OJ問題的關(guān)鍵一步,讀取輸入的字符串就得到有效的解決了。
在DEV-C++編譯器環(huán)境底下,直接調(diào)用gets函數(shù)即可;在Visual Studio 2019等VS編譯器底下,gets函數(shù)被gets_s函數(shù)取代,調(diào)用gets_s函數(shù)即可。
這兩個(gè)函數(shù),注意傳遞的參數(shù),在提交到OJ系統(tǒng)上時(shí),應(yīng)該使用gets函數(shù),因?yàn)镺J系統(tǒng)上的編譯環(huán)境其實(shí)是DEV。
給大家西大OJ上的一道處理含空格字符串的題目,OJ練習(xí):OnlineJudge
西大OJ時(shí)常會出現(xiàn)崩潰情況,我還是把題目放底下給大家吧。
到此這篇關(guān)于C語言通過gets和gets_s分別實(shí)現(xiàn)讀取含空格的字符串的文章就介紹到這了,更多相關(guān)C語言讀取含空格的字符串內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++11中跳轉(zhuǎn)initializer_list實(shí)現(xiàn)分析
這篇文章主要介紹了C++11中跳轉(zhuǎn)initializer_list實(shí)現(xiàn)分析,實(shí)例分析initializer_list<T>初體驗(yàn),結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04C語言數(shù)據(jù)結(jié)構(gòu)中樹與森林專項(xiàng)詳解
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)中樹與森林,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-11-11