第4章 C++字符串
第3章介绍了C语言字符串的相关内容,字符串的处理在程序中应用广泛,C语言字符串是以“\0”(空字符)作为结尾的字符数组。字符串是用来存储一个以上字符的非数字值的变量。在使用时,程序员需要考虑字符数组大小的开辟和结尾空字符的处理,使用起来有诸多不便。鉴于此,C++提供了string类用于字符串的处理。string类定义在头文件string中,注意和头文件cstring区分,cstring中定义的是一些对C语言字符串的处理函数。C++提供的string类不是一个基本的数据类型,但是在一般使用中与基本数据类型非常相似。
本章演示的实例都是有关C++字符串的,如字符串的基本操作、操作库函数实例,字符串查找比较实例和string字符串库函数运用实例。本章重点讲解字符串操作库函数实例和string字符串成员函数实际应用实例,初学者应反复多实践,加深理解。
4.1 操作字符串
案例4-1 把一个字符串截断(\0)
【案例描述】
在实际编程中,经常需要截断字符串。如读取图像头文件规定大小为30个字符,那么超过的就截断,可用函数如strtok()实现。但是如果知道结束字符'\0'的应用,实现起来就比较简单。本实例介绍'\0'的用法,效果如图4-1所示。
图4-1 把一个字符串截断(\0)
【实现过程】
程序先定义2个字符数组和2个字符串,在不同位置赋予'\0',测试输出的字符串;然后又定义4个字符串str1[80]等,提示用户输入并取得4个字符串,把这几个合并,并在6的位置赋予'\0',测试输出的字符串。代码如下:
#include<iostream>
#include<iostream.h>
int main()
{
int i;
//字符数组初始化并赋值
static char str10[8]={112,113,114,115,116,98};
static char str11[11]={'I',' ','a','m',' ','a',' ','b','o','y','\0'};
static char str12[8]="program";
static char str13[]="program";
str10[3]='\0';
for(i=0;i<8;i++)
cout<<str10[i]; //逐个输出字符数组的元素
cout<<endl;
str11[3]='\0';
for(i=0;i<11;i++)
cout<<str11[i]; //逐个输出字符数组的元素
cout<<endl;
str12[3]='\0';
for(i=0;i<8;i++)
cout<<str12[i]; //逐个输出字符串的字符
cout<<endl;
str13[3]='\0';
for(i=0;i<8;i++)
cout<<str13[i]; //逐个输出字符串的字符
cout<<endl<<endl;
cout<<str10;
cout<<endl;
cout<<str11;
cout<<endl;
cout<<str12;
cout<<endl;
cout<<str13;
cout<<endl;
static char str1[80],str2[80],str3[80],string[240];
cout<<"连续输入3个字符串:"<<endl;
cin>>str1>>str2>>str3;
cout<<"输入字符串为:"<<str1<<str2<<str3<<endl;
strcpy( string, str1 ); //strcpy复制一个字符串
strcat( string, str2 ); //strcat连接两个字符串
strcat( string, str3 );
string[6]='\0';
int len=strlen(string); //取字符串长度
for(i=0;i<len;i++)
cout<<string[i]; //逐个输出字符数组的元素
cout<<endl;
cout<<string<<endl;
system("pause");
return 0;
}
【案例分析】
(1)C++语言将字符串作为字符数组来处理。
(2)有了结束标志'\0'后就可知道结束,例如,str11[3]='\0';和string[6]='\0';,分别只能输出3个字符和6个字符。
注意:如果数组定义的长度大于字符串的长度,则内存中后面空的空间均为'\0'。如char c[10]="CHINA";,要注意的是,'\0'ASCII值为0,而' '(空格)ASCII值为32。
案例4-2 复制一个字符串(strcpy())
【案例描述】
下面的几个实例演示的是字符串函数的使用,这是编译器函数库提供的,按语法规定调用这些函数即可。本实例演示的是复制一个字符串,例如定义字符串a和b,如果a的值已存在,利用复制函数给b赋字符串同样的值。本例演示复制一个字符串函数strcpy()的用法,效果如图4-2所示。
图4-2 复制一个字符串(strcpy())
【实现过程】
第一个演示是demo1(),先复制一个字符串后连接两个字符串。第二个演示是demo2(),复制4个字符串,按规定格式输出。代码如下:
#include<iostream.h>
#include<iostream>
#include<string.h>
#include<iomanip.h>
void demo1( void )
{
char string[80]; //定义字符串
strcpy( string, "Hello world from " ); //strcpy复制一个字符串
strcat( string, "strcpy " ); //strcat连接两个字符串
strcat( string, "and " );
strcat( string, "strcat!" );
cout<<"String = %s\n"<<string;
}
#define N 4
void demo2()
{
int a,b,c,d;
char name[4][8];
for(a=1;a<=N;a++)
for(b=1;b<=N;b++)
{
if(a!=b)
for(c=1;c<=N;c++)
if(a!=c && b!=c)
{
d=10-a-b-c;
if((a==1)+(b==4)+(c==3)==1 &&
(b==1)+(a==4)+(c==2)+(d==3)==1 &&
(c==1)+(d==4)+(b==2)+(a==3)==1 &&
(b==4)+(a==3)==1)
{
strcpy(name[a-1],"Canada"); //strcpy复制一个字符串
strcpy(name[b-1],"America");
strcpy(name[c-1],"Russia");
strcpy(name[d-1],"China");
// cout <<"这时a="<<a<<",b="<<b<<",c="<<c<<",d= "<<d<<" .......\n";
//setiosflags(ios::left)左对齐
cout<<setiosflags(ios::left)<<setw(15)<<"The first :"
<<setw(10)<<name[0]<<endl;
//setw设置输出字符宽带
cout<<setw(15)<<"The second :"<<setw(10)<<name[1]<<endl;
cout<<setw(15)<<"The third :"<<setw(10)<<name[2]<<endl;
cout<<setw(15)<<"The last :"<<setw(10)<<name[3]<<endl;
}
}
}
}
int main()
{
demo1();
cout <<"\n"; //换行
demo2();
cout << "\n";
system("pause");
return 0;
}
【案例分析】
(1)函数strcpy()的原型为char * strcpy (char * dest, const char * src);,其功能是将字符串src的内容复制给字符串dest,并返回dest,也就是将第二个字符数组中的字符串复制到第一个字符数组中,将第一个字符数组中的相应字符覆盖。
(2)代码char string[80];strcpy(str1,str2);,执行结果为"Hello world from ",其功能是复制到数组string中。同样,strcpy(name[a-1],"Canada");,将字符串"Canada"复制到数组name[a-1]。
注意:代码中char string[80];,如果再加语句string = "Hello world from ";,编译器会出错。
案例4-3 获得字符串长度(strlen())
【案例描述】
在编程中常需要知道字符串的长度,如输入登录名和密码是否超过长度。本实例将多字符串连接在一起,测试输出字符串的长度;然后随机输入一个字符串并输出其长度;最后反序输出字符串。本例效果如图4-3所示。
图4-3 获得字符串长度(strlen())
【实现过程】
程序分两个演示。demo1()先复制一个字符串,然后连接两个字符串,再显示出长度和字符串;demo2()代码定义1个字符串str,输入后输出获得的字符串长度,再反序输出字符串。代码如下:
#include <iostream>
#include <string.h>
using namespace std;
void demo1( void )
{
char string[80];
int i1;
strcpy( string, "Hello world from " ); //strcpy复制一个字符串
strcat( string, "strcpy " ); //strcat连接两个字符串
strcat( string, "and " );
strcat( string, "strcat!" );
cout<<"连接后字符串:"<<string<<endl;
i1 = strlen(string); //获得字符串长度
cout<<"连接后字符串长度:"<<i1<<endl;
}
int demo2(void)
{
cout << "输入一个字符串: ";
char str[80]; //定义一个字符串
cin >> str;
//下面的代码反序输出字符串
int k;
k = strlen(str); //获得字符串长度
cout<<"获得字符串:"<<str<<endl;
cout<<"获得字符串长度:"<<k<<endl;
k--;
while(k>=0) { //反序输出
cout << str[k]; //输出一个字符
k--;
}
return 0;
}
int main()
{
demo1();
cout <<"\n"; //换行
demo2();
cout << "\n";
system("pause");
return 0;
}
【案例分析】
(1)函数strlen: size_t strlen (const char * string);,返回字符串的长度。函数参数为数组名,返回值为数组首字母到'\0'的长度,并非是数组在内存中空间的大小。代码char str[10]="China"; cout<<strlen(str);,输出的结果不是10,也不是6,而是5。运算符sizeof的格式为:sizeof (expression)。
(2)代码strcpy( string, "Hello world from " );,把字符串"Hello world from "赋值给string[80];,strcat( string, "strcpy " );连接两个字符串string和"strcpy ";,strlen(str);取字符串char str[80]的长度。
注意:知道字符串的长度后,在申请内存空间时,就知道实际占用内存空间的大小,在字符串连接赋值等操作中就不容易出错。
案例4-4 字符串的比较(strcmp())
【案例描述】
本实例演示strcmp()函数的用法,该函数用来比较字符串是否相同,例如,经常用于输入的密码对不对,一个单词是否出现在字符串中等。本实例将演示实现这些功能,效果如图4-4所示。
图4-4 字符串的比较(strcmp())
【实现过程】
程序分两个演示。demo1()定义1个字符串s[10],取得输入的密码,然后用比较函数strcmp,判断输入的密码是否正确;demo2()定义一个函数bsearch(char*list[],char obj[],int len),该函数的第一个输入参数为指针字符串,第二个是待查找单词,第三个是指向字符串数组数。其代码如下:
# include<iostream.h>
# include<iostream>
# include<string.h>
int demo1(void){
char s[10]; //定义一个字符串
cout<<"Enter password: "<<endl;
gets(s);
if(strcmp(s, "pass")) //字符串的比较
cout<<"密码不正确\n";
else
cout<<"密码正确\n";
return 1;
}
void bsearch(char*list[],char obj[],int len)
{
char** low,**high,**mid; //定义字符串
low=list;
high=list+len-1;
while(low<=high)
{
mid=low+(high-low)/2;
if(strcmp(*mid,obj)<0) //字符串的比较
low=mid+1;
else if(strcmp(*mid,obj)>0)
high=mid-1;
else
{cout<<"找到! 单词在字符串位置="<<mid-list+1<<endl;
return;
}
}
cout<<"未查到!"<<endl;
}
void demo2()
{
//定义字符串
char*a[10]={"aa","bbb","cccc","ddddd","eeeeee","fffffff"};
for (int i=0;i<6;i++) //输出每个单词
cout<<*(a+i)<<" ";
char c[20];
cout<<endl;
cout<<"请输入要查阅的字符串:";
cin>>c;
char *b; //定义字符串
b=c;
void (*s)(char*[],char*,int); //定义指针字符串
s=bsearch; //查阅单词
(*s)(a,c,6); //调用函数
}
int main()
{
demo1();
cout <<"\n"; //换行
demo2();
cout << "\n";
system("pause");
return 0;
}
【案例分析】
语句strcmp: int strcmp (const char* string1, const char* string2);用于比较两个字符串string1和string2的内容,函数对字符串中的每个ASCII字符两两进行比较,直到遇到不同的字符或'\0'为止。函数值由两个对应的字符相减而得,该函数具有返回值,返回值是两个字符串对应的第一个不同的ASCII码的差值。若两个字符串完全相同,函数值为0,如果字符串1>字符串2,则函数值为一个正整数。
代码中,void (*s)指向一个字符串*s,void*