[學習筆記]字符串的一些基本操作


字符串有很多操作,目前先不講什么\(KMP\),\(AC\)自動機之類的高端算法。我感覺字符串的操作對於\(OIer\)們比較薄弱,特別是轉\(C++\)\(P\)黨們

便於本文閱讀,開頭省略以下代碼:

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
using namespace std;

並且考慮到閱讀體驗,輸入輸出將不用\(latex\)

字符串的輸入輸出的一些常見誤區

\(string\)類型一般都是用\(cin\)讀入。

\(char\)類型用\(cin\),\(scanf\)或者\(sscanf\)讀入

一般字符串的題目都是模擬題,所以不用怕\(cin\)超時

1、\(cin\) 作用:讀到空格,\(Tab\),回車就結束讀入

\(char\)版:

int main()
{
	char s[20];
	cin>>s;
	cout<<s<<endl;
	return 0;
}

\(string\)版:

int main()
{
	string s;
	cin>>s;
	cout<<s<<endl;
	return 0;
}

\(Input\):abc def

\(Output\):abc

2、\(scanf\) 作用:同\(cin\)

\(char\)版:

int main()
{
	char s[20];
	scanf("%s",s);
	printf("%s\n",s);
	return 0;
}

\(Input\):abc def

\(Output\):abc

3、\(getline\) 作用:讀入整行字符串,碰到換行退出

\(string\)版:

int main()
{
	string s;
	getline(cin,s);
	cout<<s<<endl;
	return 0;
}

\(Input\):abc def

\(Output\):abc def

4、\(cin.get\) 作用:讀入單個字符,類型必須是\(char\)

int main()
{
	char s;
	s=cin.get();
	cout<<s<<endl;
	return 0;
}

\(Input\):abc def

\(Output\):a

5、\(getchar\) 作用:讀入單個字符,類型必須是\(char\)

int main()
{
	char s;
	s=getchar();
	cout<<s<<endl;
	return 0;
}

\(Input\):abc def

\(Output\):a

輸出有幾種方式,\(cout\),\(printf\),\(putchar\),不過我覺得\(gets\)\(puts\)要盡量少用,有些題目用\(gets\)會因為\(Linux\)的一些原因導致程序\(WA\)

順帶提一句,除\(puts\)會輸出自動換行,其他三種輸出方式不會自動換行

正文

筆者羅列了一下字符串的基本操作:

字符串操作:賦值,復制,連接,比較,清空

字符串性質:求串長,求子串,查找子串,刪除,替換,插入

字符串狀態:判定串是否為空

那么我們從字符串的操作講起吧

1、賦值

(1) \(=\)

單個字符用單引號'',多個字符用雙引號""

int main()
{
	char s1[20]="What?!",s2='W';
	cout<<s1<<" ";
	cout<<s2<<endl;
	return 0;
}

\(Output\): What?! W

(2)\(push_back\)

這是\(string\)特有的,因為直接賦值單字符''會\(CE\),用法即在字符串末尾添加一個字符

int main()
{
	string s;
	s.push_back('W');
	cout<<s<<endl;
	return 0;
}

\(Output\):W

(3) \(memset\)

memset(s,c,len) 將字符串\(s\)\(len\)的字符初始化為\(char\)類型\(c\)

int main()
{
	char s[20];
	memset(s,'0',sizeof(s)+1);//不+1結尾會輸出一個問號
	cout<<s<<endl;
	return 0;
}

\(Output\):0000000000000000000

2、復制

\(char\)類型:

(1) \(memcpy\)

memcpy(s1,s2,len) 將\(s2\)復制\(len\)長度到\(s1\)

int main()
{
	char s1[20],s2[20]="What?!",s3[20]="Aha!";
	memcpy(s1,s2,strlen(s2)+1);//將s2復制到s1
	cout<<s1<<" ";
	memcpy(&s1,&s3,sizeof(s3));;//將s3復制到s1
	cout<<s1<<endl;
	return 0;
}

\(Output\): What?! Aha!

(2) \(strcpy\)

strcpy(s1,s2) 將\(s2\)復制到\(s1\)

int main()
{
	char s1[20],s2[20]="What?!";
	strcpy(s1,s2);//將s2復制到s1
	cout<<s1<<" ";
	strcpy(s1,"Aha!");//將"Aha!"復制到s1
	cout<<s1<<endl;
	return 0;
}

\(Output\): What?! Aha!

(3)\(strncpy\)

strncpy(s1,s2,len) 將\(s2\)復制\(len\)長度到\(s1\)

int main()
{
	char s1[20]={0},s2[20]={0},s3[20]="What?!";//這里不初始化會出現奇怪的東西
	strncpy(s1,s3,sizeof(s3));//將s3復制到s1
	cout<<s1<<" ";
	strncpy(s2,s3,4);//將s3開始的4個字符復制到s2
	cout<<s2<<endl;
	return 0;
}

\(Output\): What?! Aha!

\(string\)類型:

(1) \(=\)

直接等於另一個字符串

int main()
{
	string s1,s2="What?!";
	s1=s2;
	cout<<s1<<endl;
	return 0;
}

\(Output\):What?!

(2) \(copy\)

s1.copy(s,len,s) 復制\(s1\)\(l\)個位置,長度為\(len\)到字符串\(s\),但是\(s\)\(char\)類型

int main()
{
	string s1="Code is King";
	char s[6];s1.copy(s,7,5);
	cout<<s<<endl;
	return 0;
}

如果定義字符數組大於所要\(copy\)的長度,會出現奇怪的東西,所以要手動算長度

3、連接

\(char\)類型:

(1)\(strcat\)

strcat(s1,s2) 在\(s1\)后拼接\(s2\)

int main()
{
	char s1[20]="Code is",s2[20]=" King";
	strcat(s1,s2);//在s1后拼接s2
	cout<<s1<<endl;
	return 0;
}

\(Output\):Code is King

(2)\(strncat\)

strncat(s1,s2,len) 在\(s1\)后面拼接\(s2\)的前\(len\)個字符

int main()
{
	char s1[20]="Code is",s2[20]=" King Code";
	strncat(s1,s2,5);//在s1后面接上s2開始的5個字符
	cout<<s1<<endl;
	return 0;
}

\(Output\):Code is King

\(string\)類型:

(1) +=

由於\(string\)里面有\(operator\),所以直接\(+=\)就行了

int main()
{
	string s1="Code is",s2=" King";
	s1+=s2;//直接接上
	cout<<s1<<endl;
	return 0;
}

\(Output\):Code is King

4、比較

\(char\)類型:

(1) \(strcmp\)

strcmp(s1,s2) 若s1>s2,返回一個正數;若s1==s2,返回\(0\),若s1<s2 返回一個負數

怎么判定一個串比較和另一個串的大小呢?\(C++\)是比較第一次失配時兩個字符\(ASCLL\)碼的大小,一個串是另一個串的前綴,那么另一個串大

int main()
{
	char s1[20]="Code is King";
	char s2[20]="Code is King";
	char s3[20]="Code is Queen";
	cout<<strcmp(s1,s2)<<" ";//比較大小
	cout<<strcmp(s1,s3)<<endl;
	return 0;
}

\(Output\):0 -1

(2) \(strncmp\)

strncmp(s1,s2,len) 比較\(s1\)\(s2\)的前\(len\)個字符,若s1>s2,返回一個正數;若s1==s2,返回\(0\),若s1<s2 返回一個負數

int main()
{
	char s1[20]="Code is King";
	char s2[20]="Code is Queen";
	cout<<strncmp(s1,s2,8)<<" ";//比較s1和s2的前8個字符
	return 0;
}

\(Output\):0

\(string\)類型

(1) \(>\ =\ <\)

原理同\(string\)中的\(=\),比較方式同\(strcmp\)

int main()
{
	string s1="Code is King";
	string s2="Code is King";
	string s3="Code is Queen";
	if(s1==s2) cout<<0<<" ";//直接比較
	else cout<<-1<<" ";
	if(s2==s3) cout<<0<<endl;
	else cout<<-1<<endl;
	return 0;
}

\(Output\):0 -1

5、清空

\(char\)類型: 可以直接一位一位賦值,或者直接\(memset\),用法略

\(string\)類型:

(1) \(clear\)

s.clear() 清空原串

int main()
{
	string s="Code is King";
	s.clear();//清空
	cout<<s<<endl;
	return 0;
}

\(Output\):啥都不輸出

(2) 直接等於一個空串,用法略

接下來就是字符串性質

1、求串長

\(char\)類型:

(1) \(strlen\)

strlen(s) 返回字符串\(s\)的長度

int main()
{
	char s[20]="Code is King";
	cout<<strlen(s)<<endl;//求s的長度
	return 0;
}

\(Output\):12

\(string\)類型:

(1) \(s.length\)

s.length() 返回字符串\(s\)的長度

int main()
{
	string s="Code is King";
	cout<<s.length()<<endl;//求s的長度
	return 0;
}

\(Output\):12

\(Tips\):如果你平常用這種方法寫輸出請改一下

for(int i=0;i<strlen(s);i++)
		cout<<s[i];
	cout<<endl;

因為每一次都要算一個\(strlen\),所以復雜度成為了\(O(n^2)\)

2、求子串

\(char\)類型:直接\(strnpy\),用法略

\(string\)類型:

(1) \(s.substr\)

s,substr(l,len) 復制串\(s\)從第\(l\)個字符開始\(len\)長度的串
s.substr(l) 復制串\(s\)到末尾

int main()
{
	string s1="Code is King";
	string s2=s1.substr(5,7);//復制從第5個字符開始的7個字符
	string s3=s1.substr(5);//復制從第5個字符開始直到末尾
	cout<<s2<<" ";
	cout<<s3<<endl;
	return 0;
}

\(Output\):is King is King

3、查找子串

\(char\)類型

(1) \(strstr\)

strstr(s1,s2) 查找\(s2\)\(s1\)第一次中指針地址,若找不到,指針地址為\(end\)

int main()
{
	char s[20]="Code is King";
	char *p=strstr(s,"is");//在s中查找is並返回指針
	cout<<p<<endl;
	return 0;
}

\(Output\):is King

(2) \(strnstr\) 反向查找\(s2\)\(s1\)第一次的指針地址,若找不到,指針地址為\(end\),用法略

\(string\)類型:

(1) \(find\)

s.find(s1) 查找串\(s1在串\)s\(中\)第一次出現的位置,若找不到,值為\(s.end()\)

int main()
{
	string s="Code is King";
	int find=s.find("is");//查找s中的is
	cout<<find<<endl;
	return 0;
}

\(Output\):5

(2) \(rfind\)

s.rfind(s1) 反向查找串\(s1在串\)s\(中\)第一次出現的位置,若找不到,值為\(s.end()\)

int main()
{
	string s="Code is King";
	int find=s.rfind("is");//反向查找is
	cout<<find<<endl;
	return 0;
}

\(Output\):5

4、刪除

\(string\)類型:

(1) \(erase\)

s,erase(l,len) 刪除串\(s\)從第\(l\)個字符開始\(len\)長度的串

s.erase(l) 刪除第\(l\)個字符

s.erase(l,r) 刪除\([l,r]\)區間內的字符

int main() 
{
	string s="This is an example sentence.";
	cout<<s<<'\n';    //This is a example sentence.
	s.erase(10,8);
	cout<<s<<'\n';    //This is an sentence.
	s.erase(s.begin()+9);
	cout<<s<<'\n';    //This is a sentence.
	s.erase(s.begin()+5, s.end()-9);
	cout<<s<<'\n';    //This sentence.
	return 0;
}

\(Output\):

This is a example sentence.

This is an sentence.

This is a sentence.

This sentence.

\((Code\ By\ Reference\ C++)\)

5、替換

\(string\)類型:

(1) \(replace\)

s.replace(l,len,s1) 將串\(s\)中第\(l\)個字符開始\(len\)長度替換為串\(s1\)

s.replace(l1,len1,s1,l2,len2) 將串\(s\)中第\(l1\)個字符開始\(len1\)長度替換為串\(s1\)中第\(l2\)個字符開始\(len2\)長度

s.replace(l1,len1,s1,len2) 將串\(s\)中第\(l1\)個字符開始\(len1\)長度替換為串\(s1\)\(len2\)長度

s.replace(l1,len1,len2,c) 將串\(s\)中第\(l1\)個字符開始\(len1\)長度替換為\(len2\)\(c\)字符 \(c\)\(char\)類型

int main()
{
	string base="this is a test sing.";
	string s2="n example";
	string s3="sample phrase";
	string s4="useful.";
	// Using positions:     
	sing s=base;           // "this is a test sing."
	s.replace(9,5,s2);          // "this is an example sing." (1)
	s.replace(19,6,s3,7,6);     // "this is an example phrase." (2)
	s.replace(8,10,"just a");     // "this is just a phrase."     (3)
	s.replace(8,6,"a shorty",7);  // "this is a short phrase."    (4)
	s.replace(22,1,3,'!');        // "this is a short phrase!!!"  (5)
	// Using iterators: 
	s.replace(s.begin(),s.end()-3,s3);                    // "sample phrase!!!"      (1)
	s.replace(s.begin(),s.begin()+6,"replace");             // "replace phrase!!!"     (3)
	s.replace(s.begin()+8,s.begin()+14,"is coolness",7);    // "replace is cool!!!"    (4)
	s.replace(s.begin()+12,s.end()-4,4,'o');                // "replace is cooool!!!"  (5)
	s.replace(s.begin()+11,s.end(),s4.begin(),s4.end());// "replace is useful."    (6)
	cout<<s<<endl;
	return 0;
}

\(Output\):replace is useful

\((Code\ by\ Reference\ C++)\)

6、插入

\(string\)類型:

(1) \(insert\)

s.insert(l,s1) 將串\(s1\)插入到串\(s\)\(l\)個字符后

s.insert(l1,s1,l2,len) 將串\(s1\)\(l2\)個字符開始\(len\)長度插入到串\(s\)\(l1\)個字符后

s.insert(l,s1,len) 將串\(s1\)\(len\)個字符插入到串\(s\)\(l\)個字符后

s.insert(l,len,c) 將串\(s\)\(l\)個字符后插入\(len\)\(c\)字符 \(c\)\(char\)類型

int main()
{
	string s="to be question";
	string s2="the ";
	string s3="or not to be";
	string::iterator it;
	s.insert(6,s2);                 // to be (the )question
	s.insert(6,s3,3,4);             // to be (not )the question
	s.insert(10,"that is cool",8);    // to be not (that is )the question
	s.insert(10,"to be ");            // to be not (to be )that is the question
	s.insert(15,1,':');               // to be not to be(:) that is the question
	it = s.insert(s.begin()+5,','); // to be(,) not to be: that is the question
	s.insert(s.end(),3,'.');       // to be, not to be: that is the question(...)
	s.insert(it+2,s3.begin(),s3.begin()+3); // (or )
	cout<<s<<endl;
	return 0;
}

\(Output\): to be, or not to be: that is the question...

\((Code\ by\ Reference\ C++)\)

最簡單的字符串狀態留在最后

1、是否為空

\(string\)類型:

(1) \(empty\)

s.empty() 判定串\(s\)是否為空串,是返回\(1\),不是返回\(0\)

int main()
{
	string s1="Code",s2;
	if(!s1.empty()) cout<<1<<" ";
	else cout<<0<<" ";
	if(!s2.empty()) cout<<1<<endl;
	else cout<<0<<endl;
	return 0;
}

\(Output\):1 0

當然\(string\)里面還有一些函數如\(append\),\(assign\),筆者就不在此贅筆了

參考網站:

C++中輸入字符串的幾種方法

Reference-C++


免責聲明!

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



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