[学习笔记]字符串的一些基本操作

字符串有很多操作,目前先不讲什么(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
",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<<'
';    //This is a example sentence.
	s.erase(10,8);
	cout<<s<<'
';    //This is an sentence.
	s.erase(s.begin()+9);
	cout<<s<<'
';    //This is a sentence.
	s.erase(s.begin()+5, s.end()-9);
	cout<<s<<'
';    //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++

原文地址:https://www.cnblogs.com/owencodeisking/p/9607942.html