C++中字符串String及字符操作方法


字符串的輸入方法

1、單個單詞能夠直接用std::cin,由於:std::cin讀取並忽略開頭全部的空白字符(如空格,換行符,制表符)。讀取字符直至再次遇到空白字符,讀取終止。

所以cin僅僅能讀取單個單詞。顯然能夠多次使用cin來獲取多個單詞;

2、多個單詞使用函數std::getline(std::cin, s)請看以下代碼:

 

#include <iostream>
#include <string> 
int main()
{
	std::string line; // empty string
	while(std::getline(std::cin, line))
	{
            // read line at time until end-of-file
	    std::cout << line << std::endl; // write s to the output
	}
    return 0;
}

Name: getline

 

這個函數接受兩個參數:一個輸入流對象和一個 string 對象。getline 函數從輸入流的下一行讀取,並保存讀取的內容到不包含換行符。和輸入操作符不一樣的是,getline 並不忽略行開頭的換行符。僅僅要 getline 遇到換行符,即便它是輸入的第一個字符,getline 也將停止讀入並返回。假設第一個字符就是換行符,則 string 參數將被置為空 string。

 

因為getline函數返回時丟棄換行符,換行符將不會存儲在string對象中。

 

Prototype: ssize_t getline (char **lineptr, size_t *n, FILE *stream)
Description:
This function reads an entire line from stream, storing the text (including the newline and a terminating null character) in a buffer and storing the buffer address in *lineptr. 
Before calling getline, you should place in *lineptr the address of a buffer *n bytes long, allocated  with malloc. If this buffer is long enough to hold the line, getline stores the line in this buffer.  Otherwise, getline makes the buffer bigger using realloc, storing the new buffer address back in  *lineptr and the increased size back in *n. . 
If you set *lineptr to a null pointer, and *n to zero, before the call, then getline allocates the initial buffer for you by calling malloc. 
In either case, when getline returns, *lineptr is a char * which points to the text of the line. 
When getline is successful, it returns the number of characters read (including the newline, but  not including the terminating null). This value enables you to distinguish null characters that are  part of the line from the null character inserted as a terminator. 
This function is a GNU extension, but it is the recommended way to read lines from a stream. The  alternative standard functions are unreliable. 
If an error occurs or end of file is reached without any bytes read, getline returns -1. Header files:stdio.h

String的操作方法

 

s.empty()

Returns true if s is empty; otherwise returns false
假設 s 為空串,則返回 true,否則返回 false。

 

 

s.size()

Returns number of characters in s
返回 s 中字符的個數

s[n]

Returns the character at position n in s; positions start at 0.
返回 s 中位置為 n 的字符,位置從 0 開始計數

 

【注意:1、引用下標時假設超出下標作用范圍就會引起溢出錯誤。相同不會報錯。2、索引的實際數據類型是類型 unsigned 類型string::size_type。

 

#include <iostream>
#include <string>

int main()
{
	std::string s = "hello world";
	std::cout<<s<<std::endl;
	for (std::string::size_type ix = 0; ix != s.size(); ++ix)
	s[ix] = '*';
    std::cout<<"Now s is:"<<s<<std::endl;
    std::cout<<"s's len is:"<<s.size()<<", s[12]="<<s[100]<<std::endl;
    return 0;
}

注意:循環中使用了std::string::size_type ix = 0;請使用string內置類型size_type來操作。由於int型可能不夠string的長度,所以內置類型size_type(實際能夠覺得是unsigned)被創建,保證各機器的兼容性,避免溢出(和下標溢出可不是一回事)。

 

不論什么存儲 string 的 size 操作結果的變量必須為 string::size_type 類型。特別重要的是,還要把 size 的返回值賦給一個 int 變量。

 

s1 + s2

Returns a string equal to the concatenation of s1 and s2
把 s1 和s2 連接成一個新字符串,返回新生成的字符串

 

【備注: 能夠連續加,和Python類似。

string s3 = s1 + ", " + s2 + "\n";。

注意:當進行 string 對象和字符串字面值混合連接操作時,+ 操作符的左右操作數必須至少有一個是 string 類型的【想象下級聯也就知道這確實是有道理的】。----1、也就是說+連接必須保證前兩個有一個為string類型!2、字符串字面值不能直接相加,字符串字面值和string是不同類型的,字符串里面沒有空字符'\0'。(更新於2014.06.24)】

 

s1 = s2

Replaces characters in s1 by a copy of s2
把 s1 內容替換為 s2 的副本

 

【備注:。它必須先把 s1 占用的相關內存釋放掉,然后再分配給 s2 足夠存放 s2 副本的內存空間,最后把 s2 中的全部字符拷貝到新分配的內存空間。

v1 == v2

Returns true if v1 and v2 are equal; false otherwise
比較 v1 與 v2 的內容,相等則返回 true,否則返回 false

!=, <, <=, >, and >=

Have their normal meanings
保持這些操作符慣有的含義

cctype Functions

 

我們常常要對 string 對象中的單個字符進行處理,比如。通常須要知道某個特殊字符是否為空白字符、字母或數字。下面 列出了各種字符操作函數。適用於 string 對象的字符(或其它不論什么 char 值)。這些函數都在cctype 頭文件里定義。

isalnum(c)

True if c is a letter or a digit.假設 c 是字母或數字,則為 True。

isalpha(c)

true if c is a letter.假設 c 是字母,則為 true。

iscntrl(c)

true if c is a control character.假設 c 是控制字符。則為 true

isdigit(c)

true if c is a digit.假設 c 是數字,則為 true。

isgraph(c)

true if c is not a space but is printable.假設 c 不是空格,但可打印,則為 true。

 

 

islower(c)

true if c is a lowercase letter.假設 c 是小寫字母,則為 true。

isprint(c)

True if c is a printable character.假設 c 是可打印的字符,則為 true。

【注意:可打印的字符是指那些能夠表示的字符】

ispunct(c)

True if c is a punctuation character.假設 c 是標點符號,則 true。

 

【注意:標點符號則是除了數字、字母或(可打印的)空白字符(如空格)以外的其它可打印字符】

isspace(c)

true if c is whitespace.假設 c 是空白字符。則為 true。

 

 

 

【注意:空白字符則是空格、制表符、垂直制表符、回車符、換行符和進紙符中的隨意一種】

isupper(c)

True if c is an uppercase letter.假設 c 是大寫字母。則 true。

isxdigit(c) 

 

true if c is a hexadecimal digit.假設是 c 十六進制數,則為 true。

tolower(c) 

 

If c is an uppercase letter, returns its lowercase equivalent; otherwise returns c unchanged.假設 c 大寫字母。返回其小寫字母形式,否則直接返回 c。

 

toupper(c)

 

If c is a lowercase letter, returns its uppercase equivalent; otherwise returns c unchanged.假設 c 是小寫字母,則返回其大寫字母形式。否則直接返回 c。

 

【注意:ctype.h是定義在C標准庫中的頭文件。cctype 事實上就是利用了 C 標准庫函數。C 標准庫頭文件命名形式為 name 而 C++ 版本號則命名為 cname ,少了后綴,.h而在頭文件名稱前加了 c 表示這個頭文件源自 C 標准庫。因此,cctype 與 ctype.h 文件的內容是一樣的,僅僅是採用了更適合 C++程序的形式。特別地,cname 頭文件里定義的名字都定義在命名空間 std 內,而 .h 版本號中的名字卻不是這樣。通常。C++ 程序中應採用 cname 這樣的頭文件的版本號,而不採用 name.h 版本號,這樣。標准庫中的名字在命名空間 std 中保持一致。

使用 .h 版本號會給程序猿帶來負擔,由於他們必須記得哪些標准庫名字是從 C 繼承來的,而哪些是 C++ 所特有的。】

字符串操作

下面總結更新於2014.10.01,來源於經典教材。

 

當中:s和str是字符串string,ca是一個字符數組,str_ca是一個字符串或者一個字符數組,str_ca_ch是一個字符串、字符數組或一個字符,ch是一個字符。n、n1、n2、pos1、pos2是整數。

長度操作

s.capacity()

返回s獲取的存儲容量;

s.size()/s.length()

返回s的長度;

s.empty()

假設s沒有包括字符則返回true。否則返回false;

s.max_size()

返回s可能的最大長度; 

編輯操作

s.append(str_ca)

將str_ca加入到s的結尾,返回s;

s.append(ca, n)

將ca的前n個字符加入到s的結尾,返回s;

s.append(n, ch)

將ch的n份拷貝加入到s的結尾,返回s;

s.insert(pos, str)

將str的拷貝插入到s的pos位置,返回s。

s.insert(pos1, str, pos2, n)

將str中從pos2位置開始的n個字符插入到s的pos1位置。返回s。【假設n大於str的長度。不會有問題。沒有溢出錯誤。僅僅會拷貝到str的末尾】

s.insert(pos, ca, n)

將ca的前n個字符插入到s的pos位置,假設n被省略,則插入ca中全部的字符到pos位置,返回s;

s.insert(pos, n, ch)

將字符ch的n個拷貝插入到s的pos位置。返回s;

s.erase(pos, n)

刪除s中從pos開始的n個字符(默認pos為0),返回s;

s.replace(pos1, n1, str)

將s中pos1位置開始的長度為n1的字符串替換為str【假設n1太大,從pos到s結尾的全部字符將被替換】。返回s;

s.replace(pos1, n1, ca, n2)

和上面一樣,僅僅只是取ca的前n2個字符。返回s;

s.swap(str)/swap(s, str)

交換s和str的內容分。返回為void。

復制操作

支持+  +=操作符。

s.assign(str_ca)

將str_ca的一份拷貝賦予s。返回s。

s.assign(ca, n)

將ca的前n個字符構成的字符串賦予s。返回s;

s.assign(n, ch)

將n個ch組成的字符串賦予s,返回s;

s.substr(pos, n)

返回s中從pos(默覺得0)開始的,有n個字符組成的s的子串的拷貝。

查找操作

s.find(str_ca_ch, pos)

返回s中第一個大於等於pos的位置,而且從這個位置的下一個字符開始s中字符和str_ca_ch中對應字符匹配。假設沒有這種位置則返回npos。pos默覺得0

s.find_first_of(str_ca_ch, pos)

返回s中大於等於pos的第一個和str_ca_ch中隨意字符匹配的字符的位置,假設沒有這種位置則返回npos,pos的默認值為0

s.find_first_not_of(str_ca_ch, pos)

返回s中大於等於pos的第一個和str_ca_ch中隨意字符都不匹配的字符的位置,假設沒有這種位置則返回npos。pos的默認值為0

s.find_last_of(str_ca_ch, pos)

返回s中小於等於pos的最大的一個和str_ca_ch中隨意字符匹配的字符的位置,假設沒有這種位置則返回npos,pos的默認值為0

s.find_last_not(str_ca_ch, pos)

返回s中小於等於pos的最大的一個和str_ca_ch中隨意字符都不匹配的字符的位置,假設沒有這種位置則返回npos,pos的默認值為0

s.rfind(str_ca_ch, pos)

返回s中最后一個小於等於pos的位置,而且從這個位置開始的str_ca_ch.size()個字符和str_ca_ch中對應的字符匹配。假設沒有這種位置則返回npos。pos默覺得npos

比較操作

支持上述 <、<=、>、>=、==、!=操作符。

s.compare(str_ca)

返回值為正、0、負

string和C風格字符串的轉換

s.c_str()

返回一個常字符數組。這個數組包括存儲在s中字符。以一個空字符結束;

s.data()

返回一個常字符數組。這個數組包括存儲在s中字符,但沒有以空字符結束。

s.copy(charArray, pos, n)

將charArray替換為s中從pos開始的n個字符,假設pos被省略了,即從0開始,假設n太大。那么拷貝字符直到s結束,返回終於拷貝的字符個數。

 

備注:data()和c_str()都能夠被用來從一個文件名稱中提取open操作所須要的字符數組,此部分內容可能會在興許文件操作中接觸到。

樣例

【此小節更新於2014.06.24】

原題在還有一篇博文中:C/C++中容器vector用法http://blog.csdn.net/zhanh1218/article/details/33323111

 

#include <iostream>
#include <string>
#include <vector>
using std::cin; using std::cout; using std::endl; using std::string; using std::vector;

string deal_word(string word)
{
	// 使用c++11 auto 語句 以及range for 語句
	for(auto &c : word)
	{
		if (not ispunct(c))
		{
			c = toupper(c); //連接非標點字符到字符串
		}
		else
		{
			word.erase(word.size()-1, 1); //僅僅能刪除最后一個標點符號。

 

有局限性!

} } return word; } string deal_word2(string word) { // 使用下標及c++11 decltype for (decltype(word.size()) index = 0; index != word.size(); ++index) { if (not ispunct(word[index])) { word[index] = toupper(word[index]); } else { word.erase(index, 1); // 刪除指定位置上的某一個字符。在此為標點 index -= 1; //保證下標不越界!

重要!

} } return word; } int main() { string word; // 緩存輸入的單詞 vector<string> text; // empty vector cout<<"Please input the text:"<<endl; //提示輸入 while (std::cin >> word and word != "INPUTOVER") // INPUTOVER 用於標示輸入結束,也能夠ctrl + z停止輸入 { word = deal_word(word); // 單詞處理 text.push_back(word); // append word to text } for(std::vector<int>::size_type ix =0, j = 0; ix != text.size(); ++ix, ++j) { if (j==8) // 8個單詞一行 { cout<<endl; //換行 j = 0; //又一次計數 } cout<<text[ix]<<" "; //加空格。 } return 0; }

 

改寫了兩種處理單詞的方法。

 

使用了c++11中的新特性!

【更新於2014.06.05,一直忽視了for循環中不要增刪迭代器中內容的問題。這個確實不優點理,還是選擇復制吧(也就是原來的方法)!

 

錯誤概率低,可讀性強。效率上還有待考證。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM