目录
字符串的处理——string类型
string s4 {8, 'A'};
定义字符串s4的初值是8个A
cout << "s4=" << s4 << "s4的长度是:" << s4.length() << endl;
串名.length() 用于求串的长度
s2 = s3 + ' ' + s4;
串名+串名 可以实现字符串之间的联结
s3.insert(7, "&teacher");
表示向s3的7下标出插入&teacher
s3.replace(2, 4, "ar");
表示将s3从
2下标开始长度为4
的子串替换成ar
s1 = s3.substr(6, 7);
表示将s3从下标
6开始长度为7
的字串
赋值
给s1
int pos = s3.find(s1);
表示在s3中查询s1是否存在,
若存在则返回s1在s3中第一个字符的下标
s3.erase(5, 8);
表示删除s3从
5下标开始的8个字符
bool f = s1 > s4;
关系运算符可以比较字符串的大小
关系运算符里的两个函数:
boolalpha
将布尔值显示为ture或者flase
noboolalpha
将布尔值显示为0或者1
名字空间的定义及使用
名字空间的定义:
namespace one
{
const int M = 200;
int inf = 10;
int x;
}
namespace 名字空间名称{…;…;}//最后大括号外面不用加分号
使用名字空间中的内容:
F1:名字空间名称::局部内容名
如:one::inf*=2;
F2:using namespace 名字空间名称;//作用是以一个申明
如:using namespace one;
F3:using 名字空间名称::局部内容名;
如:using one ::x;
相比C语言函数相关的改进
1.扩大全局变量的作用域
在C语言中,全局变量的作用域虽然从定义开始到程序结束,但是在同名局部变量作用域内,该全局变量不可见,C++对此进行了改进。
可在全局变量前加上域解析符“::”来访问被隐藏的全局变量。
示例如下:
::sum += sum;
2.形式参数可带有默认值
在C语言中,调用函数时实参必须与形参的个数保持相等,没有实参形参就无法得到相应的值。
但是在C++中允许函数原型申明中为一个或多个形参指定默认参数值,这样在调用函数时,可以不必提供实参,当然如果提供了实参那么还是将实参带到函数里,所以在C++中实参的个数小于等于形参。
示例如下:
void Fun(int i, int j = 5, int k = 10);
Fun(20);
注意:
1.默认参数值如果在函数原型中已经给出了,那么在函数定义首部不必再次出现。如果原型中没有给出,那么函数定义首部可以出现。
2.默认参数值的给定一定是
从右往左
的,所以诸如void Fun(int i, int j , int k = 10);
void Fun(int i=1, int j = 5, int k = 10);都是对的.但是像void Fun(int i, int j = 5, int k );就是错误的了。
3.实参提供的顺序是
从左往右
。
3.函数重载
在C语言中,同一作用域范围内函数名必须是唯一的。这就造成了完成同一或相似功能的函数必须定义不同的名称,增加了记忆负担。。
在C++中对于功能完全相同或类似的,只在
形参的个数,类型和顺序
存在差异的函数,可以用相同的函数名来命名,这种情况被称为
重载
。
下面通过一段代码来对重载进行示例:
#include<iostream>
using namespace std;
int square(int x)
{
return x*x;
}
float square(float x)
{
return x * x;
}
double square(double x=1.5)
{
return x * x;
}
int main()
{
cout << "square()=" << square() << endl;
cout << "square(10)=" << square(10) << endl;
cout << "square(2.5f)=" << square(2.5f) << endl;
cout << "square(1.1)=" << square(1.1) << endl;
return 0;
}
运行结果如下:
square()=2.25
square(10)=100
square(2.5f)=6.25
square(1.1)=1.21
注意:
1.重载函数必须具有
相同的函数名
,但是在
形参的个数,类型,顺序的一个或几个方面必须存在不同
,返回值不是区分重载函数的要素。
例如:void Fun(int)与int Fun(int )是错误的重载函数,它们的形参一样,仅返回值不同,不符合要求。
2.在函数调用时,如果给出的实参与形参的类型不相符,编译器会自动进行类型转化。
引用的定义与应用
引用是C++新增的概念,用来为变量起别名,在声明时通过“&”来标记。
格式如下:数据类型 &引用名=一个已定义的变量名
代码演示:
int x=5;
int &r=x;
说明:
1.引用被声明以后就可以像普通变量一样使用,使用时不用再带“&”符号。
2.引用只是一个变量的别名,所以系统不会为它另外开辟新的空间,像上面代码中r和x占用的是同一段空间。
2.并不是任何类型的数据都可以由引用,像void & r=x; int &&r=x; int &*p=x; int &ra[10]; 都是错误的。(即不能建立void类型的引用,引用的引用,指向引用的指针,引用数组)
引用作为形参
在C++中引用最常用的用途是作为函数的形参,这样就可以通过
对引用的访问和修改达到对实参进行操作的效果
。
与引用形参对应的实际参数只能是变量,而不能是常量或者表达式。
可以在引用参数之前
加上const修饰使其变成常引用
,一旦修改常引用形参,编译器就会报错,这在语法上保证了实参的安全性。
引用与指针的比较
有一种观点认为“引用是能自动间接引用的一种指针”。
以交换值的函数演示两者之间的区别:
void swap(int &x,int &y)
{
int t = x;
x = y;
y = t;
}
void swap(int* x, int* y)
{
int t = *x;
*x = *y;
*y = t;
}
上面这个函数中x,y不会另外占用空间,与实参共享空间。
下面这个函数x,y需要额外占用空间,获得的是实参的地址。
引用作为返回值
原型声明如下:
类型名 & 函数名 (形参表)
int &Fun(const int &x,int &y,int z)
它可以作为赋值的左值使用如:Fun(a,b,c)=20;
说明:
return后面只能是变量,而不能是常量或表达式,因为只有变量才能作左值。
return后面变量的内存空间在本次函数调用结束后仍要存在,所以自动局部变量不能作为返回值。
return后面的变量不能是常引用,这样作为左值时会改变它的值,编译器会报错。
动态内存空间管理
在C语言中通过malloc,calloc函数申请动态内存空间,free来释放空间。
在C++中则通过new和delete来实现这些操作。(new和delete是运算符而不是函数)
用new申请动态内存空间:
比较C与C++在申请动态空间上的区别:
申请一个int型动态的变量:
int *ptr = (int*)
malloc(sizeof(int));//C
ptr = new int;//C++
申请N个元素的动态一维数组:
ptr = (int*)
malloc(N * sizeof(int));//C
ptr = new int[N];//C++
申请N行M列的动态二维数组:
int* q = (int**)
malloc(N * sizeof(int*));
for (i = 0; i < N; i++)
q[i] = (int*)
malloc(M * sizeof(int));//C
q = new int* [N];
for (i = 0; i < N; i++)
q[i] = new int[M];//C++
用delete释放动态内存空间:
示范代码如下:
ptr = new int;
delete ptr;
ptr = new int[N];
delete[]ptr;
q = new int* [N];
for (i = 0; i < N; i++)
q[i] = new int[M];
for (i = 0; i < N; i++)
delete[]q[i];
delete[]q;
下面通过一个例子加深对其的了解:
生成N个0-99的随机整数,统计其中奇数的个数。用一个动态一维数组存放N个随机数,用一个动态整形变量存放统计结果。
#include<iostream>
#include<iomanip>
#include<cmath>
#include<ctime>
using namespace std;
const int N= 30;
int main()
{
int* p, * sum, i;
sum = new int(0);
p = new int[N];
if (p == NULL)
{
cout << "allocation failure!\n";
return 0;
}
srand(time(NULL));
for (i = 0; i < N; i++)
{
p[i] = rand() % 100;
if (p[i] % 2)
(*sum)++;
}
for (i = 0; i < N; i++)
{
cout << setw(4) << p[i];
if ((i + 1) % 10 == 0)
cout << endl;
}
cout << "The number of odd is:" << *sum << endl;
delete[]p;
delete sum;
return 0;
}
上面申请动态内存空间用sum=new int (0)而不是sum=new int。因为后面这个语句得到的sum的初值是随机值,所以前面这个语句给sum赋了初值0,就保证了最后结果的正确性。
异常处理
程序中的
错误
可分为语法错误和运行错误。语法错误包括编译错误和链接错误,运行错误是编译,链接通过后,程序在运行时出现的错误。
异常
指的是不同,即与期待的结果不同,它是一种错误,但不是上述中的错误。例如某个月份是13,就可以认为是异常。
在C++中,异常处理通过以下三步来实现
1.检查异常(使用try语句块)
2.抛出异常(使用throw语句块)
3.捕捉异常(使用catch语句块)
下面通过代码来进行演示:
#include<iostream>
using namespace std;
int divide(int x, int y)
{
if (y == 0)throw y;
return x / y;
}
int main()
{
int a = 10, b = 5, c = 0;
try
{
cout << "a/b=" << divide(a, b) << endl;
cout << "b/a=" << divide(b, a) << endl;
cout << "a/c=" << divide(a, c) << endl;
cout << "c/a=" << divide(c, a) << endl;
}
catch (int)
{
cout << "except of divide zero" << endl;
}
cout << "calculate finished" << endl;
return 0;
}
注意:
1.try-catch语句必须同时出现,并且try在前,catch在后。
2.try和catch块之间不能有其他的语句。
2.只能有一个try块,但是可以有很多个catch块。