C++中的字符串(1)
1、字符串
1.1 字符串定義
字符串就是連續(xù)的一連串字符,在C++當(dāng)中, 處理字符串的方式有兩種類型。一種來(lái)自于C語(yǔ)言,也被稱為C風(fēng)格字符串。另外一種是基于string類庫(kù)。
C風(fēng)格的字符串其實(shí)就是字符存儲(chǔ)在char數(shù)組當(dāng)中。不過(guò)它和一般的數(shù)組有一些區(qū)別,擁有一些特殊的性質(zhì)。比如一空字符\0結(jié)尾,它的ascii碼是0,用來(lái)標(biāo)記字符串的結(jié)尾。
char str[5] = {'h', 'e', 'l', 'l', 'o'};
char str2[5] = {'h', 'e', 'l', 'l', '\0'};
對(duì)于上面的兩個(gè)例子,第一個(gè)例子雖然也是char數(shù)組,但是由于它的結(jié)尾不是\0,所以它不能看成是字符串。因?yàn)楹芏嗨惴ǘ际且診0的位置為標(biāo)記的,比如計(jì)算字符串長(zhǎng)度的算法,以及cout等等。
上面我們采用的是數(shù)組常規(guī)的初始化方式,這當(dāng)然是可以的,不過(guò)這樣會(huì)很不方便。一個(gè)是需要一位一位地填寫字符,會(huì)非常地麻煩。另外還需要手動(dòng)填充\0,也容易忘記,
所以對(duì)于字符串而言我們還有更好的初始化方式:
char hello[6] = "hello"; char world[] = "world";
用引號(hào)括起來(lái)的字符串隱式地包含了結(jié)尾的\0,需要注意的是,我們?cè)诖_定數(shù)組長(zhǎng)度的時(shí)候需要將結(jié)尾的\0也計(jì)算在內(nèi)。
這里要提醒大家注意引號(hào)的區(qū)別, 在C++當(dāng)中單引號(hào)表示單個(gè)字符,而雙引號(hào)表示字符串。所以下面這種寫法是錯(cuò)誤的:
char c = "S";
并且“S”其實(shí)表示的是字符串所在的內(nèi)存地址,當(dāng)我們把一個(gè)內(nèi)存地址賦值給一個(gè)char類型的時(shí)候自然就會(huì)報(bào)錯(cuò)了。
咦,不是說(shuō)好的是字符串么,怎么又扯到地址了?不要急,等后面講到指針的地方就明白了。
1.2 字符串的讀入
直接用字符串常量來(lái)初始化字符數(shù)組只是一種方式,另外一種常用的方式是只定義字符數(shù)組的長(zhǎng)度,從外部讀入數(shù)據(jù),
如:
char str[100];
scanf("%s", str);
cin >> str;
無(wú)論是使用scanf還是cin,都是一樣的效果。
但是沒(méi)有這么簡(jiǎn)單,比如我們?cè)賮?lái)看一段代碼:
char name[100];
char level[100];
scanf("%s", name);
scanf("%s", level);
在這段代碼當(dāng)中,我們定義了name和level兩個(gè)字符串變量。當(dāng)我們執(zhí)行的時(shí)候,就會(huì)發(fā)現(xiàn)問(wèn)題:

我剛輸入完名字,還沒(méi)來(lái)得及輸level就結(jié)束了。如果我們把name和level分別輸出的話就會(huì)發(fā)現(xiàn),name的值是liang,level的值是tang。
這說(shuō)明了什么?說(shuō)明了我們讀入字符串的時(shí)候它并不是按行讀入的,而是按照空格分隔的!它不像是隔壁的Python,input默認(rèn)就是讀入一行,C++的讀入默認(rèn)都是按照空格分隔的。
那問(wèn)題來(lái)了,假如我們需要讀入一行應(yīng)該怎么辦呢?也有辦法,我們可以使用cin.getline代替之前的scanf或者是cin。
我們來(lái)看下它的函數(shù)簽名:
istream& getline ( istream& is, string& str, char delim ); istream& getline ( istream& is, string& str );
C++允許參數(shù)列表不同的同名函數(shù)重載,這兩個(gè)簽名都是OK的。兩者的差別在于第三個(gè)參數(shù),但三個(gè)參數(shù)表示分隔符,如果不傳的話,默認(rèn)是'\n'。第二個(gè)參數(shù)表示字符串的長(zhǎng)度,所以如果要按照行來(lái)讀入字符串的話,剛剛的代碼應(yīng)該寫成:
cin.getline(name, 100); cin.getline(level, 100);
除了可以使用getline之外,還可以使用get。get有好幾種變體,一種變體是讀入一個(gè)字符,它有一種變體也可以讀入一行字符串。不過(guò)唯一的區(qū)別是,get函數(shù)不會(huì)處理行尾的換行符。如果我們要讀入兩行字符的話,需要手動(dòng)將這個(gè)換行符處理掉。
cin.get(name, 100); // 讀入一行數(shù)據(jù) cin.get(); // 讀入換行符 cin.get(level, 100);// 讀入第二行數(shù)據(jù)
寫成三行看起來(lái)有些繁瑣,我們還可以進(jìn)行簡(jiǎn)化,簡(jiǎn)化成一行:
cin.get(name, 100).get().get(level, 100);
看起來(lái)很像是Java8的流式編程,能夠這樣做的原因是get和getline函數(shù)會(huì)返回一個(gè)cin的對(duì)象。所以我們可以這樣連續(xù)調(diào)用。
相信有些同學(xué)已經(jīng)注意到了,同樣的函數(shù)名,根據(jù)我們傳入的參數(shù)不同執(zhí)行了不同的邏輯。這在C++當(dāng)中叫做函數(shù)重載,是一個(gè)非常重要的概念。
1.3 排坑
關(guān)于getline有一個(gè)比較大的坑,當(dāng)我們同時(shí)使用cin和getline的時(shí)候,有時(shí)候會(huì)出現(xiàn)問(wèn)題。
比如下面這段代碼:
int a; char name[100]; cin >> a; cin.getline(name, 100); cout << "a = " << a << endl; cout << "name = " << name << endl;
這段代碼很簡(jiǎn)單,我們定義了兩個(gè)變量。一個(gè)是int型的a,一個(gè)是字符串name。我們使用cin讀入a,使用getline讀入name。
這看起來(lái)一點(diǎn)問(wèn)題也沒(méi)有,但是當(dāng)我們運(yùn)行的時(shí)候就會(huì)出現(xiàn)問(wèn)題。

會(huì)發(fā)現(xiàn)我都沒(méi)有來(lái)得及輸入name,程序就結(jié)束了,而name讀到了一個(gè)空。
這并不是C++有bug,而是我們?cè)谳斎?2的時(shí)候,敲了一個(gè)回車。所以在使用getline讀入一行的時(shí)候,看到了回車,直接退出了,讀入了一個(gè)空行,這就是為什么我們沒(méi)有機(jī)會(huì)輸入name的原因。
要解決這個(gè)問(wèn)題怎么辦呢?其實(shí)也很簡(jiǎn)單,我們額外讀入一個(gè)字符,把換行符給讀取掉就行了。
int a; char name[100]; cin >> a; cin.get(); // getchar() C語(yǔ)言版本 cin.getline(name, 100); cout << "a = " << a << endl; cout << "name = " << name << endl;
類似的問(wèn)題在競(jìng)賽的題目當(dāng)中很常見(jiàn),我們經(jīng)常要同時(shí)讀入字符串和數(shù)字,很容易遇到這樣的問(wèn)題。遇到了不要緊張,仔細(xì)檢查一下數(shù)據(jù)和邏輯,看看是不是讀入到了換行符。
到此這篇關(guān)于C++中的字符串(1)的文章就介紹到這了,更多相關(guān)C++字符串內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
注:文章轉(zhuǎn)自微信公眾號(hào):Coder梁(ID:Coder_LT)
相關(guān)文章
C++ 詳細(xì)講解stack與queue的模擬實(shí)現(xiàn)
C++ Stack(堆棧) 是一個(gè)容器類的改編,為程序員提供了堆棧的全部功能,也就是說(shuō)實(shí)現(xiàn)了一個(gè)先進(jìn)后出(FILO)的數(shù)據(jù)結(jié)構(gòu),許多程序都使用了 queue 容器。queue 容器可以用來(lái)表示超市的結(jié)賬隊(duì)列或服務(wù)器上等待執(zhí)行的數(shù)據(jù)庫(kù)事務(wù)隊(duì)列2022-04-04
C++中利用cout和fstream采用非科學(xué)計(jì)數(shù)法輸出
這篇文章主要介紹了C++中利用cout和fstream采用非科學(xué)計(jì)數(shù)法輸出方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
C語(yǔ)言實(shí)現(xiàn)飛機(jī)游戲(進(jìn)階版)的示例代碼
在前文中,已經(jīng)帶大家利用C語(yǔ)言實(shí)現(xiàn)了簡(jiǎn)單的飛機(jī)游戲,但它還存在一些缺陷。因此,本文將給大家?guī)?lái)進(jìn)階版的飛機(jī)游戲,需要的可以參考一下2022-10-10
C語(yǔ)言詳解strcmp函數(shù)的分析及實(shí)現(xiàn)
strcmp函數(shù)語(yǔ)法為“int strcmp(char *str1,char *str2)”,其作用是比較字符串str1和str2是否相同,如果相同則返回0,如果不同,前者大于后者則返回1,否則返回-12022-05-05
C++實(shí)現(xiàn)LeetCode(15.三數(shù)之和)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(三數(shù)之和),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07

