C語言通過gets和gets_s分別實現讀取含空格的字符串

導讀

在刷Oj題時,遇到包含空格的字符串輸入,如何讀取呢?如果使用scanf以%s格式去讀取輸入的字符串,遇到空格就讀取結束瞭,顯然這樣是讀取不瞭的。當然,scanf也是可以讀取含空格字符串的,但操作起來相對較難,對C語言初學者並不友好。下面開始介紹兩個可以對含空格字符串讀取的庫函數——gets和gets_s函數

gets函數

函數聲明

char * gets ( char * str );

函數介紹

頭文件

#include<stdio.h>

從stdin獲取字符串

從標準輸入(stdin)中讀取字符(包括空格,Tab),並將其作為C字符串存儲到str中,直到到達換行符或文件結尾。

如果找到換行符,則不會將其復制到str中。

在復制到str的字符之後,將自動追加終止的空字符。

請註意,gets與fgets完全不同:gets不僅使用stdin作為源,而且在結果字符串中不包含結尾的換行符,並且不允許指定str的最大大小(這可能導致緩沖區溢出)。

參數

str

指向內存塊(字符數組)的char*型指針,其中讀取的字符串作為C字符串復制。

返回值

成功時,函數返回str(返回輸入字符串的起始位置)。

讀取結束(讀取到’\n’)或讀取失敗時,函數返回空指針(NULL)。

以下兩行瞭解即可

如果在嘗試讀取字符時遇到文件結尾,則設置EOF指示符(FEOF)。如果在讀取任何字符之前發生這種情況,則返回的指針為空指針(NULL)(str的內容保持不變)。

如果發生讀取錯誤,將設置錯誤指示符(ferror),並返回空指針(NULL)(但str指向的內容可能已更改)。

兼容性

C標準的最新修訂版(2011年)已明確將該功能從其規范中刪除。

該函數在C++中被禁止(如2011個標準,它遵循C9+TC3)。

用法實例

(在DEV-C++編譯器環境底下,Visual Studio 2019並不支持gets函數)

eg1:多組輸入含空格字符串,輸出其字符串長度和字符串

#include<stdio.h>
#include<string.h>
 
int main()
{
	char str[100] = { 0 };
	int len=0;
	while(gets(str) != NULL)	//gets函數的多組輸入寫法,讀取結束或失敗時返回NULL,註意和scanf函數的多組輸入結束或失敗返回值EOF區分開 
	{
		len = strlen(str);
		printf("輸入的字符串%s長度是%d\n", str, len);
	}
	
	return 0;
}

eg2:使用動態內存分配函數返回的指針接收輸入的含空格的字符串

#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函數的多組輸入寫法,讀取結束或失敗時返回NULL,註意和scanf函數的多組輸入結束或失敗返回值EOF區分開 
		{
			len = strlen(str);
			printf("輸入的字符串%s長度是%d\n", str, len);
		}
 
		
		free(str);
		str=NULL;
	}
 
	return 0;
}

eg3:由於目標指針str不允許指定str的最大大小(這裡指內存空間大小)(這可能導致緩沖區溢出)

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
 
 
int main()
{
	char str[3] = { 0 };//創建可以存放三個字符的數組 
	int len=0;
	//輸入字符串abcdef(超過str數組長度) 這種情況下的輸出依然可以得到期望的值。
    //但是,這也體現瞭gets函數在某些情況下可能會導致緩沖區溢出,這是一個不安全的函數 
	while(gets(str) != NULL)	//gets函數的多組輸入寫法,讀取結束或失敗時返回NULL,註意和scanf函數的多組輸入結束或失敗返回值EOF區分開 
	{
		len = strlen(str);
		printf("輸入的字符串%s長度是%d\n", str, len);
	}
	
	return 0;
}

gets_s函數

函數聲明

char * gets_s( char * buffer,  size_t  sizeInCharacters );

函數介紹

頭文件

#include<stdio.h>

參數

buffer

輸入字符串的存儲位置,char*型指針。

sizeInCharacters

緩沖區的大小。

返回值

如果成功,則返回 buffer。 NULL 指針指示錯誤或文件尾條件。 使用 ferror 或 feof 來確定發生瞭哪一個。

註解

gets_s 函數從標準輸入流 stdin 中讀取一個行並將該行存儲在 buffer中。 該行由所有字符組成,其中包含第一個換行符 ( ” \n ” ) 。 gets_s 然後,在返回行之前,將換行符替換為空字符 ( ” \0 ” ) 。 相反, fgets_s 函數將保留換行符。

如果讀取的第一個字符是文件尾字符,則空字符將存儲在 buffer 的開頭,並返回 NULL。

_getws_s 是 gets_s 的寬字符版本;其參數和返回值都是寬字符字符串。

如果 buffer 為 NULL 或 sizeInCharacters 小於或等於零,或者如果緩沖區太小,無法包含輸入行和 null 終止符(小寫的null即空字符 ( ” \0 ” )),這些函數將調用無效參數處理程序,如buffer中所述。 如果允許執行繼續,則這些函數返回 NULL 並將 errno 設置為 ERANGE。

以下兩行瞭解即可

在C++ 中,使用這些函數由模板重載簡化;重載可以自動推導出緩沖區長度 (不再需要指定大小自變量),並且它們可以自動用以更新、更安全的對應物替換舊的、不安全的函數。 有關詳細信息,請參閱安全模板重載。

默認情況下,此函數的全局狀態的作用域限定為應用程序。 若要更改此項,請參閱 CRT 中的全局狀態。

用法實例

(由於gets_s是Visual Studio 編譯器提供的安全gets函數,因此僅在該編譯器環境底下可以使用)

eg1:多組輸入,多組輸出,求含空格字符串長度,以char類型型數組存放

#include<stdio.h>
#include<string.h>
 
#define SZ 10  //根據實際輸入情況定義最長字符串長度+1即可,增加1是為瞭給'\0'留位置,這裡最長可輸入9長度的字符串
 
int main()
{
    int len = 0;
    char str[SZ] = { 0 };
 
    while (gets_s(str, SZ) != NULL)//這裡隻能輸入不超過SZ-1長度的字符串,否則程序崩潰,這也體現出gets_s函數的安全性極高
    {
        len = strlen(str);
        printf("輸入的字符串%s長度為%d", str, len);
    }
 
    return 0;
}

eg2:多組輸入,多組輸出,輸入處理含空格的字符串,以動態內存分配函數形式

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 
#define SZ 10  //根據實際輸入情況定義最長字符串長度+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長度的字符串,否則程序崩潰,這也體現出gets_s函數的安全性極高
    {
        len = strlen(str);
        printf("輸入的字符串%s長度為%d", str, len);
    }
 
    free(str);
    str=NULL;
 
    return 0;
}

學習小結

這兩個函數給我們提供瞭一種新的讀取字符串的方式,與scanf函數讀取字符串的區別就在於它們可以讀取含空格,Tab的字符串。解決關於字符串OJ問題的關鍵一步,讀取輸入的字符串就得到有效的解決瞭。

在DEV-C++編譯器環境底下,直接調用gets函數即可;在Visual Studio 2019等VS編譯器底下,gets函數被gets_s函數取代,調用gets_s函數即可。

這兩個函數,註意傳遞的參數,在提交到OJ系統上時,應該使用gets函數,因為OJ系統上的編譯環境其實是DEV。

給大傢西大OJ上的一道處理含空格字符串的題目,OJ練習:OnlineJudge

西大OJ時常會出現崩潰情況,我還是把題目放底下給大傢吧。

到此這篇關於C語言通過gets和gets_s分別實現讀取含空格的字符串的文章就介紹到這瞭,更多相關C語言讀取含空格的字符串內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: