一、字符串

1.计算char数组本身的长度——sizeof()

示例

1
2
3
4
5
6
7
8
9
10
11
12
char a[]="hello";
char b[]={'h','e','l','l','\0'};
char c[]={'h','e','l','l'};
cout<<sizeof(a)<<endl;
cout<<sizeof(b)<<endl;
cout<<sizeof(c)<<endl;


输出:
6
5
4

2.计算字符串的长度——strlen()

示例

1
2
3
4
5
6
7
8
9
char a[100]="hello";
int len1=strlen(a); //strlen函数有返回值
int len2=strlen("hello");
cout<<len1<<endl;
cout<<len2<<endl;

输出:
5
5

注意:

  1. strlen仅仅是一个计数器的功能,遇到空字符串’\0’则停止计算,strlen返回第一个’\0\之前的字符长度

  2. strlen只计算可见的字符,而不把空字符计算在内

  3. strlen()函数返回的是储存在数组中的字符串的长度,而不是数组本身的长度

当你是在想不起来该用啥求字符串长度的时候,直接for循环也是可取的(这种方法也是遍历字符串的方法之一)

1
2
3
4
5
char a[100];
cin>>a;
int i=0;
for(int i=0;a[i]!='\0';i++){}
cout<<"长度为"<<i;

3.字符串输入输出

首先是大家最熟悉的cin和cout,要注意的是cin的使用需要附上iostream库并且加上语句 using namespace std

使用cin读入字符串只写char数组的名字就行

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<iostream>
using namespace std;
char a[105],b[10][105],c[105];
int main()
{
cin>>a; //读入一个字符串
for(int i=1;i<=10;i++)cin>>b[i]; //读入10个字符串
cout<<a<<endl;
for(int i=1;i<=10;i++)cout<<b[i]<<endl;
scanf("%s",c); //scanf读入字符串和cin效果基本一样
printf("%s",c); //printf读入字符串和cout效果基本一样
return 0;
}

要注意的是cin读入到空格或者换行符就会停止

如果要读入一整行(包括空格),请使用getline函数(还有一个get()函数,这里不统一说了,感兴趣的自己去查)

1
2
3
4
5
6
7
8
9
10
11
12
#include<iostream>
using namespace std;
char a[105];
int main()
{
cin.getline(a,106);
//第二个参数是读入长度,根据具体情况来,一般推荐设置为char数组长度+1
//如果设置读入长度大于输入长度,getline会读入到换行符并忽略换行符
//getline实际读取的字符串长度为设置的读入长度-1,因为他在读入末尾自动帮你加了个\0
cout<<a;
return 0;
}

4.字符串拼接——strcat

把字符串p和q拼起来中间再加个字符x(原始写法):

1
2
3
4
5
6
7
8
9
10
char * mystrstr(char *p,char *q,char x)
{
char *tmp=new char;
char *out=tmp;
for(;*p!='\0';p++){*tmp=*p;tmp++;}
*tmp=x;tmp++;
for(;*q!='\0';q++){*tmp=*q;tmp++;}
*tmp='\0'; //千万别忘了,不然会出乱码
return out;
}

如果你懒,你可以用cstring库里的strcat函数:

strcat(S,T)函数将会把T拼接到S上,然后返回S

要注意的是这里的S和T都是char指针,如果要拼接字符上去,请在变量名前加上’&'符号

例如:

1
2
3
4
cin>>p>>x>>q;
strcat(p,&x);
strcat(p,q);
cout<<p;

说明:

strstr(T,S)是一个字符串处理函数,用于判断字符串S是否是字符串T的子串。如果是,则该函数返回S在T中首次出现的地址;否则,返回NULL。

头文件:#include <string.h>

函数原型:char *strstr(const char *str1, const char *str2);

返回值:(1) 成功找到,返回在父串中第一次出现的位置的 char *指针 (2) 若未找到,即不存在这样的子串,返回 NULL。

5.字符串复制——strcpy

函数原型:

1
char * strcpy ( char * destination, const char * source );

其中distination指针指向容器字符串,source指针指向被复制的字符串

例如:

1
2
3
4
5
6
7
8
9
10
11
12
#include <cstdio>
#include <cstring>
int main ()
{
char str1[]="Sample string";
char str2[40];
char str3[40];
strcpy (str2,str1);
strcpy (str3,"copy successful");
printf ("str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);
return 0;
}

输出:

1
2
3
str1: Sample string
str2: Sample string
str3: copy successful

6.字符串查找——strstr

函数原型:

1
char *strstr (const char *s1, const char *s2);

此函数返回一个指针,该指针指向s1中找到的s2的第一个字符,如果s1中不存在s2,则返回空指针。如果s2指向空字符串,则返回s1

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <cstring> 
#include <cstdio>
int main()
{
char s1[] = "GeeksforGeeks";
char s2[] = "for";
char* p;
p = strstr(s1, s2);
if(p)
{
printf("String found\n");
printf("First occurrence of string '%s' in '%s' is '%s'", s2, s1, p);
}
else printf("String not found\n");
return 0;
}

输出:

1
2
String found
First occurrence of string 'for' in 'GeeksforGeeks' is 'forGeeks'

7.字符串比较——strcmp

1
int strcmp(const char *str1, const char *str2)

str1字典序小于str2时,返回值小于0

str1字典序大于str2时,返回值大于0

str1字典序等于str2时,返回值等于0

二、其他常见代码段

1.结构体排序

【例题背景】将Mystruct按score从小到大排序,若score相同则按name字典序从小到大排序

基础冒泡排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <cstdio>
#include <cstring>
struct Mystruct
{
char name[105];
int score;
}a[105];
int n;
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%s%d",a[i].name,&a[i].score);
for(int i=0;i<n;i++)
for(int j=1;j<n-i;j++)
if(a[j].score<a[j-1].score)
{
Mystruct tmp;
tmp=a[j];
a[j]=a[j-1];
a[j-1]=tmp;
}
else if(a[j].score==a[j-1].score)
{
if(strcmp(a[j].name,a[j-1].name)<0)
{
Mystruct tmp;
tmp=a[j];
a[j]=a[j-1];
a[j-1]=tmp;
}
}
for(int i=0;i<n;i++)printf("%s %d\n",a[i].name,a[i].score);
return 0;
}

进阶sortsort排序(需要algorithmalgorithm库)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Mystruct
{
char name[105];
int score;
}a[105];
bool cmp(const Mystruct a,const Mystruct b)
{
if(a.score==b.score)return strcmp(a.name,b.name)<0;
return a.score<b.score;
}
int n;
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%s%d",a[i].name,&a[i].score);
sort(a,a+n,cmp);
for(int i=0;i<n;i++)printf("%s %d\n",a[i].name,a[i].score);
return 0;
}

终极重载运算符(需要algorithm库)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Mystruct
{
char name[105];
int score;
bool operator < (const Mystruct b)const{
if(score==b.score)return strcmp(name,b.name)<0;
return score<b.score;
}
}a[105];
int n;
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%s%d",a[i].name,&a[i].score);
sort(a,a+n);
for(int i=0;i<n;i++)printf("%s %d\n",a[i].name,a[i].score);
return 0;
}

重载运算符代码通用结构:

1
2
3
4
bool operator [你要重载的运算符] (const [比较对象的变量类型] [起个好听的变量名] )const
{
return [ [当前所在的结构体内的某个变量] 和 [比较对象的比较量] 的关系式 ]
}

2.序列求最大值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<cstdio>
#include<iostream>
using namespace std;
int a[1005],n;
int find_max(int a[])
{
int maxx=0;
for(int i=0;i<n;i++)
maxx=max(maxx,a[i]);
return maxx;
}
int find_min(int a[])
{
int minn=0x7fffffff; //七个f。这是十六进制表示,代表了int的上限
for(int i=0;i<n;i++)
minn=min(minn,a[i]);
return minn;
}
int main()
{
for(int i=0;i<n;i++)cin>>a[i];
cout<<find_max(a)<<" "<<find_min(a);
return 0;
}

3.不限行数输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<cstdio>
#include<iostream>
using namespace std;
char a[1005];
int main()
{
while(cin>>a)
//或者写成scanf形式
//while(~scanf("%s",a))
{
cout<<a;
}
return 0;
}

4.一次读入一整行

使用getline函数读入char数组的方法上面已经说过了,这里补充强调一下,如果要把getline和cin一起使用的话,请加上清空输入缓冲区的函数

请看示例:

1
2
3
4
5
6
7
8
9
10
11
12
#include<cstdio>
#include<iostream>
using namespace std;
char a[1005];
int n;
int main()
{
cin>>n;
cin.getline(a,1000);
cout<<n<<"\n"<<a;
return 0;
}

大家会发现这段代码里getline就和没写一样。原因是cin在读入nn时只拿走了nn的值,而没有拿走换行符,所以getline一读入换行符就结束了,和没有一样

这时候我们需要这样写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<cstdio>
#include<iostream>
using namespace std;
char a[1005];
int n;
int main()
{
cin>>n;
cin.clear(); //清空输入流标识符,确保可以输入
cin.sync(); //清空输入流
cin.getline(a,1000);
cout<<n<<"\n"<<a;
return 0;
}

这样就可以正常执行了