linux C++ day1
编译器
-g++
-gcc -lstdc++
扩展名
-.cpp/.cc/.C/.cxx
-.c -x C++
头文件
–#include
-#include
I/O流
–cout<<
–cin>>
–也可以用scanf/printf
名字空间
–std::
–using namespace std;
–所有标准类型、对象和函数都位于std命名空间中
名字空间:
为什么需要名字空间?
划分逻辑单元
.文件是物理单元,而名字空间则是逻辑单元
避免名字冲突
.同一作用域中不允许同时存在名字相同的标识符
什么是名字空间
名字空间定义
–namespace 名字空间名{
名字空间成员1;
名字空间成员2;}
名字空间合并
–namespace 名字空间名{
名字空间成员3;}
声明定义分开
–名字空间的声明和定义可以分开,但是定义部分需要借助作用域限定操作符"::"指明所定义的成员隶属于哪个名字空间
怎么用名字空间
作用域限定符
–名字空间名::名字空间成员名
名字空间指令
–using namespace 名字空间名;
–名字空间指令以后的代码,对名字空间中的所有成员可见,对可见名字空间成员的引用,可省略作用域限定符
–名字空间指令有可能导致名字冲突
名字空间声明
–using 名字空间名::名字空间成员名;
–名字空间声明用于将名字空间中的特定标识符引入当前作用域,可省略作用域限定符,直接引用之
–名字空间声明有可能导致重复声明
无名名字空间
不属于任何有名名字空间的标识符,隶属于无名命名空间
无名命名空间的成员,直接通过"::"访问,特别是在其与有名名字空间中的同名标识符构成冲突或被后者隐藏时
–int var=100;
namespace ns{
int var =200;
void fun(void){
cout<<var<<’ ‘<<::var<<endl;//200 100
}
}
–using namespace ns;
cout<<var<<endl;//错误
cout<<ns::var<<’ ‘<<::var<<endl;//200 100
–using ns::var;
cout<<var<<’ '<<::var<<endl;//200 100
名字空间嵌套与别名
内层隐藏外层
名字空间内部可以再定义名字空间,谓之名字空间嵌套
–namespace ns1{namespace ns2{…}}
在内层名字空间声明的标识符,隐藏在外层名字空间声明的同名标识符
–namespace ns1{
int var=1;
namespace ns2{
int var =2;
void fun(void){
cout<<var<<endl;//2
}
}
}
逐层分解
无论是定义还是使用嵌套的名字空间中的标识符,都需要通过作用域限定操作符逐层分解
–namespace ns1{
namespace ns2{
namespace ns3{
extern int var;
void fun(void);
}
}
}
–int ns1::ns2::ns3::var =123;
void ns1::ns2::ns3::fun (void){cout<< var<<endl;}
–cout<< ns1::ns2::ns3::var<<endl;//123
ns1::ns2::ns3::fun();//123
名字空间别名
利用名字空间别名,可以简化名字空间路径的书写形式
–namespace ns1{
namespace ns2{
namespace ns3{
extern int var;
void fun(void);
}
}
}
–namespace ns123=ns1::ns2::ns3;
–int ns123::var=123;
var ns123::fun(void){cout<<var<<endl;}
–cout<<ns123::var<<endl;//123
ns123::dun();//123
结构、联合和枚举
C++的结构
声明或定义结构型变量,可以省略struct关键字
可以定义成员函数,在结构体的成员函数中可以直接访问该结构体的成员变量,无需通过".“或”->"
–struct User{
char name[256];
int age;
void who(void){
cout<<“我是”<<name<<",今年"<<age<<“岁。”<<endl;}
};
–User user={“张飞”,25},*puser=&user;
user.who();
puser->who();
C++的联合
.声明或定义联合型变量,可以省略union关键字
与其说匿名联合是一种类型定义,倒不如说是一种对多个变量在内存中布局方式的表达
–union{
int n;
char c[sizeof(n)];
};
–n=0x12345678;
–for(size_t i=0;i<sizeof©;++i){
printf("%#x",c[i]);//0x78 0x56 0x34 0x12
printf("\n");
}
C++的枚举
.声明或定义枚举变量,可以省略enum关键字
.C++中的枚举是一种独立的数据类型,整型不能隐式转换为枚举型
–enum Corlor{
RED,YELLOW,BLUE,WHIFE,BLACK}corlor;
–color =RED;
color =5;//错误
color=0;//错误
–void foo(Color color);
foo(RED);
foo(5);//错误
foo(0);//错误
布尔值与操作符别名
布尔类型
表示布尔量的数据类型 -bool
布尔类型的字面值常量
–true表示真
–false表示假
以单字节整数形式存储,类似于char
–分别用1和0表示真和假
任何基本类型都可以被隐式转换为布尔类型
–非0即真,0即假
操作符表明
某些欧洲语言所使用的字母比26个基本拉丁字母多,占用了键盘中"~","&"等特殊符号的位置
国际标准化组织为一些操作符规定了别名,以便使用这些的键盘也能输入正确的C/C++代码
C95和C++98以后的语言标准都支持ISO-646
#include
using namespace std;
int main(void)<%
int a<::> =<%13,21,37,49,58%>;
int b<::>=<%79,63,45,31,16%>;
for(int i=0;i<5;++i)
cout<<(a<:i:>bitand b<:i:>)+
((a<:i:>xor b<:i:>)>>1)<<’ ';
cout<<endl;
%>
目录:
更严格的类型检查
Hello, World !
名字空间的定义与合并
名字空间的声明与定义可以分开
作用域限定符
名字空间指令
名字空间声明
名字空间声明与指令的区别
无名名字空间
多层名字空间
C++的结构
C++的匿名联合
C++的枚举
字符串的基本用法
字符串的基本运算
字符串的大小和容量
字符串拼接
在字符串中搜索特定字符
从字符串中提取子字符串
访问字符串中的单个字符
字符串的查找与替换
字符串的比较与排序
字符串的插入与删除
字符串的交换与复制
布尔类型
1 更严格的类型检查
1.1 问题
C++在类型检查上比C语言要严格。主要表现在增加了字符常量类型,强化了枚举类型,对指针运算要求更严格等。
1.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:增加了字符常量类型
代码如下:
#include
int main(int argc, const char * argv[])
{
std::cout << sizeof('x') << std::endl;
return 0;
}
上述代码中,以下代码:
std::cout << sizeof('x') << std::endl;
输出结果为1,而在C语言中,用printf函数输出结果则为sizeof(int)的值。
步骤二:强化了枚举类型
代码如下:
#include
int main(int argc, const char * argv[])
{
std::cout << sizeof('x') << std::endl;
enum Color {
RED, YELLOW, BLUE, WHITE, BLACK
};
Color color = RED;
int n;
n = YELLOW;
return 0;
}
上述代码中,以下代码:
int n;
n = YELLOW;
是错误的。在C++中不能将枚举常量直接赋值给一个整型变量。
步骤三:对指针运算要求更严格
代码如下:
#include
int main(int argc, const char * argv[])
{
std::cout << sizeof('x') << std::endl;
enum Color {
RED, YELLOW, BLUE, WHITE, BLACK
};
Color color = RED;
int n;
n = YELLOW;
int* p;
void* a = NULL;
p = a;
a = a + 1;
return 0;
}
上述代码中,以下代码:
p = a;
是错误的。因为C++中不允许将void*类型的指针赋值给其它类型的指针。
上述代码中,以下代码:
a = a + 1;
也是错误的。因为C++中void*类型的指针不能进行运算。
1.3 完整代码
本案例的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::cout << sizeof('x') << std::endl;
enum Color {
RED, YELLOW, BLUE, WHITE, BLACK
};
Color color = RED;
int n;
n = YELLOW;
int* p;
void* a = NULL;
p = a;
a = a + 1;
return 0;
}
2 Hello, World !
2.1 问题
使用vi编写HelloWorld.cpp程序,运行后,在控制台输出“Hello World!”
2.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:打开vi,编辑源程序
代码如下:
#include
int main(int argc, const char * argv[])
{
std::cout << "Hello World!" << std::endl;
return 0;
}
上述代码中,以下代码:
std::cout << "Hello World!" << std::endl;
是在控制台上输出字符串“Hello World!”,其中std::cout是一个对象,在本语句中相当于C语言中的printf函数。<<为输出流控制符。std::endl表示输出一个换行符,相当于C语言中的\n。
步骤二:使用g++进行编译链接
在控制台使用g++编译器对源代码进行编译链接,生成可执行文件。运行查看结果。
2.3 完整代码
本案例的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::cout << "Hello World!" << std::endl;
return 0;
}
3 名字空间的定义与合并
3.1 问题
大型程序中往往会使用多个独立开发的库,库中不可避免的出现同名的变量、函数或类、模板等,造成名称的冲突。名字空间是为了防止名字冲突提供的一种机制。通过使用namespace XXX可以将你所使用的库的变量、函数、类放入名字空间中,形成自己的作用域,避免名字冲突。
3.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:名字空间的定义
语法格式:
namespace 名字空间名{
名字空间成员1;
名字空间成员2;
}
其中:
1)namespace是定义名字空间的关键字。
2)名字空间名与变量名一样是一个标识符,在定义它的作用域内必须保持唯一。
3)名字空间成员可以是能出现在全局作用域中的任何声明,包括:变量、函数、结构体、类、模板及其他名字空间等。
注意:
1)名字空间结束后无需分号。
2)名字空间可以在全局作用域内,也可以在其它名字空间中,但不能在函数或类的定义中。
代码如下:
namespace ns {
int var = 0;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}//注意此处无分号
int main(int argc, const char * argv[])
{
std::cout << "ns::var = " << ns::var << std::endl;
ns::fun();
return 0;
}
上述代码中,定义了一个名字空间ns,其中包含两个成员,一个是整型变量var,另一个是函数fun。
步骤二:名字空间的合并
命名空间可以定义在几个不同的部分。
代码如下:
#include
namespace ns {
int var = 0;
void fun (void) {
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
namespace ns {
struct type {
int a;
float b;
};
}
int main(int argc, const char * argv[])
{
ns::type st = {10, 20.5};
std::cout << "st.a = " << st.a << std::endl;
std::cout << "st.b = " << st.b << std::endl;
return 0;
}
上述代码中,名字空间ns被分在两个部分。第一部分之前没有ns的名字空间,所以会创建一个新的名字空间,但第二部分为已经存在的名字空间,所以不会新建名字空间,只是在已有的空间内添加成员。
3.3 完整代码
本案例中名字空间定义的完整代码如下所示:
namespace ns {
int var = 0;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}//注意此处无分号
int main(int argc, const char * argv[])
{
std::cout << "ns::var = " << ns::var << std::endl;
ns::fun();
return 0;
}
本案例中名字空间合并的完整代码如下所示:
#include
namespace ns {
int var = 0;
void fun (void) {
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
namespace ns {
struct type {
int a;
float b;
};
}
int main(int argc, const char * argv[])
{
ns::type st = {10, 20.5};
std::cout << "st.a = " << st.a << std::endl;
std::cout << "st.b = " << st.b << std::endl;
return 0;
}
4 名字空间的声明与定义可以分开
4.1 问题
名字空间的声明和定义可以分开,但是定义部分需要借助作用域限定操作符“::”指明所定义的成员隶属于哪个名字空间。
4.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:名字空间的声明
代码如下:
#include
namespace ns {
extern int var;
void fun (void);
}
上述代码中,整型变量var前面加extern表示此变量将在名字空间外定义。
步骤二:名字空间的定义
代码如下:
#include
namespace ns {
extern int var;
void fun (void);
}
int ns::var = 10;
void ns::fun (void) {
int a = 10;
std::cout << "a = " << a << std::endl;
}
上述代码中由于是在名字空间外定义,所以必须使用名字空间名加作用域运算符ns::指明变量或函数是哪一个名字空间的。
4.3 完整代码
本案例中的完整代码如下所示:
#include
namespace ns {
extern int var;
void fun (void);
}
int ns::var = 10;
void ns::fun (void) {
int a = 10;
std::cout << "a = " << a << std::endl;
}
int main(int argc, const char * argv[])
{
std::cout << "ns::var = " << ns::var << std::endl;
ns::fun();
return 0;
}
5 作用域限定符
5.1 问题
作用域限定符为两个冒号::,其作用是通知编译器应从作用域限定符左侧的名字所示的作用域中寻找右侧那个名字,即指定访问哪个名字空间的哪个成员。
5.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:使用作用域限定符
代码如下所示:
#include
namespace ns {
int var = 0;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
int main(int argc, const char * argv[])
{
std::cout << "ns::var = " << ns::var << std::endl;
ns::fun();
return 0;
}
上述代码中,std::cout表示是使用标准库名字空间std中的成员cout;ns::var表示使用自定义名字空间ns中的成员var。
5.3 完整代码
本案例中的完整代码如下所示:
#include
namespace ns {
int var = 0;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
int main(int argc, const char * argv[])
{
std::cout << "ns::var = " << ns::var << std::endl;
ns::fun();
return 0;
}
6 名字空间指令
6.1 问题
名字空间指令表示在当前作用域中对某个名字空间的所有成员可见,而外层作用域的同名实体将被隐藏。
6.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:使用名字空间指令
代码如下所示:
#include
namespace ns {
int var = 0;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
using namespace ns;
int main(int argc, const char * argv[])
{
std::cout << "ns::var = " << var << std::endl;
fun();
return 0;
}
上述代码中,以下代码:
using namespace ns;
指定ns名字空间中的所有成员,在该行语句以下的所有语句中均可直接使用。
上述代码中,以下代码:
std::cout << "ns::var = " << var << std::endl;
变量var是ns名字空间中的变量,由于使用了名字空间指令,所以可以直接使用,其前面无需添加作用域限定符ns::。
步骤二:使用名字空间指令引发的冲突
代码如下所示:
#include
namespace ns {
int var = 0;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
namespace ns1 {
int var = 0;
}
如果有两个名字空间,ns和ns1,其中都有整型变量var,此时对它们同时使用名字空间指令using将引发冲突。代码如下所示:
#include
namespace ns {
int var = 0;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
namespace ns1 {
int var = 0;
}
using namespace ns;
using namespace ns1;
int main(int argc, const char * argv[])
{
std::cout << "ns::var = " << var << std::endl;
fun();
return 0;
}
上述代码中,以下代码:
using namespace ns;
using namespace ns1;
指定ns名字空间和ns1名字空间中的所有成员,在该行语句以下的所有语句中均可直接使用。这样就导致以下语句:
std::cout << "ns::var = " << var << std::endl;
中的变量var无法确定是ns中的还是ns1中的,而引发冲突。此时只能在变量前添加作用域限定符,代码如下:
std::cout << "ns::var = " << ns::var << std::endl;
或
std::cout << "ns::var = " << ns1::var << std::endl;
6.3 完整代码
本案例中的完整代码如下所示:
#include
namespace ns {
int var = 0;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
namespace ns1 {
int var = 100;
}
using namespace ns;
using namespace ns1;
int main(int argc, const char * argv[])
{
//std::cout << "ns::var = " << var << std::endl;
std::cout << "ns::var = " << ns::var << std::endl;
std::cout << "ns1::var = " << ns1::var << std::endl;
fun();
return 0;
}
7 名字空间声明
7.1 问题
名字空间声明表示在当前作用域中对某个名字空间的指定成员可见,而外层作用域的同名实体将被隐藏。
7.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:使用名字空间声明
代码如下所示:
#include
namespace ns {
int var = 0;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
using ns::var;
int main(int argc, const char * argv[])
{
std::cout << "ns::var = " << var << std::endl;
fun();
return 0;
}
上述代码中,以下代码:
using ns::var;
指定ns名字空间中的变量成员var,在该行语句以下的所有语句中均可直接使用。
上述代码中,以下代码:
std::cout << "ns::var = " << var << std::endl;
变量var是ns名字空间中的变量,由于使用了名字空间声明,所以可以直接使用,其前面无需添加作用域限定符ns::。
上述代码中,以下代码:
fun();
由于没有使用名字空间声明,所以报错,不能使用。
步骤二:使用名字空间声明引发的冲突
代码如下所示:
#include
namespace ns {
int var = 0;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
namespace ns1 {
int var = 0;
}
using ns::var;
using ns1::var;
上述代码中,以下代码:
using ns::var;
using ns1::var;
由于第一行使用名字空间声明已经在当前作用域内声明了变量var,所以第二行试图再在当前作用域内声明另一个名字空间的同名变量时将报错。
7.3 完整代码
本案例中的完整代码如下所示:
#include
namespace ns {
int var = 0;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
namespace ns1 {
int var = 0;
}
using ns::var;
using ns1::var;
int main(int argc, const char * argv[])
{
std::cout << "ns::var = " << var << std::endl;
ns::fun();
return 0;
}
8 名字空间声明与指令的区别
8.1 问题
名字空间声明将所声明的标识符引入当前作用域,就如同该标识符在当前作用域中被声明一样,是针对名字空间中的某个成员而言的。
名字空间指令只是将该名字空间指定为可见,并不对作用域构成任何影响,是针对名字空间中的所有成员而言的。
8.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:名字空间声明与指令的区别
代码如下所示:
#include
namespace ns {
int var = 10;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
namespace ns1 {
int var = 0;
}
using ns::fun;
using namespace ns1;
上述代码中,以下代码:
using ns::fun;
是名字空间声明,其作用仅是使名字空间ns中的fun函数成员在当前作用域有效。
上述代码中,以下代码:
using namespace ns1;
是名字空间指令,其作用是使名字空间ns1中的所有成员在当前作用域有效。
8.3 完整代码
本案例中的完整代码如下所示:
#include
namespace ns {
int var = 10;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
namespace ns1 {
int var = 0;
}
using ns::fun;
using namespace ns1;
int main(int argc, const char * argv[])
{
std::cout << "ns::var = " << var << std::endl;
fun();
return 0;
}
9 无名名字空间
9.1 问题
无名名字空间,又称为全局名字空间,不属于任何有名名字空间的标识符,都隶属于无名命名空间。全局作用域中定义的标识符被隐式地添加到无名名字空间中。
9.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:在无名名字空间中定义成员
代码如下所示:
#include
int var = 100;
int main(int argc, const char * argv[])
{
std::cout << "var = " << var << std::endl;
return 0;
}
上述代码中,全局变量var就定义在无名名字空间中。
步骤二:使用无名名字空间中成员的冲突
代码如下所示:
#include
namespace ns {
int var = 10;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
int var = 100;
int main(int argc, const char * argv[])
{
int var = 200;
std::cout << "var = " << var << std::endl;
std::cout << "::var = " << ::var << std::endl;
std::cout << "ns::var = " << ns::var << std::endl;
return 0;
}
上述代码中,以下代码:
std::cout << "var = " << var << std::endl;
变量var为局部变量,因为局部变量会隐藏全局变量,此时如果想要使用全局变量,需要在变量var前加作用域限定符::。
代码如下所示:
std::cout << "::var = " << ::var << std::endl;
9.3 完整代码
本案例中的完整代码如下所示:
#include
namespace ns {
int var = 10;
void fun (void){
int a = 10;
std::cout << "a = " << a << std::endl;
}
}
int var = 100;
int main(int argc, const char * argv[])
{
int var = 200;
std::cout << "var = " << var << std::endl;
std::cout << "::var = " << ::var << std::endl;
std::cout << "ns::var = " << ns::var << std::endl;
return 0;
}
10 多层名字空间
10.1 问题
多层名字空间,又称为名字空间的嵌套,是指定义在其他名字空中的名字空间。
10.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义多层名字空间
代码如下所示:
#include
namespace ns1 {
int var = 10;
namespace ns2 {
int var = 20;
void fun (void){
std::cout << "ns2::var = " << var << std::endl;
}
}
}
int main(int argc, const char * argv[])
{
std::cout << "ns1::var = " << ns1::var << std::endl;
ns1::ns2::fun();
return 0;
}
上述代码中,以下代码:
void fun (void){
std::cout << "ns2::var = " << var << std::endl;
}
中的变量var是名字空间ns2中的整型变量成员var,因为内层空间中的同名成员会隐藏外层空间中的同名成员。
上述代码中,以下代码:
ns1::ns2::fun();
对于内层名字空间中的成员的引用,需要通过作用域限定操作符逐层的分解。
10.3 完整代码
本案例中的完整代码如下所示:
#include
namespace ns1 {
int var = 10;
namespace ns2 {
int var = 20;
void fun (void){
std::cout << "ns2::var = " << var << std::endl;
}
}
}
int main(int argc, const char * argv[])
{
std::cout << "ns1::var = " << ns1::var << std::endl;
ns1::ns2::fun();
return 0;
}
11 C++的结构
11.1 问题
结构体是一种由用户定义的数据类型。在C和C++中都有结构体,但C++中的结构体对C语言中的结构体概念进行了扩充,主要表现在两个方面:首先在定义结构体变量时,C++的结构体可以省略struct关键字;第二点,C++中的结构体可以有函数成员。
11.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义C++结构
代码如下所示:
#include
struct User {
char name[256];
int age;
void who (void) {
std::cout << “我是” << name <<",今年" << age << “岁。” << std::endl;
}
};
int main(int argc, const char * argv[])
{
User user = {"张飞", 25};
user.who();
return 0;
}
上述代码中,以下代码:
void who (void) {
std::cout << "我是" << name <<",今年" << age << "岁。" << std::endl;
}
是定义在结构体User中的函数,在C++中这样定义是合法的。
上述代码中,以下代码:
User user = {"张飞", 25};
是定义结构体变量,并进行初始化。在定义变量时,C++允许省略关键字struct,直接使用结构体名做数据类型。
上述代码中,以下代码:
user.who();
是对结构体中函数的调用,其方法与引用数据成员相同。
11.3 完整代码
本案例中的完整代码如下所示:
#include
struct User {
char name[256];
int age;
void who (void) {
std::cout << “我是” << name <<",今年" << age << “岁。” << std::endl;
}
};
int main(int argc, const char * argv[])
{
User user = {"张飞", 25};
user.who();
return 0;
}
12 C++的匿名联合
12.1 问题
联合可以没有名字,被称为匿名联合。匿名联合仅仅通知编译器它的成员变量共同享一个地址,而变量本身是直接引用的,不使用通常的点号运算符语法。
12.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义匿名联合
代码如下所示:
#include
int main(int argc, const char * argv[])
{
union {
int n;
char c[sizeof (n)];
};
n = 0x12345678;
for (size_t i = 0; i < sizeof (c); ++i)
printf ("%#x ", c[i]); // 0x78 0x56 0x34 0x12
printf ("\n");
return 0;
}
上述代码中,以下代码:
union {
int n;
char c[sizeof (n)];
};
定义了一个匿名联合,因为整型变量n占4个字节,而字符数组c的元素个数为sizeof (n),即也是4个字节,所以整型变量n与字符数组c共用4个字节的地址空间。
上述代码中,以下代码:
n = 0x12345678;
将整型变量n赋值为0x12345678,而这个16进制数刚好占4个字节,由于整型变量n在内存中是倒着存放的,所以n所占的4个字节中第一个存放了十六进制数0x78,第二个存放的是0x56,第三个存放的是0x34,第四个存放的是0x12。又由于字符数组c与整型变量n共用4个字节,所以,以下代码:
for (size_t i = 0; i < sizeof (c); ++i)
printf ("%#x ", c[i]); // 0x78 0x56 0x34 0x12
printf ("\n");
将字符数组c逐个输出时,得到的结果是0x78 0x56 0x34 0x12。
12.3 完整代码
本案例中的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
union {
int n;
char c[sizeof (n)];
};
n = 0x12345678;
for (size_t i = 0; i < sizeof (c); ++i)
printf ("%#x ", c[i]); // 0x78 0x56 0x34 0x12
printf ("\n");
return 0;
}
13 C++的枚举
13.1 问题
枚举是一种由用户定义的数据类型。在C和C++中都有枚举,但C++中的枚举对C语言中的枚举概念进行了扩充,主要表现在两个方面:首先在定义枚举变量时,C++的枚举可以省略enum关键字;第二点,C++中的枚举是一种独立的数据类型。
13.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义匿名联合
代码如下所示:
#include
enum Color {
RED, YELLOW, BLUE, WHITE, BLACK
};
int main(int argc, const char * argv[])
{
Color color = RED;
int n;
n = YELLOW;
return 0;
}
上述代码中,以下代码:
Color color = RED;
定义了一个枚举类型Color的变量color,并初始化为RED。在C++中,定义是可以省略关键字enum。
上述代码中,以下代码:
int n;
n = YELLOW;
是错误的。在C++中不能将枚举常量直接赋值给一个整型变量。
13.3 完整代码
本案例中的完整代码如下所示:
#include
enum Color {
RED, YELLOW, BLUE, WHITE, BLACK
};
int main(int argc, const char * argv[])
{
Color color = RED;
int n;
n = YELLOW;
return 0;
}
14 字符串的基本用法
14.1 问题
字符串的基本用法主要是指字符串类对象的定义与初始化方法。
14.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:字符串的实例化
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str;
std::string str1("Hello World!");
std::string str2 = std::string();
std::string str3 = std::string("Hello World!");
std::string *pstr = new std::string;
std::string *pstr1 = new std::string();
std::string *pstr2 = new std::string("Hello World!");
return 0;
}
上述代码中,以下代码:
std::string str;
std::string str1("Hello World!");
是在栈中隐式实例化字符串类,第一条语句在栈上定义了一个空的字符串对象;第二条语句在栈上定义了一个字符串对象,然后调用构造函数对其进行初始化。
上述代码中,以下代码:
std::string str2 = std::string();
std::string str3 = std::string("Hello World!");
是在栈中显式实例化字符串类,第一条语句在栈上定义了一个空的字符串对象,然后将一个空的字符串临时对象初始化给它;第二条语句同样在栈上定义了一个空的字符串对象,然后将一个初始化好的临时字符串对象赋值给它。
上述代码中,以下代码:
std::string *pstr = new std::string;
std::string *pstr1 = new std::string();
std::string *pstr2 = new std::string("Hello World!");
是在堆中实例化字符串类,然后用字符串指针指向它。
步骤二:C++字符串与C字符串关系
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str;
std::string str1("Hello World!");
std::string str2 = std::string();
std::string str3 = std::string("Hello World!");
std::string *pstr = new std::string;
std::string *pstr1 = new std::string();
std::string *pstr2 = new std::string("Hello World!");
std::string str4 = "Hello World!";
char const *pc = "Hello World!";
std::string str5 = pc;
char sa[] = "Hello World!";
std::string str6 = sa;
char const *pc1 = str6.c_str();
return 0;
}
上述代码中,以下代码:
std::string str4 = "Hello World!";
可以将一个C语言的字符串直接赋值给一个C++的字符串。
上述代码中,以下代码:
char const *pc = "Hello World!";
std::string str5 = pc;
char sa[] = "Hello World!";
std::string str6 = sa;
可以将一个字符指针或一个字符数组赋值给一个C++的字符串。
上述代码中,以下代码:
char const *pc1 = str6.c_str();
如果希望用字符指针指向C++的字符串,则需要调用字符串类中的c_str()函数,该函数能够返回字符串对象中所存储的字符串数据在内存的地址。
14.3 完整代码
本案例中的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str;
std::string str1("Hello World!");
std::string str2 = std::string();
std::string str3 = std::string("Hello World!");
std::string *pstr = new std::string;
std::string *pstr1 = new std::string();
std::string *pstr2 = new std::string("Hello World!");
std::string str4 = "Hello World!";
char const *pc = "Hello World!";
std::string str5 = pc;
char sa[] = "Hello World!";
std::string str6 = sa;
char const *pc1 = str6.c_str();
return 0;
}
15 字符串的基本运算
15.1 问题
字符串的基本运算主要包括字符串的拼接、赋值和关系运算。
15.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:字符串的拼接
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello ";
std::string str2 = "World!";
std::string str3 = str1 + str2;
return 0;
}
上述代码中,以下代码:
std::string str3 = str1 + str2;
是将字符串str2的内容拼接到字符串str1的最后一个字符后面,形成一个更大的字符串,赋值给str3。
步骤二:字符串的赋值
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello ";
std::string str2 = "World!";
std::string str3 = str1 + str2;
std::string str4 = "Hello ";
std::string str5 = "World!";
std::string str6;
str6 = str5;
str4 += str5;
return 0;
}
上述代码中,以下代码:
str6 = str5;
是实现字符串对象间的相互赋值,将str5赋值给str6。
上述代码中,以下代码:
str4 += str5;
是实现字符串对象间的复合赋值,本语句实现的是将str4与str5拼接后在赋值给str4。
步骤三:字符串的关系运算
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello ";
std::string str2 = "World!";
std::string str3 = str1 + str2;
std::string str4 = "Hello ";
std::string str5 = "World!";
std::string str6;
str6 = str5;
str4 += str5;
std::string str7 = "zhangfei";
std::string str8 = "zhaoyun";
if (str7 == str8)
std::cout << str7 << "==" << str8 << std::endl;
else if (str7 < str8)
std::cout << str7 << "<" << str8 << std::endl;
else
std::cout << str7 << ">" << str8 << std::endl;
return 0;
}
上述代码中,以下代码:
if (str7 == str8)
是判断字符串str7与str8是否相等,其判断的方法是将两个字符串的对应字符进行比较,如果相同则比较下一个对应字符,直到有不同或两个字符串同时结束为止。本例中str7与str8的第一对对应字符是z,第二对对应字符是h,第三对对应字符是a,第四对对应字符是n和o,依次类推。
注意:对应字符进行比较时,是区分大小写的,即a和A是两个不同的字符。
15.3 完整代码
本案例中的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello ";
std::string str2 = "World!";
std::string str3 = str1 + str2;
std::string str4 = "Hello ";
std::string str5 = "World!";
std::string str6;
str6 = str5;
str4 += str5;
std::string str7 = "zhangfei";
std::string str8 = "zhaoyun";
if (str7 == str8)
std::cout << str7 << "==" << str8 << std::endl;
else if (str7 < str8)
std::cout << str7 << "<" << str8 << std::endl;
else
std::cout << str7 << ">" << str8 << std::endl;
return 0;
}
16 字符串的大小和容量
16.1 问题
字符串的大小或长度是指该字符串实际容纳的字符数,而字符串的容量是该字符串最多容纳的字符数。
16.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:字符串的大小
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::cout << str1.size() << std::endl;
std::cout << str1.length() << std::endl;
str1.resize(20, 'a');
std::cout << str1 << std::endl;
return 0;
}
上述代码中,以下代码:
std::cout << str1.size() << std::endl;
std::cout << str1.length() << std::endl;
中的size()和length()成员函数都能获得字符串实际容纳的字符数,length()函数是较早版本的,size()是为了和容器类保持一致新添加的。
上述代码中,以下代码:
str1.resize(20, 'a');
是用来更改字符串实际容纳的字符数的,当第一个参数小于原字符串实际容纳的字符数时,字符串将只保留第一个参数指定的前几个字符,当第一个参数大于原字符串实际容纳的字符数时,字符串多出来的空间将有第二个参数填补。
步骤二:字符串的容量
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::cout << str1.size() << std::endl;
std::cout << str1.length() << std::endl;
str1.resize(20, 'a');
std::cout << str1 << std::endl;
std::cout << str1.capacity() << std::endl;
str1.reserve(50);
std::cout << str1.capacity() << std::endl;
return 0;
}
上述代码中,以下代码:
std::cout << str1.capacity() << std::endl;
获取的是字符串最多容纳的字符数。由于字符串可以动态改变,所以在向字符串添加字符时,字符串会变长,但不是添加一个字符就只变长一个字节,而是变长单位长度的字节数,这样做的好处是避免频繁内存操作,提高效率。
上述代码中,以下代码:
str1.reserve(50);
可以指定字符串的容量。
16.3 完整代码
本案例中的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::cout << str1.size() << std::endl;
std::cout << str1.length() << std::endl;
str1.resize(20, 'a');
std::cout << str1 << std::endl;
std::cout << str1.capacity() << std::endl;
str1.reserve(50);
std::cout << str1.capacity() << std::endl;
return 0;
}
17 字符串拼接
17.1 问题
字符串拼接是指将两个字符串连接在一起,形成一个更长的字符串。
17.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:字符串拼接
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello ";
std::string str2 = "World!";
str1.append(str2);
std::cout << str1 << std::endl;
std::string str3 = "Hello ";
std::string str4 = "Hello World!";
str3.append(str4, 6, 6);
std::cout << str3 << std::endl;
std::string str5 = "Hello ";
str5.append(10, 'A');
std::cout << str5 << std::endl;
return 0;
}
上述代码中,以下代码:
str1.append(str2);
将字符串str2拼接到字符串str1的后面。
上述代码中,以下代码:
str3.append(str4, 6, 6);
将字符串str4的第6字符开始的连续6个字符,拼接到字符串str3的后面。该函数的第二个参数是从第一个参数的第几个字符开始计算,注意从0开始计算;第三个参数是从第二个参数开始的连续几个字符被拼接。
上述代码中,以下代码:
str5.append(10, 'A');
将10个A拼接到字符串str5的后面。
17.3 完整代码
本案例中的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello ";
std::string str2 = "World!";
str1.append(str2);
std::cout << str1 << std::endl;
std::string str3 = "Hello ";
std::string str4 = "Hello World!";
str3.append(str4, 6, 6);
std::cout << str3 << std::endl;
std::string str5 = "Hello ";
str5.append(10, 'A');
std::cout << str5 << std::endl;
return 0;
}
18 在字符串中搜索特定字符
18.1 问题
在字符串中搜索特定字符是指在字符串中寻找是否存在指定的字符或字符集。
18.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:正向查找
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::cout << str1.find_first_of('o') << std::endl;
std::string str2 = "World!";
std::cout << str1.find_first_of(str2) << std::endl;
std::cout << str1.find_first_not_of('o') << std::endl;
std::cout << str1.find_first_not_of(str2) << std::endl;
return 0;
}
上述代码中,以下代码:
std::cout << str1.find_first_of('o') << std::endl;
是在字符串str1中查找是否存在字符o,如果存在,则返回字符串中第一个o的位置。
上述代码中,以下代码:
std::cout << str1.find_first_of(str2) << std::endl;
是在字符串str1中查找是否存在字符集str2中的字符,如果存在,则返回字符串中第一个字符集str2中有的字符的位置。
上述代码中,以下代码:
std::cout << str1.find_first_not_of('o') << std::endl;
是在字符串str1中查找第一个与字符o不相同的字符的位置。
上述代码中,以下代码:
std::cout << str1.find_first_not_of(str2) << std::endl;
是在字符串str1中查找第一个与字符集str2中字符不相同的字符的位置。
步骤二:反向查找
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::cout << str1.find_first_of('o') << std::endl;
std::string str2 = "World!";
std::cout << str1.find_first_of(str2) << std::endl;
std::cout << str1.find_first_not_of('o') << std::endl;
std::cout << str1.find_first_not_of(str2) << std::endl;
std::cout << str1.find_last_of('o') << std::endl;
std::cout << str1.find_last_of(str2) << std::endl;
std::cout << str1.find_last_not_of('o') << std::endl;
std::cout << str1.find_last_not_of(str2) << std::endl;
return 0;
}
上述代码中,以下代码:
std::cout << str1.find_last_of('o') << std::endl;
是在字符串str1中查找是否存在字符o,如果存在,则返回字符串从后向前查找的第一个o的位置。
上述代码中,以下代码:
std::cout << str1.find_first_of(str2) << std::endl;
是在字符串str1中查找是否存在字符集str2中的字符,如果存在,则返回字符串中从后向前查找的第一个字符集str2中有的字符的位置。
上述代码中,以下代码:
std::cout << str1.find_first_not_of('o') << std::endl;
是在字符串str1中从后向前查找的第一个与字符o不相同的字符的位置。
上述代码中,以下代码:
std::cout << str1.find_first_not_of(str2) << std::endl;
是在字符串str1中从后向前查找的第一个与字符集str2中字符不相同的字符的位置。
18.3 完整代码
本案例中的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::cout << str1.find_first_of('o') << std::endl;
std::string str2 = "World!";
std::cout << str1.find_first_of(str2) << std::endl;
std::cout << str1.find_first_not_of('o') << std::endl;
std::cout << str1.find_first_not_of(str2) << std::endl;
std::cout << str1.find_last_of('o') << std::endl;
std::cout << str1.find_last_of(str2) << std::endl;
std::cout << str1.find_last_not_of('o') << std::endl;
std::cout << str1.find_last_not_of(str2) << std::endl;
return 0;
}
19 从字符串中提取子字符串
19.1 问题
从字符串中提取子字符串是指将一个字符串中的一部分截取下来形成一个新的字符串。
19.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:截取子串
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::string str2(str1, 0, 6);
std::cout << str2 << std::endl;
std::string str3 = str1.substr(6, 6);
std::cout << str3 << std::endl;
return 0;
}
上述代码中,以下代码:
std::string str2(str1, 0, 6);
定义一个新的字符串str2,其内容被初始化成字符串str1的第0个字符开始的连续6个字符。第二个参数是从第一个参数的第几个字符开始截取,第三个参数是连续截取几个字符。
上述代码中,以下代码:
std::string str3 = str1.substr(6, 6);
是在字符串str1中截取第6个字符开始的连续6个字符作为一个新的字符串,赋值给str3。第一个参数是从str1的第几个字符开始截取,第二个参数是连续截取几个字符。
19.3 完整代码
本案例中的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::string str2(str1, 0, 6);
std::cout << str2 << std::endl;
std::string str3 = str1.substr(6, 6);
std::cout << str3 << std::endl;
return 0;
}
20 访问字符串中的单个字符
20.1 问题
访问字符串中的单个字符是像字符数组那样使用下标访问字符串中的某个元素。
20.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:访问字符串中的单个字符
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::cout << str1[2] << std::endl;
std::cout << str1[20] << std::endl;
std::cout << str1.at(6) << std::endl;
std::cout << str1.at(20) << std::endl;
return 0;
}
上述代码中,以下代码:
std::cout << str1[2] << std::endl;
是像访问字符数组那样,将字符串中的第2个字符提取出来显示。值得注意的是如果下标越界,如下代码所示:
std::cout << str1[20] << std::endl;
不会报告错误。
上述代码中,以下代码:
std::cout << str1.at(6) << std::endl;
是使用成员函数来获得字符串中的第6个字符并显示。值得注意的是如果参数越界,如下代码所示:
std::cout << str1.at(20) << std::endl;
函数将抛出异常。
20.3 完整代码
本案例中的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::cout << str1[2] << std::endl;
std::cout << str1[20] << std::endl;
std::cout << str1.at(6) << std::endl;
std::cout << str1.at(20) << std::endl;
return 0;
}
21 字符串的查找与替换
21.1 问题
字符串的查找是指查看在字符串中是否有另一个指定的子串。字符串的替换是指将字符串中指定部分替换成指定的内容。
21.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:字符串的查找
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::cout << str1.find("o") << std::endl;
std::cout << str1.find("o", 5) << std::endl;
std::cout << str1.rfind("o") << std::endl;
std::cout << str1.rfind("o", 5) << std::endl;
return 0;
}
上述代码中,以下代码:
std::cout << str1.find("o") << std::endl;
在字符串str1中查看是否有o,如果有则返回字符o在字符串str1中的位置,否则返回npos,即-1。
上述代码中,以下代码:
std::cout << str1.find("o", 5) << std::endl;
在字符串str1中的第5个位置开始向后查看是否有o,如果有则返回字符o在字符串str1中的位置。
上述代码中,以下代码:
std::cout << str1.rfind("o") << std::endl;
在字符串str1中从后向前查看是否有o,如果有则返回字符o在字符串str1中的位置。
上述代码中,以下代码:
std::cout << str1.rfind("o", 5) << std::endl;
在字符串str1中的第5个位置开始向前查看是否有o,如果有则返回字符o在字符串str1中的位置。
步骤二:字符串的替换
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::cout << str1.find("o") << std::endl;
std::cout << str1.find("o", 5) << std::endl;
std::cout << str1.rfind("o") << std::endl;
std::cout << str1.rfind("o", 5) << std::endl;
std::string str2 = "Tarena";
str1.replace(6, 5, str2);
std::cout << str1 << std::endl;
return 0;
}
上述代码中,以下代码:
str1.replace(6, 5, str2);
是将字符串str1中第6个字符开始的连续5个字符替换成字符串str2的内容。
21.3 完整代码
本案例中的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::cout << str1.find("o") << std::endl;
std::cout << str1.find("o", 5) << std::endl;
std::cout << str1.rfind("o") << std::endl;
std::cout << str1.rfind("o", 5) << std::endl;
std::string str2 = "Tarena";
str1.replace(6, 5, str2);
std::cout << str1 << std::endl;
return 0;
}
22 字符串的比较与排序
22.1 问题
字符串的比较是指将两个字符串的对应字符进行比较,如果相同则对比下一对对应字符,知道不同或两个字符串同时结束。
字符串排序是指将字符串数组按指定顺序进行排序。
22.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:字符串的比较
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::string str2 = "Hello World!";
std::cout << str1.compare(str2) << std::endl;
return 0;
}
上述代码中,以下代码:
std::cout << str1.compare(str2) << std::endl;
是将字符串str1中的第一个字符与字符串str2中的第一个字符进行比较,如果相同,则对比各自的第二个字符,直到两个字符串结束,如果一直相同,则返回0;如果有不同的,则str1中的字符的ASCII码大于str2中的ASCII码,则返回整数;否则返回负数。
步骤二:字符串的排序
代码如下所示:
#include
int strCmp (const void* a, const void* b) {
return ((std::string const)a).compare ((std::string const)b);
}
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::string str2 = "Hello World!";
std::cout << str1.compare(str2) << std::endl;
std::string str3[] = {"chongqing", "tianjin", "beijing",_ "shanghai"};
size_t size = sizeof (str3[0]);
size_t nmemb = sizeof (str3) / size;
qsort (str3, nmemb, size, strCmp);
for (int i = 0; i < nmemb; i++)
std::cout << str3[i] << std::endl;
return 0;
}
上述代码中,以下代码:
size_t size = sizeof (str3[0]);
是求字符数组str3的第一个元素所占的字节数。该值是作为qsort函数的参数使用。
上述代码中,以下代码:
size_t nmemb = sizeof (str3) / size;
是求字符数组的元素个数。该值也是作为qsort函数的参数使用。
上述代码中,以下代码:
qsort (str3, nmemb, size, strCmp);
是调用库函数qsort对数组str3进行排序。该函数的第一个参数是要排序的数组名,第二个参数是要排序的数组的元素个数,第三个参数是要排序的数组的每个元素所占的字节数,第四个参数是排序条件,它是一个函数的函数名。该函数如下所示:
int strCmp (const void* a, const void* b) {
return ((std::string const)a).compare ((std::string const)b);
}
22.3 完整代码
本案例中的完整代码如下所示:
#include
int strCmp (const void* a, const void* b) {
return ((std::string const)a).compare ((std::string const)b);
}
int main(int argc, const char * argv[])
{
std::string str1 = "Hello World!";
std::string str2 = "Hello World!";
std::cout << str1.compare(str2) << std::endl;
std::string str3[] = {"chongqing", "tianjin", "beijing", "shanghai"};
size_t size = sizeof (str3[0]);
size_t nmemb = sizeof (str3) / size;
qsort (str3, nmemb, size, strCmp);
for (int i = 0; i < nmemb; i++)
std::cout << str3[i] << std::endl;
return 0;
}
23 字符串的插入与删除
23.1 问题
字符串的插入是指在字符串中指定的位置插入指定的字符串。字符串删除是指在字符串中指定的位置删除指定长度个字符。
23.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:字符串的插入
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hed!";
std::string str2 = "llo Worl";
std::cout << str1.insert(2, str2) << std::endl;
return 0;
}
上述代码中,以下代码:
std::cout << str1.insert(2, str2) << std::endl;
是在字符串str1的第2个位置插入字符串str2的所有内容。
步骤二:字符串的删除
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hed!";
std::string str2 = "llo Worl";
std::cout << str1.insert(2, str2) << std::endl;
std::cout << str1.erase(2, 8) << std::endl;
return 0;
}
上述代码中,以下代码:
std::cout << str1.erase(2, 8) << std::endl;
是从字符串str1的第2个字符开始,连续删除8个字符。
23.3 完整代码
本案例中的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hed!";
std::string str2 = "llo Worl";
std::cout << str1.insert(2, str2) << std::endl;
std::cout << str1.erase(2, 8) << std::endl;
return 0;
}
24 字符串的交换与复制
24.1 问题
字符串的交换是指将两个字符串的内容互相交换。字符串复制是指生成一个新的字符串其内容为原有字符串的内容。
24.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:字符串的交换
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello ";
std::string str2 = "World!";
swap(str1, str2);
std::cout << str1 << std::endl;
std::cout << str2 << std::endl;
return 0;
}
上述代码中,以下代码:
swap(str1, str2);
是将字符串str1的内容与字符串str2的内容进行交换。
步骤二:字符串的复制
代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello ";
std::string str2 = "World!";
swap(str1, str2);
std::cout << str1 << std::endl;
std::cout << str2 << std::endl;
std::string str3 = "Hello World!";
std::string str4;
str4.assign(str3);
std::cout << str4 << std::endl;
std::string str5;
str5.assign(str3, 2, 8);
std::cout << str5 << std::endl;
return 0;
}
上述代码中,以下代码:
str4.assign(str3);
是将字符串str3中的所有字符复制到字符串str4中。
上述代码中,以下代码:
str5.assign(str3, 2, 8);
是将字符串str3中的第2个字符开始连续8个字符复制到字符串str5中。
24.3 完整代码
本案例中的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
std::string str1 = "Hello ";
std::string str2 = "World!";
swap(str1, str2);
std::cout << str1 << std::endl;
std::cout << str2 << std::endl;
std::string str3 = "Hello World!";
std::string str4;
str4.assign(str3);
std::cout << str4 << std::endl;
std::string str5;
str5.assign(str3, 2, 8);
std::cout << str5 << std::endl;
return 0;
}
25 布尔类型
25.1 问题
布尔类型是表示布尔量的数据类型,其值只有真(true)和假(false)两个值,布尔类型的数据占1个字节的存储空间。
25.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:布尔类型
代码如下所示:
#include
int main(int argc, const char * argv[])
{
bool b;
b = true;
b = false;
std::cout << std::boolalpha << b << std::endl;
std::cout << sizeof(bool) << std::endl;
b = 5;
b = 5.5;
b = 'a';
std::cout << std::boolalpha << b << std::endl;
return 0;
}
上述代码中,以下代码:
bool b;
b = true;
b = false;
定义了布尔类型变量b,并将其赋值为true和false。
上述代码中,以下代码:
std::cout << sizeof(bool) << std::endl;
从运行结果可以看出,布尔类型占1个字节的存储空间。
上述代码中,以下代码:
b = 5;
b = 5.5;
b = 'a';
表示任何基本数据类型的数据均可直接复制给布尔变量b。
25.3 完整代码
本案例中的完整代码如下所示:
#include
int main(int argc, const char * argv[])
{
bool b;
b = true;
b = false;
std::cout << std::boolalpha << b << std::endl;
std::cout << sizeof(bool) << std::endl;
b = 5;
b = 5.5;
b = 'a';
std::cout << std::boolalpha << b << std::endl;
return 0;
}