字符串.docx
《字符串.docx》由会员分享,可在线阅读,更多相关《字符串.docx(34页珍藏版)》请在冰豆网上搜索。
![字符串.docx](https://file1.bdocx.com/fileroot1/2023-1/23/237ea1ed-8f42-43e2-89c6-c9dfabcd3acb/237ea1ed-8f42-43e2-89c6-c9dfabcd3acb1.gif)
字符串
C++全方位学习——字符串(更新中,别断楼)
[i=s]本帖最后由隨風∞流逝于2010-1-2619:
52编辑[/i]
内容比较多
我先把目录给列出来吧
char型字符串
string型字符串
string型字符串的赋值
string型字符串的合并
string型字符串的部分合并
string型字符串的替换
string型字符串的复制
string型字符串的插入
string型字符串的删除
string型字符串的查找
string型字符串的比较
判断string型字符串是否为空
字符串的使用
swap()交换两个字符串的内容
将string型字符串转换为char型字符串
char型字符串与函数
函数如何返回字符串
结构体
结构体的赋值
结构体与函数
结构体与string
string数组与函数
流的使用
重载输出运算符<<
友元的方式重载输出运算符
重载自加运算符的执行次序
重载输入运算符>>
编写一个string类
创建string类
创建可自动调节大小的string类字符串对象
限制数组越界
用复制构造函数实现字符串的赋值功能
用重载赋值运算符函数实现真正的字符串赋值功能
用重载输出运算符operator<<()函数实现字符串的输出
用重载输入运算符operator>>()函数实现字符串的输入
用重载比较运算符实现字符串的比较
为string类添加字符串的相加功能
为string类添加字符串的+=功能
完成后的string类
隨風∞流逝发表于2010-1-2519:
53
字符串是以空字符结尾的字符数组。
char型字符串
由于char占用一个字节的空间,为了让char能够存储更多的字符,我们用了数组的方式。
如:
charman[4]={'J','A','C','K'};
然而该char行数组man却不是一个字符串,因为它没有字符串的结束表示——"\0"。
只有我们为其添加"\0"这个结束标志后,这个char型数组man才能转化为字符串,如:
charman[5]={'J','A','C','K','\0'};
"\0"是一个空字符表示,它的ASCII码为0,C++有好多处理字符串的函数,它们都以"\0"为结束标示,也就是以空字符为结束标志,如cin和cout,它们也是以空字符为结束标志,它们在碰到空字符后将会停止输入或输出,如:
[code]#include
usingnamespacestd;
int_tmain(intargc,_TCHAR*argv[])
{
charman[12];
cin>>man;
cout<system("pause");
return0;
}[/code]输出:
helloworld
hello
分析:
第3行我们定义了一个存储12个字符的char型数组man,第6行用数组man来保存用户输出,我们输入了10个字符helloworld,由于cin遇到空字符就停止输入,而我们在输入world时空了一格,因此我们看到输出的结果只是hello。
可使用cin.get解决这一问题。
程序代码如下:
[code]#include
usingnamespacestd;
int_tmain(intargc,_TCHAR*argv[])
{
charman[12];
cin>>man;
cin.get(man,12);
system("pause");
return0;
}[/code]cin.get的结束标志是"\n",也就是换行,因此语句遇到空格不会结束,而是把空格也看做一个字符,同时在输入结束后,也就是用户输入一个回车后,cin.get自动为当前接受输入的数组添加字符串结束标志"\0",因此它实际保存的有效字符是它的第2个参数减1,在本例中是(12-1)11个字符。
同样,输出也是这样,假如我们在一行字符串的中间放了0,如:
[code]#include
usingnamespacestd;
int_tmain(intargc,_TCHAR*argv[])
{
charman[]={'H','e','l','l','o','0','W','o','r','l','d'};
cout<system("pause");
return0;
}[/code]空字符的ASCII码为0,我们在字符型数组中输入了一个不加引号的0,编译器就会根据ASCII码值来寻找字符,ASCII码值为0的字符是NULL字符,也就是空字符,cout遇到空字符就会停止输出,因此0后面的字符没有输出,只输出了Hello。
要解决这个问题,也就是想要存储一个,则必须将空格作为一个字符来录入,如:
[code]#include
usingnamespacestd;
int_tmain(intargc,_TCHAR*argv[])
{
charman[12]={'H','e','l','l','o','','W','o','r','l','d'};
cout<system("pause");
return0;
}[/code]输出HelloWorld
分析:
第5行字符o后面的两个单引号''中间是一个空格,由于用单引号括了起来,因此编译器会把这个空格当做字符串存储在char型数组man中,而不是当做空字符。
虽然像第5行那样逐个字符地录入是可行的,但是写起来太麻烦,而且很容易看错位置,导致输入出错。
C++提供了一种简便的方式来替代第5行,如:
charman[12]={"Helloworld"};
用双引号包括起来的字符串隐含了字符串结束标志"\0",因此你不用动手去添加它。
这样的写法明显要比第5行省事多了。
你也可以省略定义字符串的长度,而把这个任务交给编译器去完成,如:
charman[]={"Helloworld"};
编译器会自动根据双引号内字符的个数定义字符串的长度。
假如你不知道具体要存放多少个字符,那么你可以将数组长度定义得大一点,如:
charman[99];
这样,即可以防止在要存储的字符很多时,超出数组末尾写入数据,也就是数组越界。
这样做的坏处就是浪费空间,因此处理字符串的函数根据空字符的位置,而不是字符的长度来进行处理,所以你为字符数组man多开辟出来的那些内存空间除了耗费系统内存之外没有什么实际用途。
另外,C++不限制字符串的长度,也就是说可以将字符串数组的长度定义为无限大。
最好,我们在计算字符串长度时,不要忘记最后的空字符"\0".
计算字符串长度及大小的程序代码如下:
[code]#include
usingnamespacestd;
int_tmain(intargc,_TCHAR*argv[])
{
charman[12]={"Helloworld"};
cout<cout<<"strlen(man):
"<cout<<"sizeof(man):
"<man[5]='\0';
cout<cout<<"strlen(man):
"<cout<<"sizeof(man):
"<system("pause");
return0;
}[/code]输出:
Helloworld
strlen(man):
11
sizeof(man):
12
Hello
strlen(man):
5
sizeof(man):
12
分析:
第5行定义了一个字符串数组man,它保存了包括空格在内的11个字符和一个用来表示字符串结束的"\0".这样一共是12个字符,但是第7行输出strlen函数返回的字符串长度时,我们发现是11,而用sizeof返回的是12,这是为什么呢?
这是因为strlen返回的是字符串结束标志"\0"之前的字符串长度,而不是数组长度,而sizeof返回的是数组的长度,也就是该数组共有多少个元素。
在第9行,我们将数组的第6个元素修改为字符串结束标志"\0",(第1个元素是man[0]),我们看到由cout遇到空字符而结束输出,结果只输出了hello。
跟着第11行用strlen获取字符串的长度,为5,是可见字符hello的长度,没有包括结束标志"\0"。
而第12行sizeof获取的是数组的长度12.
隨風∞流逝发表于2010-1-2615:
54
string型字符串
char型字符串是C语言风格的字符串,它是用数组来保存字符串的,但是到了C++时代,由于诞生了类,出现了一种C++风格的字符串,也就是string型字符串。
这种风格的字符串是用string类来定义字符串的,因此要使用string类,我们必须在程序开头添加头文件string,string类存在于命名空间std中,这样我们就必须使用usingstd:
:
string指令,或者直接用std:
:
string来访问它。
string类在定义时隐藏掉了字符串的数组性质,因此在使用string类定义字符串时不用考虑如何将字符串存放在数组中,string类已经做好了这一步,编程者要做的,就是像定义一个整型变量那样使用它,如:
stringstr;
这里定义了一个C++风格的字符串str。
C++风格的字符串就是用对象来保存字符串的。
下面用实例演示char型字符数组和string型字符串的不同。
字符数组与字符对象不同,两者相比较的程序代码如下:
[code]#include
#include
usingnamespacestd;
int_tmain(intargc,_TCHAR*argv[])
{
stringstr="string型字符串";
charch[]="char型字符串";
cout<cout<cout<<"请输入“狗”的英文单词:
"<cin>>str;
if(str=="dog")
{
cout<<"狗:
"<cout<<"str"<<"的第1个字符是:
"<}
else
cout<<"输入错误"<cout<<"请输入“猪”的英文单词:
"<cin>>ch;
if(ch=="pig")
{
cout<<"猪:
"<cout<<"ch"<<"的第1个字符是:
"<}
else
cout<<"输入错误"<system("pause");
return0;
}[/code]输出:
string型字符串
char型字符串
请输入“狗”的英文单词:
dog
狗:
dog
str的第1个字符是:
d
请输入“猪”的英文单词:
pig
输入错误
分析:
第6行定义并初始化了一个string型字符串str,第7行定义并初始化了一个char型字符数组ch,第8行和第9行分别输出它们的值。
可以看到它们的初始化工作和输出结果都是一样的。
区别在第12行和第21行。
第11行用cin接受用户输入的字符串并保存在string型字符串str中,然后第12行对str和双引号内的正确答案进行判断,假如两者相等的话,执行大括号中的语句,输出str的值以及str中的第1个字符。
我们看到第24行也可以用个数组的形式访问str对象中的字符。
输出的结果也证明第12那种直接用str对象与一串字符进行的判断的方法是可以的。
第20行将用户输入的字符保存在char型字符数组ch中,第21行也用了第12行的方式进行判断,但是我们发现即使输出了正确的单词,系统提示输入错误。
这是为什么呢?
这是因为ch是一个数组名,我们知道数组名是该数组第1个元素的内存地址,而用引号括起来的字符串也代表第1个字符的内存地址,这两个内存地址根本不可能相等,因此程序始终执行else分支,提示输入错误。
以上问题解决的办法是用循环的方式比较数组中的每一个字符。
自定义check比较函数,程序代码如下:
[code]#include
#include
usingnamespacestd;
intcheck(charch[]);
int_tmain(intargc,_TCHAR*argv[])
{
stringstr="string型字符串";
charch[]="char型字符串";
cout<cout<cout<<"请输入“狗”的英文单词:
"<cin>>str;
if(str=="dog")
{
cout<<"狗:
"<cout<<"str"<<"的第1个字符是:
"<}
else
cout<<"输入错误"<cout<<"请输入“猪”的英文单词:
"<cin>>ch;
if(check(ch)==1)
{
cout<<"猪:
"<cout<<"ch"<<"的第1个字符是:
"<}
else
cout<<"输入错误"<system("pause");
return0;
}
intcheck(charch[])
{
charch1[]="pig";
boolquit=false;
for(inti=0;i{
if(ch[i]!
=ch1[i])
{
quit=true;
break;
}
}
if(quit==false)
return1;
else
return0;
}[/code]分析:
第4行我们定义了一个check函数,它带有一个int型返回值,并且还有一个char型数组作为该函数的接收参数。
第31~47行是该函数的定义部分,在第33行定义了一个char型数组ch1,用来保存正确答案,第34行定义了一个bool型变量quit,并将它的值初始化为false,以后该变量会作为检测的依据,第35行是一个for循环,在这里要注意它的循环次数是保存了正确答案的ch1的字符长度,而不是保存了用户输入的ch。
第37~43行循环对ch1和ch数组中的每个字符进行比较,假如有一个字符不相等的话,立即将quit的值赋为true,然后退出循环,假如所有字符均相等的话,保持不变。
第43~46行在对quit的值进行判断,假如为false,返回1,不相等时,返回0.
第23行调用了这个函数,假如返回值为1,那么执行括号内的语句,否则输出"输入错误".
我们也可以将这个check(charch[],charch1[])
这样旧可以去掉第33行对ch1的初始化,而在调用时只要写下。
check(ch,"pig");
这样"pig"会作为一个未命名的字符串数组由check函数的形式参数ch1接受,然后传递到函数中去,这样,ch1在check函数中就成了"pig"的数组名。
对于未命名数组,我们看下面语句就明白了。
cout<<"pig";
该语句中的pig就是作为一个未命名字符串数组保存在栈中,然后通过cout对象加按位左移运算符<<以流的形式将它们输出。
修改后的check函数时的程序代码如下:
[code]#include
#include
usingnamespacestd;
intcheck(charch[],charch1[]);
int_tmain(intargc,_TCHAR*argv[])
{
stringstr="string型字符串";
charch[]="char型字符串";
cout<cout<cout<<"请输入“狗”的英文单词:
"<cin>>str;
if(str=="dog")
{
cout<<"狗:
"<cout<<"str"<<"的第1个字符是:
"<}
else
cout<<"输入错误"<cout<<"请输入“猪”的英文单词:
"<cin>>ch;
if(check(ch,"pig")==1)
{
cout<<"猪:
"<cout<<"ch"<<"的第1个字符是:
"<}
else
cout<<"输入错误"<system("pause");
return0;
}
intcheck(charch[],charch1[])
{
boolquit=false;
for(inti=0;i{
if(ch[i]!
=ch1[i])
{
quit=true;
break;
}
}
if(quit==false)
return1;
else
return0;
}[/code]虽然输出结果与修改前的程序相同,但仍很麻烦,假如我们使用strcmp函数的话,那么就可以省略自己定义函数这一步骤。
strcmp函数用来比较两个字符串是否相等,假如str1str2,返回一个大于0的数字,如1.
使用strcmp函数时的程序代码如下:
[code]#include
#include
usingnamespacestd;
int_tmain(intargc,_TCHAR*argv[])
{
stringstr="string型字符串";
charch[]="char型字符串";
cout<cout<cout<<"请输入“狗”的英文单词:
"<cin>>str;
if(str=="dog")
{
cout<<"狗:
"<cout<<"str"<<"的第1个字符是:
"<}
else
cout<<"输入错误"<cout<<"请输入“猪”的英文单词:
"<cin>>ch;
if(strcmp(ch,"pig")==0)
{
cout<<"猪:
"<cout<<"ch"<<"的第1个字符是:
"<}
else
cout<<"输入错误"<system("pause");
return0;
}[/code]分析:
使用strcmp函数后,程序代码简化了很多,但是再简化也不如string类的字符串,由于string类中的函数重载了类似比较运算符(==)等关系运算符,因此string类允许使用运算符对它的字符串对象进行比较,这是string型字符串与char型字符数组的第1个区别。
隨風∞流逝发表于2010-1-2619:
51
string型字符串的赋值
char型字符串无法直接赋值,如:
[code]charch1[]="giveme";
charch2[]="acup";
ch1=ch2;[/code]这样是错误的,不能将一个数组名赋给另一个数组名。
虽然我们无法直接赋值,但我们可以通过C函数,比如说strcpy拷贝函数来实现赋值的目的。
char型字符的赋值的实现例程代码如下:
[code]#include
#include
usingnamespacestd;
int_tmain(intargc,_TCHAR*argv[])
{
charch1[]="what'syourname";
charch2[]="mynameisJack";
strcpy(ch1,ch2);
cout<cout<system("pause");
return0;
}[/code]输出:
mynameisJack
mynameisJack
分析:
第7行调用了strcpy函数,它的作用是将ch2中的字符依次复制给ch1.因此必须保证ch1足够大,以便能够容纳ch2的字符串,这里由于在初始化时ch1容纳的字符比ch2多,因此我们没有改动。
ch2可以是字符数组名,也可以是一个字符串常量,如:
strcpy(ch1,"mynameisJack");
它与strcpy(ch1,ch2)相同
[color=DarkRed]注意:
(1)strcpy会将ch2中的所有字符,包括结束标志"\0"一起复制到ch1中去。
(2)不可以直接对char型字符串数组进行赋值操作,如:
chara[9],b[9];
a=b;
只能用strcpy函数对数组元素逐个的赋值,如:
a[0]=b[0];
a[1]=b[1];
................
a[8]=b[8];[/color]
很明显,这样要麻烦多了,我们来看一下string字符串对象的赋值。
string型字符串对象的赋值实例的程序代码如下:
[code]#include
#include
usingnamespacestd;
int_tmain(intargc,_TCHAR*argv[])
{
stringstr1="what'syourname";
stringstr2="mynameisJack";
str1=str2;
cout<cout<system("pause");
return0;
}
[/code]分析:
由于在strin