C++程序设计案例实训教程第4章
2017-10-29 17:12
351 查看
第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'的长度,并非是数组在内存中空间的大小。代码charstr[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[],charobj[],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*有时候又称为泛型指针,也就是可以指向任何类型数据的指针;(*s)(a,c,6);调用函数,函数中对应函数输入的3个参数为char*list[]、char
obj[]、int len。
注意:在实际应用中,以下写法是合法的,strcmp(str1,str2);,strcmp(″China″,″Korea″);,strcmp(str1,″Beijing″);。
案例4-5 连接两个字符串(strcat())
【案例描述】
在实际编程中经常要把2个或2个以上字符串连接在一起,如输入"Hello"、"World"、" ! ",这时候可以用连接两个字符串的函数strcat()将它们连接起来。本例演示了几个字符串连接的实际运用。效果如图4-5所示。图4-5 连接两个字符串(strcat())
【实现过程】
程序分2个演示。demo1()定义4个字符串s1[80]、s2[80]、s3[80]、s4[80],提示输入4个字符串,取得输入的4个字符串后合并,获得字符串长度并打印这个字符串;demo2()定义1个函数path(intn,char s[20]),第一个输入参数为整数,表示路径的节点数,第二个字符串用来存储从起点到终点经过的路径,该函数用到递归,递归代码是if(n>1) path(n-2,s1);和if(n>0) path(n-1,s1);。其代码如下:
#include<iostream>
#include<iostream.h>
#include<string.h>
int demo1(void)
{
char s1[80], s2[80],s3[80], s4[80]; //定义字符串
cout << "输入第一个字符串s1:";
cin >>s1;
cout << "输入第二个字符串s2:";
cin >>s2;
strcat(s2, s1); //连接两个字符串
cout << "输入第三个字符串s3:";
cin >>s3;
strcat(s3, s2);
cout << "输入第四个字符串s4:";
cin >>s4;
strcat(s4, s3);
cout<<"连接后输入字符串:"<<s4<<endl;
int i = strlen(s4); //获得字符串长度
cout<<"连接后输入字符串长度:"<<i<<endl;
return 0;
}
int n,k; //k表示第几条路径,n为所求路径的终点
void path(int n,char s[20]) //s表示结果串
{
char s1[20];
s1[0]='-';
s1[1]=n+48; //将输入的整数值转换为对应字符的ASCII码值
s1[2]='\0';
strcat(s1,s); //字符串连接,返回S1串
if(n>1) path(n-2,s1);
if(n>0) path(n-1,s1);
if(n==0)
{
k++;
cout<<k<<" : 0"<<s<<endl;
}
}
void demo2()
{
do
{
cout<<"n=";
cin>>n;
}while(!(n>=0&& n<=9)); //输入整数
k=0;
path(n,"");
system("pause");
}
int main()
{
demo1();
cout <<"\n"; //换行
demo2();
cout << "\n";
system("pause");
return 0;
}
【案例分析】
(1)strcat格式为char* strcat (char* dest, const char* src);,其功能是将字符串src附加到字符串dest的末尾,返回dest。该函数有两个字符数组的参数,函数的作用是:将第二个字符数组中的字符串连接到第一个字符数组的字符串的后面。第二个字符数组被指定为const,以保证该数组中的内容不会在函数调用期间被修改。连接后的字符串放在第一个字符数组中,函数调用后得到的函数值就是第一个字符数组的地址。
(2)代码strcat(s4, s3);连接两个字符串s3和s4,就是把s3连接到前面字符数组的字符串s4的后面。
注意:在应用strcat()时要注意,第一个字符串要有足够的空间。
案例4-6 将小写字符转换为大写(strupr())
【案例描述】
编程中经常遇到大小写字母转换。如‘ABC’转换成“abc”。如输入验证码有大小写,但验证码不分大小写,就需进行大小写转换。本实例定义字符串进行大小写转换,或取得随机输入字符串的值进行大小写转换。本例效果如图4-6所示。图4-6 将小写字符转换为大写(strupr())
【实现过程】
程序分两个演示:demo1()定义1个字符串string并初始化,然后进行大写转换,打印这个字符串;demo2()代码定义2个字符串string[80],*p,然后取得输入字符串进行大小写处理,输出演示结果。其代码如下:#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include<iostream>
#include<iostream.h>
//C语言将小写字符转换为大写
void demo1()
{
char ss[]="love china";
char *ad;
ad=strupr(ss); //小写字母转换为大写字母
printf("string ss:%s\n",ad);
char string[100] = "The String to End All Strings!"; //定义字符串
char *copy1, *copy2; //定义字符串
copy1 = _strlwr( _strdup( string ) ); //大写字母转换为小写字母
copy2 = _strupr( _strdup( string ) ); //小写字母转换为大写字母
printf( "Mixed: %s\n", string ); //打印字符串
printf( "Lower: %s\n", copy1 );
printf( "Upper: %s\n", copy2 );
}
//C++语言将小写字符转换为大写
int demo2()
{
char string[80],*p;
int i;
//转换字符串中的小写字母为大写字母
cout<<"转换字符串的大小写字母为大写:"<<endl;
cout<<"string:"<<endl;
cin>>string;
p=strupr(string); //将字符串转换为大写字母
cout<<"p:"<<p<<endl;
cout<<"string:"<<string<<endl;
cout<<"--------------"<<endl;
//转换字符串的大小写字母为小写
cout<<"转换字符串为小写:"<<endl;
cout<<"string:"<<endl;
cin>>string;
p=strlwr(string); //将字符串转换为小写字母
cout<<"p:"<<p<<endl;
cout<<"string:"<<string<<endl;
return 0;
}
int main()
{
demo1();
cout <<"\n"; //换行
demo2();
cout << "\n";
system("pause");
return 0;
}
【案例分析】
(1)字母大小写转换函数的声明包含在string.h头文件中原型为:char*strupr(char *string),是将字符串string中的小写字母转换为大写,并返回指向string的指针。另一个函数char*_strlwr( char *string );,将str1中的大写字母转换成小写字母。
(2)演示1代码中,定义一个字符串类char *copy1 和char string[100] = "The String to End All Strings!";,copy1
= _strlwr( _strdup( string ) );,就可实现大写字母转换为小写;copy2 = _strupr( _strdup( string ) );,实现小写字母转换为大写。演示2具有同样的功能。
注意:C++语言中,函数int toupper( int c );的功能是将小写字母转为大写,int tolower( int c );表示将大写字母转为小写。
案例4-7 比较两个string字符串
【案例描述】
实际编程中经常会比较两个string字符串。如定义两个string类型的姓名字符串,分别输入数据查看是否是同一个人,可以直接用比较符号如“==”或用string字符串成员函数compare()实现。本例效果如图4-7所示。图4-7 比较两个string字符串
【实现过程】
在demo1()中定义string字符串,使用比较符号“==”、“>”和“<”比较字符串;在demo2()中先用string字符串成员函数compare()比较字符串,然后用if判断语句,最后打印比较结果。代码实现如下:#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
int demo1()
{
string string1( "AAAAAAAAAAAAAA" ); //定义string字符串
string string2( "BBBBBBBBBBBBBB" );
string string3( "CCCCCCCCCCCCCC" );
string string4( string2 );
//输出string字符串
cout << "string1: " << string1 << "\nstring2: " << string2
<< "\nstring3: " << string3 << "\nstring4: " << string4 ;
cout <<"\n"; //换行
cout <<"比较 string1
和 string4结果: "; //比较
string1 和
string4
if ( string1 == string4 ) //用比较符号“==”、“>”和“<”
cout << "string1 == string4\n";
else{
if ( string1 > string4 )
cout << "string1 > string4\n";
else //string1<string4
cout << "string1 < string4\n";
}
return 0;
}
int demo2(void)
{
string string1( "AAAAAAAAAAAAAA" );
string string2( "BBBBBBBBBBBBBB" );
string string3( "CCCCCCCCCCCCCC" );
string string4( string2 );
cout << "string1: " << string1 << "\nstring2: " << string2
<< "\nstring3: " << string3 << "\nstring4: " << string4;
cout <<"\n"; //换行
cout <<"比较 string1 and string2结果: "; //比较string和
string2
int result = string1.compare( string2 ); //用string字符串成员函数compare
if ( result == 0 )
cout << "string1.compare( string2 ) == 0\n";
else {
if ( result > 0 )
cout << "string1.compare( string2 ) > 0\n";
else
cout << "string1.compare( string2 ) < 0\n";
}
return 0;
}
int main()
{
demo1();
cout <<"\n"; //换行
demo2();
cout << "\n";
system("pause");
return 0;
}
【案例分析】
(1)代码中字符串的比较有两种方式:比较操作符(>、>=、<、<=、==、!=)和string字符串成员函数compare(),取得一个整数,通过整数大小判断字符串比较结果。(2)string字符串支持常见的比较操作符(>、>=、<、<=、==、!=),也支持string与C风格字符串的比较。使用这些比较操作符时,根据字符的字典排序靠前的字符小的规则,从头字母往后逐一进行比较,遇到不等的字符就按该位置上的这两个字符的比较结果确定两个字符串的大小,即string("abcde")<string("ac")。此外,string类还提供了成员函数compare()用于字符串的比较,支持多参数处理,支持用索引值和长度定位子串来进行比较,返回一个整数(0:相等、>0:大于、<0:小于)来表示比较结果。
注意:实际上,用比较操作符和成员函数compare()进行字符串比较时,其结果是一样的。
案例4-8 查找string的某个元素
【案例描述】
在编写一个查找文本文件内容的程序时,需查找string的某个元素的功能,如查找元素或子串在字符串中第一次出现的位置,查找元素或子串在字符串中最后一次出现的位置。本例演示了4个查找string中某个元素的例子,效果如图4-8所示。图4-8 查找string的某个元素
【实现过程】
代码由4个演示组成,demo1()为string1.find( "is" );,demo2()为string1.rfind( "is" ),demo3()为string1.find_first_of( "is" );,demo4()为string1.find_last_of( "is" );。代码实现如下:#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
int demo1()
{
string string1( "This is a test string!"); //定义string字符串
int location;
//显示字符串“is”的位置
cout << "Original string:\n" << string1
<< "\n\n(find) \"is\" was found at: " << string1.find( "is" );
return 0;
}
int demo2()
{
string string1( "This is a test string!"); //定义string字符串
int location;
//rfind显示字符串“is”位置
cout << "Original string:\n" << string1
<< "\n\n(find) \"is\" was found at: " << string1.rfind( "is" );
return 0;
}
int demo3()
{
string string1( "This is a test string!"); //定义string字符串
int location;
//显示字符串“is”位置并赋值给location
location = string1.find_first_of( "is" );
//显示字符串“is”位置
cout << "\n\n(find_first_of) found '" << string1[ location ]
<< "at: " << location;
return 0;
}
int demo4()
{
string string1( "This is a test string!"); //定义string字符串
int location;
//最后的字符串“is”的位置并赋值给location
location = string1.find_last_of( "is" );
//显示字符串“is”位置
cout << "\n\n(find_last_of) found '" << string1[ location ]
<< " at: " << location;
return 0;
}
int main()
{
demo1();
cout <<"\n"; //换行
demo2();
cout << "\n";
demo3();
cout <<"\n"; //换行
demo4();
cout << "\n";
system("pause");
return 0;
}
【案例分析】
string类提供的搜索与查找的函数有很多,总体上说,string类提供了6种搜索函数,返回值均为size_type。— find():返回待查找元素或子串在字符串中第一次出现的位置(例如,字符串str为“Welcome
to C++ World”,使用find()函数系列查找单个字符“o”在str中第一次出现的位置,返回结果为4,查找子串“to”在str中的位置,返回结果为8。
— rfind():返回待查找元素或子串在字符串中最后一次出现的位置。如使用rfind()函数查找单个字符“o”在str中最后一次出现的位置时,返回结果为16。
— find_first_of():返回待查找元素在字符串中第一次出现的位置。如果查找的子串,不是查找整个字符串的匹配,而是搜索子串中的字符首次出现的位置。同样以字符串“Welcome to C++ World”为例,使用find_first_of()系列函数查找字符串“abc”在其中首次出现的位置,返回结果为3,此时第一次出现了字符串“abc”中的元素“c”。
— find_last_of():返回待查找元素在字符串中最后一次出现的位置。如果查找的子串,不是查找整个字符串的匹配,而是搜索子串中的字符最后出现的位置。
— find_first_not_of():与find_first_of()类似,不过搜索的是第一个不位于字符串中的字符第一次出现的位置。
— find_last_not_of():与find_first_of()类似,不过搜索的是第一个不位于字符串中的字符最后一次出现的位置。
注意:上面6种搜索函数,实际上就是查找位置不同,函数的形式是一样。
案例4-9 获取string字符串的长度
【案例描述】
编程中经常需要知道string字符串的长度,如定义string字符串读取一个文本文件内容,需知道读了多少字节,通信中,对方发过来信息需要取得的长度。这个可以用的string字符串的一个成员函数length()来实现。本例效果如图4-9所示。
图4-9 获取string字符串的长度
【实现过程】
程序分3个演示:demo1()定义2个string字符串,输出字符串的长度;demo2()定义1个string字符串,使用size()输出字符串的内容;demo3()定义3个string字符串,分别输出string类获取的string字符串的长度、获取所能包含的最大字符数和字符串的最大长度,给第一个字符串重新分配内存,查看3个字符串的string类所能包含的最大字符数有无变化。代码实现如下:#include <iostream>
#include <string> //string类头文件
using namespace std;
int demo1()
{
string stringA = "C++";
string stringB = "Is Cool";
cout << "Length of stringA = " << stringA.length() << endl; //字符串的长度
cout << "Length of stringB = " << stringB.length() << endl;
return 0;
}
int demo2()
{
string str1("Strings handling is easy in C++"); //定义string类
string::iterator p;
unsigned int i;
// use size()
for(i=0; i<str1.size(); i++) //输出string类
cout << str1[i];
cout << endl;
return 0;
}
int demo3( )
{
string s = "";
string sr= "";
string sr1= "TEST";
sr.reserve(9); //重新分配内存
cout << "s.length = " << s.length( ) << '\n'; //字符串的长度
cout << "s.capacity = " << s.capacity( ) << '\n'; //string类所能包含的最大字符数
cout << "s.max_size = " << s.max_size( ) << '\n'; //字符串的最大长度
cout << "sr.length = " << sr.length( ) << '\n'; //字符串的长度
cout << "sr.capacity = " << sr.capacity( ) << '\n';
cout << "sr.max_size = " << sr.max_size( ) << '\n';
cout << "sr1.length = " << sr1.length( ) << '\n'; //字符串的长度
cout << "sr1.capacity = " << sr1.capacity( ) << '\n';
cout << "sr1.max_size = " << sr1.max_size( ) << '\n';
for (int i = 0; i < 20; ++i) {
//比较字符串的长度和string类所能包含的最大字符数
if (s.length( ) == s.capacity( )) {
cout << "s reached capacity of " << s.length( )
<< ", growing...\n";
}
if (sr.length( ) == sr.capacity( )) {
cout << "sr reached capacity of " << sr.length( )
<< ", growing...\n";
}
if (sr1.length( ) == sr1.capacity( )) {
cout << "sr1 reached capacity of " << sr1.length( )
<< ", growing...\n";
}
s += 'x';
sr += 'x';
sr1 += 'x';
}
return 0;
}
int main()
{
demo1();
cout <<"\n"; //换行
demo2();
cout << "\n";
demo3();
cout << "\n";
system("pause");
return 0;
}
【案例分析】
(1)reserve(9)表示重新分配内存的大小为9字节,函数默认参数为0,会对string进行非强制性缩减。begin()指向字符串第一个字符的迭代器;end()超尾值的迭代器。演示2中str1.size(),指的是字符串中的元素个数,等于end()减去begin()。(2)string类提供了一些和大小、容量相关的函数。s.length( )表示获取字符串的长度;s.capacity( )表示string类所能包含的最大字符数;s.max_size(
)表示字符串的最大长度。
注意:除上面的介绍外,string类提供了一些与大小、容量相关的函数,rbegin()是超尾值的反迭代器;rend()是引用第一个字符的反转迭代器;empty()是检查字符串是否为空。
案例4-10 提取string字符串的子串
【案例描述】
在一个string字符串中想获取指定的子串,如通信中接收对方信息并提取有关内容,处理后替换内容,然后发回去。string字符串提供这种功能的成员函数substr()。本例效果如图4-10所示。图4-10 提取string字符串的子串
【实现过程】
程序分两个演示:demo1()定义string字符串,用substr()函数输出指定位置子的字符串;demo2()定义1个string字符串,使用size()输出字符串内容;demo3()定义4个string字符串分别表示文件名、基本文件名、扩展文件名和临时文件名,取出基本文件名和扩展文件名,然后用临时的文件名替换扩展文件名。代码实现如下:#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
int demo1(void)
{
string s1( "AA1234567890asdfasdf" ); //定义string类
string s2( " AAB" );
string s3;
//测试函数substr功能
cout << "The substring of s1 starting at location 0 for\n"
<< "14 characters, s1.substr(0, 14), is:\n"
<< s1.substr( 0, 14 ) << "\n\n";
return 0;
}
int demo2 (void)
{
//定义文件名、基本文件名、扩展文件名、临时文件名
string filename, basename, extname, tmpname;
const string suffix("tmp"); //定义string类
for (int i=1; i<2; ++i) {
filename = "filename.txt";
//找文件名
string::size_type idx = filename.find('.');
if (idx == string::npos) {
//文件名不包含'.'
tmpname = filename + '.' + suffix;
}
else {//拆分文件名和扩展名
basename = filename.substr(0, idx);
extname = filename.substr(idx+1);
if (extname.empty()) { //字符串是否为空
//没有扩展名,加上 tmp
tmpname = filename;
tmpname += suffix;
}
else if (extname == suffix) {
//用xxx替换扩展tmp
tmpname = filename;
tmpname.replace (idx+1, extname.size(), "xxx");
}
else {
//用tmp替换扩展名
tmpname = filename;
tmpname.replace (idx+1, string::npos, suffix);
}
}
//打印文件名称和临时文件名称
cout << filename << " => " << tmpname << endl;
}
return 0;
}
int main()
{
demo1();
cout <<"\n"; //换行
demo2();
cout << "\n";
system("pause");
return 0;
}
【案例分析】
(1)代码中,extname.empty()用于检查字符串是否为空;代码tmpname.replace (idx+1, extname.size(), "xxx");的原型是replace(size_type p0, size_type n0, const E *s);,其作用是将原string中的元素或子串替换,返回替换后的string。(2)string类提供了substr()成员函数用于提取子串,以string
str("12345678912345678")为例,str.substr();返回str的全部内容;str.substr(9);提取索引9后面的子串,即"12345678";str.substr(5,6);从索引5开始提取6个字符,即"678912"。
注意:编程中,replace()用于元素或子串的替换,substr()用于提取子串。
案例4-11 把两个string字符串相加
【案例描述】
编程中经常需要把string字符串相加或将string对象、字符数组或字符插入到string字符串中,或将另一个string字符串添加到string字符串后。如加密时需把两个明文字符串相加,加密后输出密文,本实例演示将这个功能,效果如图4-11所示。【实现过程】
定义4个string字符串,重载“+=”操作符,成员函数append()另一个string字符串添加到string字符串后;成员函数insert()用于将string对象、字符数组或字符插入到string字符串中;成员函数replace()用于替换指定位置的字符串。代码实现如下:#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1("A"); //定义string类
string str2("B");
string str3("O");
string str4;
str4 = str1;
cout << str1 << "\n" << str3 << "\n";
str4 = str1 + str2; //string类相加
cout << str4 << "\n";
str4 = str1 + " to " + str3; //string类相加
cout << str4 << "\n";
if(str3 > str1) //string类比较
cout << "str3 > str1\n";
if(str3 == str1+str2) //string类比较
cout << "str3 == str1+str2\n";
str1 = "This is a null-terminated string.\n";
cout << str1;
string str5(str1);//定义string类
cout << str5;
cout << "Enter a string: ";
cin >> str5;
cout << str5;
string s("C++ Primer"); //初始化s为
"C++ Primer"
s.append(" 3rd Ed."); //追加函数,s == "C++ Primer 3rd Ed."
//等同于o s.append(" 3rd Ed.")
s.insert(s.size(), " 3rd Ed."); //元素插入
cout << s << endl;
//开始位置为11,删除3个字符后插入"4th"
s.replace(11, 3, "4th"); //替换函数,s == "C++ Primer 4th Ed."
cout << s << endl;
//等同于用"4th"退换"3rd"
s.erase(11, 3); //s="C++ Primer Ed."
s.insert(11, "4th"); //s="C++ Primer 4th Ed."
cout << s << endl;
s.replace(11, 3, "4th"); //s="C++ Primer 4th Ed."
cout << s << endl;
s.replace(11, 3, "Fourth"); //s="C++ Primer Fourth Ed."
cout << s << endl;
system("pause");
return 0;
}
【案例分析】
(1)代码中重载了操作符(+=),(+=)操作符能将另一个string字符串、C风格字符串,甚至是单个字符添加到string字符串后。append()函数的原型为:append(constE *s);,其功能与(+=)操作符相同。
(2)成员函数insert()的原型为:insert(size_type p0, const E *s);,作用是将string对象、字符数组或字符插入到string字符串中。这和append函数相似,只是元素插入不再局限于尾部,可以插入到中间。因此,需要一个指示插入位置的参数,该参数可以是位置,也可以是迭代器,数据将被插入该位置的前面。代码s.erase(11,
3);的作用是删除从11开始的3个字符。
注意:append()函数通过指定初始位置和追加字符数,以及指定区间的方法,可以将另一个string字符串或C风格字符串的一部分追加到字符串中,如定义append(const
E *s, size_type n);。
案例4-12 string字符串与单字符相加
【案例描述】
本例继续讨论上面两个实例的内容。如加密时对已经加密的string字符串加一个识别码(前面或后面),该识别码是一个单字符(如回车符),这就需要进行string字符串与单个字符的处理,方法与实例68是一样的。本例效果如图4-12所示。图4-12 string字符串与单字符相加
【实现过程】
定义3个string字符串string1、string2和string3,2个字符串char*str10和char *str11,2个单字符char str12和char str13,重载操作符“+=”,成员函数append()把另一个字符串添加到string字符串后并输出结果。用同样的方法把一个单字符添加到string字符串后并输出结果。代码实现如下:
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
int main()
{
string string1( "cat" ); //定义string类
string string2;
string string3;
string2 = string1;
string3.assign( string1 );
//输出字符串
cout << "string1: " << string1 << "\nstring2: " << string2
<< "\nstring3: " << string3 << "\n\n";
//重载“ +=”
char *str10=" pet";
char *str11=" acomb";
string3 += str10; //加一个字符串
string1.append( str11 ); //加一个字符串
//输出字符串
cout << "string1: " << string1 << "\nstring2: " << string2
<< "\nstring3: " << string3 << "\n\n";
//重载“ +=”
char str12='2';
char str13='3';
string3 += str12; //加一个字符
string1.append(3,str13); //加一个字符
//输出字符串
cout << "string1: " << string1 << "\nstring2: " << string2
<< "\nstring3: " << string3 << "\n\n";
system("pause");
return 0;
}
【案例分析】
(1)代码string3.assign( string1 );的原型为:assign(const E *s);,该成员函数assgin有多种重载形式,如assign(const_iteratorfirst, const_iterator last);,用于复制、赋值操作,功能是依次把一个string
对象的部分内容复制到另一个string对象上。
(2)实际上,单字符也可以用多字符的形式处理,如"c",处理起来比较麻烦,处理后的结果可能又要转换成单字符。
注意:编程中就要记住重载的“+=”操作符、append函数是将另一个string字符串、C风格字符串,甚至是单个字符都可以添加到string字符串后。
案例4-13 使用atoi()函数把字符串转换为整数
【案例描述】
在实际编程中,各种数据类型要进行转换,如字符串转换成整数。本实例和下面实例演示的是整数和字符串相互转换的例子,调用C++库函数实现。本实例演示的是判断简单验证IP格式是否正确,效果如图4-13所示。图4-13 使用atoi()函数把字符串转换为整数
【实现过程】
程序定义函数isValidIP(),输入字符串IP地址,提取字符串每位数字,用atoi()函数转换成整数,接着判断其值,若其值大于255或其值为0,则ip格式错误,否则返回正确。代码如下:#include <iostream>
#include <stdlib.h> //atoi()头函数
using namespace std;
bool isValidIP(string ip);
int main(){
if(isValidIP("192.168.6.989")) //判断ip地址
cout<<"IP地址格式正确"<<endl;
else
cout<<"IP地址格式不正确"<<endl;
system("pause");
return 0;
}
bool isValidIP(string ip){ //验证IP格式是否正确
string delim="."; //定义string类字符串
string ret[4];
string::size_type loc=0,start =0;
for(int i=0;i<4;i++){ //共有4位
loc = ip.find(delim, start); //查找"."位置
if(loc != string::npos){
ret[i]=ip.substr(start,loc-start); //提取子串
start=loc+1;
}else if(i==3){
ret[i]=ip.substr(start); //提取子串
}else{
//格式不对,应该有3个.
return false;
}
}
for(i=0;i<4;i++){ //共有4位
int num=atoi(ret[i].c_str()); //字符串转换为整数
if(num>255){ //大于255
return false;
}else if((num==0)&&(ret[i].compare("0"))){ //如为0
return false;
}
}
return true;
}
【案例分析】
上述代码简单验证IP格式是否正确,ip值由三位十进制数值组成,,每位的大小在(0,255)之间,每项数值间以“.”分隔。atoi格式为intatoi( const char *string ),转换字符串为整数。
注意:C++几个库函数atof、atoi、_atoi64、atol,功能为转换字符串为双精型(atof)、整数(atoi、_atoi64)或长整数(atol)。
案例4-14 使用itoa()函数把整数转换为字符串
【案例描述】
本实例继续上面实例的话题,用C++库函数itoa()把整数转换为字符串,转换成字符串后可以以一定格式输出。本实例是将10进制数转换为格雷码,效果如图4-14所示。图4-14 使用itoa()函数把整数转换为字符串
【实现过程】
程序定义函数Deci2Gray(),输入是需转换整数,用itoa()函数把整数转换成字符串,返回格雷码;主函数读取输入整数,调用转换函数。代码如下:#include <iostream>
using namespace std;
#include<stdlib.h>
char *Deci2Gray (int n)
{
int g; //g代表格雷码
//用于储存格雷码的二进制表达式
char *s;
s=(char*)malloc(sizeof(s)*2); //分配内存
g = n^(n>>1); //将十进制数右移一位并取异或;
itoa(g, s, 2); //整数转换为字符串
return s; //返回格雷码
}
int main (void)
{
int d; //d代表十进制数
cout<<"Please input the interge decimal number you wish to convert:"<<endl;
scanf("%d",&d); //读取输入整数
cout<<"The Gray-Code of this number is:";
cout<<endl;
cout<<Deci2Gray(d); //调用转换函数
system("pause");
return 0;
}
【案例分析】
格雷码(Gray code)又叫循环二进制码或反射二进制码。itoa格式为char *_itoa( int value, char *string, int radix );,其作用是转换整数为字符串。注意:C++几个库函数_i64toa、_ui64toa、_itow、_i64tow、_ui64tow,功能分别为转换字符串为:64位整数数据类型(__int64)、无符号64位整数数据类型和整数(unsigned_int64、int)或64位整数和无符号64位整数(__int64、unsigned__int64)。
4.2 字符串输入输出
案例4-15 使用get()函数吸收缓冲区垃圾
【案例描述】
C++语言基本的输入函数cin,其功能是输入一个数字或接收一个字符串,遇“空格”、“Tab”、“Enter”就结束。另外,可用cin.get(字符变量名)来接收字符,不过应注意,读取字符之前应清空缓冲区,否则会出现错误。cin.getline()可以接收一个字符串,也可以接收空格并输出。本实例进行这方面函数的演示,效果如图4-15所示。【实现过程】
定义4个演示,第1个演示用cin.get(symbol),但是读取字符之前未清空缓冲区,第2个演示清空缓冲区,第3个演示cin.getline()接收一个字符串,第4个演示getline()接收一个二维字符串。代码如下:图4-15 使用get()函数吸收缓冲区垃圾
#include <iostream>
#include <string> // include for C++ standard string class
using namespace std;
int demo1()
{
cout<<"输入一个数字:\n";
int number;
cin>>number; //获取一个数值
cout<<"输入一字符:\n";
char symbol;
// cin>>symbol;
cin.get(symbol); //获得一个字符
cout<<"symbol="<<symbol<<endl;
return 0;
}
int demo2()
{
cout<<"输入一个数字:\n";
int number;
cin>>number; //获取一个数字
cout<<"输入一字符:\n";
char symbol;
// cin>>symbol;
cin.sync(); //读取字符之前清空缓冲区
cin.get(symbol); //获得一个字符
cout<<"symbol="<<symbol<<endl;
return 0;
}
int demo3()
{
char m0[20];
cout<<"输入一个测试字符串:";
cin.sync(); //读取字符之前清空缓冲区
cin.getline(m0,5); //接收一个字符串,可以接收空格并输出
cout<<"m0= "<<m0<<endl;
return 0;
}
int demo4()
{
char m[3][20]; //定义二维数组
for(int i=0;i<3;i++)
{
cout<<"\n请输入第"<<i+1<<"个字符串:";
cin.sync(); //读取字符之前清空缓冲区
cin.getline(m[i],20); //接收一个字符串,可以接收空格并输出
}
cout<<endl;
for(int j=0;j<3;j++) //输出二维数组的值
cout<<"输出m["<<j<<"]的值:"<<m[j]<<endl;
return 0;
}
int main()
{
demo1();
cout <<"\n"; //换行
demo2();
demo3();
demo4();
system("pause");
return 0;
}
【案例分析】
(1)在demo1()中,当输入为18时,按回车键后,symbol输出是一个换行符'\n';在demo2()中,当输入为18时,读取字符之前清空缓冲区cin.sync();,这时cin.get(symbol);将获取输入的字符'a',这样就不会出现get()函数读取到number后面的换行符。(2)cin.get()中,参数有4种,即从0个到3个。其中,Ch为模板类型参数:int_type
get(),获得一个字符,可为eof与terminator;istream& get(Ch& p),获得一个字符给p,可为terminator,不可为eof;istream&
get(Ch *p,streamsize n),定义最大输入,默认terminator为'\n';istream& get(Ch *p,streamsize n,Ch term),重定义terminator,不再为'\n'。cin.getline()参数有两种,即istream&
getline(Ch *p,streamsize n)和istream& getline(Ch *p,streamsize n,Ch term)。
注意:cin.get()与cin.getline()的区别在于,前者对于终止符不抛弃,后者舍弃。getchar()用于接收一个字符;gets()用于接收一个字符串,可以接收空格并输出,这两个函数都需包含“#include<string>”。
案例4-16 字符串的输入(getline())
【案例描述】
编程中经常需要输入字符串,输入字符串函数有多个,本例利用getline()函数实现字符串的输入,效果如图4-16所示。图4-16 字符串的输入(getline)
【实现过程】
cin.getline()从键盘接收一行字符,并进行判断计数;设状态变量为word,判断是字母时,word为1,判断是非字母时,word为0。代码如下:#include <iostream>
using namespace std;
void main(void)
{char s[80];
int i=0, word=0,num=0;
cin.getline (s,80); //从键盘接收一行字符
while(s[i]!='\0')
{
if((s[i]>='a'&&s[i]<='z'||s[i]>='A'&&s[i]<='Z')&&word==0)
{
word=1; //改变状态,防止继续对下一字母计数
num++;
}
else if(s[i]==' '||s[i]=='\t')
word=0; //改变状态,遇到下一个字母时开始计数
i++;
}
cout<<"num="<<num<<endl; //输出到'\0'为止
system("pause");
}
【案例分析】
(1)gets()的格式为:char *gets(char *buffer);,其功能是从stdio流中读取字符串,直至接收到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串。(2)代码getline()也可以作为成员函数使用。例如,cin.getline(char* cha,int num,char f);,其功能是向cha中输入num个字符,输入过程中达到num个数或者提前遇到f字符时,输入结束。
注意:gets(s)函数与scanf("%s",s)函数的用法相似,但不完全相同。
4.3 C风格字符串
案例4-17 string与C风格字符串的转换
【案例描述】
本例涉及string对象转换成C风格的字符串或相反转换,在实际编程中经常会用到,如读取文本文件信息为C风格,需要转换成帮助信息为string。本例效果如图4-17所示。图4-17 string与C风格字符串转换
【实现过程】
第一个演示demo1()定义string的对象str,把这个string对象转换成C风格的字符串,再把C风格的字符串转换成string对象;第二个演示与demo1()的功能类似,string对象和C风格的字符串相互转换。代码实现如下:#include <string>
#include <iostream>
using namespace std;
int demo1(void)
{
string str("Hello World!");
const char *test = str.c_str(); //string与C风格字符串的转换
cout << str.c_str() << endl; //输出string类
cout << test <<endl; //输出转换后的C风格字符串
str = test; //C风格字符串与string类转换
cout << "\nstr1= "<< str.c_str() << endl; //输出string类
return 0;
}
int demo2()
{
string s1( "AA1234567890asdfasdf" );
string s2( " AAB" );
string s3("Hello World!");
//测试转换
string *test = new string( s1 ); //定义string类
cout << "\ns1 = "<< s1.c_str() << endl; //输出string类
cout << "\n*test = " << *test << "\n\n";
const char *test1 = s3.c_str(); //string类与C风格字符串转换
cout << "\n*test1 = " << test1 << "\n\n";
s1 = test1;//C风格字符串与string类转换
cout << "\ns1= "<< s1.c_str() << endl; //输出string类
s3 = test1;
cout << "\ns3= "<< s3.c_str() << endl; //输出string类
return 0;
}
int main()
{
demo1();
cout <<"\n"; //换行
demo2();
cout << "\n";
system("pause");
return 0;
}
【案例分析】
(1)函数c_str()返回指针指向const char类型指针。“HelloWorld”字符串在string str内部是私有成员,不允许使用c_str()修改,故返回const类型。string对象转换成C风格的字符串,const
char *test = str.c_str(); ,这是为了防止字符数组被程序直接处理,c_str()返回一个指向常量数组的指针。
(2)C风格字符串转换为string字符串相对来说比较简单,通过构造函数即可实现。但由于string字符串实际上是类对象,其并不以空字符'\0'结尾。因此,string字符串向C风格字符串的转化是通过3个成员函数完成的,分别为:const
char *data();,以字符数组的形式返回字符串内容,但末尾并不添加'\0';const char *c_str();,返回一个以'\0'结尾的字符数组;int
copy(char*s,size_type n);,字符串的内容复制或写入已有的C风格字符串或字符数组内。
注意:本实例用到了成员函数c_str(),另外涉及两个成员函数data()和copy()。
案例4-18 string字符串与C风格字符串相加
【案例描述】
本例继续讨论上面实例的内容。如加密时,一个明文string字符串与另外一个C风格字符串在不转换的情况下相加,并进行加密处理后输出密文。本例效果如图4-18所示。图4-18 string字符串与C风格字符串相加
【实现过程】
定义2个string字符串str1、str5和1个字符串char*str,重载“+=”操作符,成员函数append()把另一个字符串添加到string字符串后;成员函数insert()将字符串插入到string字符串中;成员函数replace()替换指定位置的字符串。代码实现如下:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1("A"); //定义string类
string str5(str1); //定义string类
cout << str5<<endl;
char *str="test";
str5+=str; //加一个字符串
str5+="my name is jiayp"; //加一个字符串
str5+='a'; //加一个字符
cout << str5<<endl;
cout << "Enter a string: "<<endl;
cin >> str5;
cout << str5<<endl;
string s("C++ Primer"); //初始化s为
"C++ Primer"
s.append(" 3rd Ed."); //加一个字符串,追加函数,s == "C++ Primer 3rd Ed."
//等同于o s.append(" 3rd Ed.")
s.insert(s.size(), " 3rd Ed."); //元素插入
cout << s << endl;
//开始位置为11,
删除3个字符后插入"4th"
s.replace(11, 3, "4th"); //替换函数s="C++ Primer 4th Ed."
cout << s << endl;
// 等同于用"4th"退换"3rd"
s.erase(11, 3); //s="C++ Primer Ed."
s.insert(11, "4th"); //s="C++ Primer 4th Ed."
cout << s << endl;
s.replace(11, 3, "4th"); //s="C++ Primer 4th Ed."
cout << s << endl;
s.replace(11, 3, "Fourth"); //s="C++ Primer Fourth Ed."
cout << s << endl;
system("pause");
s.append(str); //追加函数
s.append(str,1,3);
s.append(str,2,string::npos);
cout << s << endl;
s.append("my name is jiayp");
s.append("nico",5);
s.append(5,'x');
cout << s << endl;
s.insert(0,"my name"); //插入函数
s.insert(1,str);
cout << s << endl;
system("pause");
return 0;
}
【案例分析】
(1)成员函数insert()的作用是将string对象、字符数组或字符插入到string字符串中。这和追加函数append()相似,只是元素插入不再局限于尾部,可以插入到中间,因此,需要一个指示插入位置的参数,该参数可以是位置,也可以是迭代器,数据将被插入该位置的前面。insert()函数的重载形式为:(1)string&append( size_type pos, const char* s);。(2)string& append( size_type pos, const char* s
, size_type n );。
(2)提到追加与相加,首先想到的是重载操作符“+=”,它能将另一个string字符串、C风格字符串,甚至是单个字符添加到string字符串后。
注意:C++中实现string字符串、C风格字符串,甚至是单个字符添加到string字符串中的处理是一样的。
4.1 本章练习
相关文章推荐
- C++程序设计案例实训教程第4章
- C++程序设计案例实训教程第5章
- C++程序设计案例实训教程第5章
- C++程序设计案例实训教程第9章
- C++程序设计案例实训教程第8章
- C++程序设计案例实训教程第8章
- C++程序设计案例实训教程第1章
- C++程序设计案例实训教程第15章
- C++程序设计案例实训教程第1章
- C++程序设计案例实训教程第15章
- C++程序设计案例实训教程第16章
- C++程序设计案例实训教程第16章
- C++程序设计案例实训教程第2章(qq讨论群112133686)
- C++程序设计案例实训教程第3章
- C++程序设计案例实训教程 前言
- C++程序设计案例实训教程第2章(qq讨论群112133686)
- C++程序设计案例实训教程第3章
- C++程序设计案例实训教程 前言
- C++程序设计案例实训教程 目录
- C++程序设计案例实训教程 目录