目录
【例1.1】输出一行字符“This is a C++ program.”
一、从C到C++
C语言是结构化和模块化的语言,C语言的设计者必须细致地设计程序中的每个细节,准确地考虑程序运行时每一时刻发生的事情,当程序规模变大时,结构化程序设计就显得力不从心。
C++既可以用于面向过程的结构化程序设计,也可用于面向对象的程序设计。C++对C的增强体现在两个方面:
- 对原来的面向过程机制做了扩充
- 增加了面向对象的机制
学习C++之后,既可以进行面向对象的程序设计,也可以进行面向过程的程序设计。
二、C++语言的词法和词法规则
1.C++语言的字符集
等同于C语言的字符集,包括:
- 大小写英文字母
- 数字字符
- 其他ASCII码字符
2.单词及词法规则
单词是构成语句的关键成份之一,通常由若干字符组成,C++有几种单词:
(1)关键字
是C++语言中的命令字,它是预定义好的单词,C++编译程序对其有专门的解释。如int、float、if、else、while、switch等等。
(2)标识符
程序员用标识符对程序中的元素实施命名,包括函数名、类名、对象名、类型名、变量名、常变量名、数组名等。
标识符以字母或下划线开始,后跟字母、数字、下划线。标识符区分大小写字母。
(3)运算符
运算符代表某种操作的单词,由一个或多个字符组成。注意运算符的优先级和综合顺序。
(4)分隔符
在语句中关键字和标识符之间、各个语句之间要用分隔符分开。C++常用的分隔符有空格、逗号、分号、冒号大括号。
(5)注释符
C++提供了两种注释符:
- /* 注释 */
- // 注释
三、最简单的C++程序
【例1.1】输出一行字符“This is a C++ program.”
#include <iostream> //用cout输出时需要用
using namespace std; //使用命名空间std
int main()
{
cout << "This is a C++ program.\n";
return 0;
}
【注】
- 标准C++规定main函数必须声明为int类型,如果程序正常运行,向操作系统返回一个零值,否则返回非零值,通常是-1
- C++程序可以用/* 注释 */做多行注释,也可以用// 做单行注释
- C++程序常用cout、cin进行输出输入,cout是C++定义的输出流对象,<<是插入运算符
- 使用cout、cin需要用头文件iostream,在程序开始要用#include声明包含的头文件
- using namesapce std;意思是使用命名空间。C++标准库中的类和函数是在命名空间std中声明的,因此程序中如果用C++标准库中的有关内容(此时需要用#include命令行),就要用using namespace std;语句声明
【例1.2】求a和 b两个数之和
#include<iostream> //预处理命令
using namespace std; //使用命名空间
int main()
{
int a,b,sum;
cin>>a>>b;
sum=a+b;
cout<<"a+b="<<sum<<endl;
return 0;
}
【注】
- cin是C++定义的输入流对象。“>>”是提取运算符,与cin配合,其作用是从设备中提取数据送到输入流cin中。在程序执行时,键盘输入的第一个数据赋予a,第二个数据赋予b
- cout语句中大哥endl是C++控制符函数,作用是让光标换行
【例1.3】求两个数中的大数
#include <iostream>
using namespace std;
int main()
{
int max(int x, int y); //对max函数做声明
int a, b, c;
cin >> a >> b;
c = max(a, b); //调用max函数
cout << "max=" << c << endl;
return 0;
}
int max(int x, int y)
{ //定义max函数
int z;
if (x > y)
z = x;
else
z = y;
return (z);
}
四、C++对C的扩充
1.C++的输入输出
C++为了方便使用,除了可以利用printf和scanf函数进行输入和输出外,还增加了标准输入流输出流cin和cout。他们是在头文件iostream中定义的,标准流是不需要打开文件和关闭文件就能直接操作的流式文件,在此标准输入流是指从键盘上输入的数据,标准输出流是指向屏幕输出的数据流。
C++预定义的标准流 | ||
流名 | 含义 | 隐含设备 |
cin | 标准输入 | 键盘 |
cout | 标准输出 | 屏幕 |
cerr | 标准出错输出 | 屏幕 |
clog | cerr缓冲形式 | 屏幕 |
(1)用cout进行输出
- 【格式】cout<<表达式1[<<表达式2……]
- 【功能】由左向右逐个计算表达式的值,将其插入到输出流cout中
- cout必须与输出运算符<<一起使用,每个<<后跟一个表达式,<<运算符的结合方向是从左向右,所以各个表达式的值按从左到右的顺序插入到输出流中
- endl是C++输出流的常数,在头文件iostream中定义,代表让光标换行。在C++中也可以用“\n”控制光标换行。
(2)用cin进行输入
- 【格式】cin>>变量1[>>变量2……]
- >>是C++的提取运算符,表示从标准输入设备取得数据,赋予其后的变量
- 从键盘输入数值数据时,两个数据之间用空格分隔或用回车分隔
(3)cin和cout的使用
#include <iostream>
using namespace std;
int main() {
cout << "please enter your name and age:" << endl;
char name[10];
int age;
cin >> name;
cin >> age;
cout << "your name is" << name << endl;
cout << "your age is" << age << endl;
return 0;
}
2.用const定义常变量
(1)格式
const 类型 变量名 = 常数
(2)例
const float PI = 3.14159;
3.函数原型声明
(1)含义
C++规定,如果函数调用在函数定义之前,要求在调用之前声明该函数的原型
(2)格式
函数类型 函数名(形参表)
- 形参表中形参可以只写类型。例:int max(int x,int y);或int max(int ,int );其实C++编译时,只检查参数的数据类型
4.函数的重载
(1)含义
C++允许在同一个域中用一个函数名定义多个函数,这些函数的函数参数、参数类型不相同。用一个函数名实现不同的功能,就是函数的重载。
(2)例1.6
设计程序计算三个数中的大数
#include<iostream>
using namespace std;
int max(int a,int b,int c) //求3个整数中的最大者
{
if(b>a) a=b;
if(c>a) a=c;
return a;
}
int max(float a,float b,float c) //求三个实数中的最大者
{
if(b>a) a=b;
if(c>a) a=c;
return a;
}
int max(long a,long b,long c) //求三个长整数中的最大者
{
if(b>a) a=b;
if(c>a) a=c;
return a;
}
int main()
{
int a,b,c,m;
float d,e,f,n;
long g,h,i,p;
cin>>a>>b>>c;
cin>>d>>e>>f;
cin>>g>>h>>i;
m=max(a,b,c);
n=max(d,e,f);
p=max(g,h,i);
cout<<"max_int"<<m<<endl;
cout<<"max_float"<<n<<endl;
cout<<"max_long"<<p<<endl;
return 0;
}
- 下面的例子说明用函数重载设计参数个数不同的函数,用一个函数名求两个整数或三个整数中的最大数。
#include <iostream>
using namespace std;
int max(int a,int b,int c) //求三个整数中的最大者
{
if(b>a) a=b;
if(c>a) a=c;
return a;
}
int max(int a,int b) //求两个整数中的最大者
{
if(a>b) return a;
else return b;
}
int main()
{
int a=7,b=-4,c=9;
cout<<max(a,b,c)<<endl;
cout<<max(a,c)<<endl;
return 0;
}
【注】不允许函数参数个数、参数类型都相同,只是函数返回值不同。因为系统无法从调用形式上判断用与哪个函数相匹配。
5.函数模板
(1)含义
如果两个函数的函数参数个数相同,函数的行为相同(做相同的事),只是函数和参数的数据类型不同,如果用函数重载的话,编写的函数代码是相同的,为了节省时间,C++提供了函数模板功能。
(2)格式
template typename 标识符[,typename标识符,……] 函数定义(函数的类型和参数的类型用声名的标识符表示) template是关键字,含义是模板;typename是关键字,表示其后的标识符代表类型参数,调用时根据实参的类型确定形参的类型。
- 所谓函数模板,是建立一个通用函数,不指定函数类型和参数类型,而用一个虚拟的类型表示。在调用函数时,用实参的类型取代模板中的虚拟类型。
(3)例
计算两个数中的大数定义函数模板
#include<iostream>
using namespace std;
template<typename T>
T max(T a,T b,T c)
{
if(b>a) a=b;
if(c>a) a=c;
return a;
}
int main()
{
int i1=8,i2=5,i3=6,i;
double d1=56.9,d2=90.876,d3=43.2,d;
long g1=12345,g2=-23521,g3=341854,g;
i=max(i1,i2,i3);
d=max(d1,d2,d3);
g=max(g1,g2,g3);
cout<<"i_max="<<i<<endl;
cout<<"d_max="<<d<<endl;
cout<<"g_max="<<g<<endl;
return 0;
}
【注】从程序中看到,此问题用函数模板比用函数重载更方便。注意,函数模板只适用于函数参数的个数相同而类型不同,并且函数体相同的情况,如果函数的参数个数不同,则不能用函数模板。
6.有默认参数的函数
(1)含义
C++允许为函数的参数设置默认值,这时调用函数时,如果没有实参,就以默认值作为实参值
(2)格式
形参类型 形参变量名=常数
(3)功能
调用函数时,如果没有实参,就以常数作为该形参的值;如果有实参,仍以实参的值作为该形参的值
- 有默认值的形参必须放在形参表的右边,不允许无默认参数值和有默认参数值的形参交错排列
(4)例
编写计算圆柱体体积函数float volum(float h,float r=12.5)调用可以采用以下任何一种形式volume(45.6);或volume(32.4,10.5);
(5)注
如果用函数原型声明,只要在函数原型声明中定义形参的默认值即可;一个函数名不能同时用于重载函数和带默认形参值的函数。当调用函数时,如少写一个参数,系统无法判断是利用重载函数还是利用带默认参数值的函数,出现二义性。
7.变量的引用
(1)含义
C++提供了为变量取别名的功能,这就是变量的引用。
(2)格式
类型 &变量1=变量2
- 变量2是在此之前已经定义过的变量,且与变量1的类型相同。这里为变量2定义一个别名变量1,在程序里变量1和变量2就是同一个变量。
- 两个变量不能用同一个别名
(3)例
#include <iostream>
using namespace std;
int main()
{
int a = 10;
int &b = a; //声明b是a的引用
a = a * a; //a的值变化了,b的值也应一起变化
cout << a << " " << b << endl;
b = b / 5; //b的值变化了,a的值也应一起变化
cout << b << " " << a << endl;
return 0;
}
(4)将引用作为函数参数
C++除了可以用普通变量、指针变量做形参外,还可以用引用变量做形参。
- 普通变量做形参:这时传递的是实参的值,在函数内形参与实参是两个不同的内存单元,对形参的修改不会影响实参的值
#include<iostream>
using namespace std;
void swap(int a,int b)
{
int temp;
temp=a;
a=b;
b=temp; //实现a和b的值互换
}
int main()
{
int i=3,j=5;
swap(i,j);
cout<<"i="<<i<<" "<<"j="<<j<<endl; //i和j的值未互换
return 0;
}
- 用指针变量做形参:C语言还允许用指针变量做形参,这时传递的是实参变量的地址(指针),在函数内利用这个指针访问实参变量。
#include <iostream>
using namespace std;
void swap(int *p1,int *p2)
{
int temp;
temp=*p1;
*p1=*p2;
*p2=temp;
}
int main()
{
int i=3,j=5;
swap(&i,&j);
cout<<"i="<<i<<" "<<"j="<<j<<endl; //i,j换了
return 0;
}
- 用引用变量做形参:用指针变量做形参,它将实参变量的地址传递给形参,在函数内用“*指针变量”的方式访问实参变量。我们知道引用变量是变量的别名,在调用函数时,用引用变量的做的形参就成了实参变量的别名,在函数中用的形参名就是实参的别名,这样比用指针变量更直观、更方便。
#include <iostream>
using namespace std;
void swap(int &a,int &b)
{
int temp;
temp=a;
a=b;
b=temp;
}
int main()
{
int i=3,j=5;
swap(i,j);
cout<<"i="<<i<<" "<<"j="<<j<<endl; //i、j换了
return 0;
}
(5)对引用的进一步说明
- 引用变量都具有非void类型
- 不能建立引用的数组
- 可以建立常引用变量,不允许修改常引用变量的值
int i;
const int &a = i;
a = 3; //错误的用法
i = 8; //i不是常变量,可以修改
- 可以建立指针变量的引用变量
int i;
int *p=&i;
int *&pt=p;//pt是p的别名变量,同时也是指针变量
8.内置函数
(1)含义
C++提供了一种机制,在编译时,将所调用的函数的代码嵌入到调用函数代码中,在执行函数时省去了调用环节,提高了函数的执行速度。这种机制称为内置函数,有的书称内联函数。
(2)格式
inline 函数类型 函数名(形参表)
【注】inline是C++的关键字,在编译时,编译程序会把这个函数嵌入到调用函数的函数体中
(3)例:计算三个整数中的最大数
#include<iostream>
using namespace std;
inline int max(int a,int b,int c) //这是一个内置函数
{
if(b>a) a=b;
if(c>a) a=c;
return a;
}
int main()
{
int i=7,j=10,k=25,m;
m=max(i,j,k);
cout<<"max="<<m<<endl;
return 0;
}
【注】由于在定义函数时指定它是内置函数,因此编译系统在遇到调用max(i,j,k)时就用max函数体的代码代替max(i,j,k),同时用实参代替形参。
#include <iostream>
using namespace std;
inline int power(int x)
{
return x*x;
}
int main()
{
cout<<power(2)<<endl;
cout<<power(1+1)<<endl;
return 0;
}
【注】使用内置函数可以节省程序运行时间,但增加了目标程序的长度。所以在使用时要衡量时间和空间的得失。
9.作用域运算符
(1)含义
并不是所有的变量在程序运行的时时刻刻都是可见的。有的变量在整个程序运行期间都是可见的,称他们为全局变量;有的变量只在一个函数中可知,被称为局部变量。
每个变量都有其有效的作用域,程序只能在变量的有效作用域内使用变量,不能直接使用其他域中的变量。
(2)例
#include<iostream>
using namespace std;
float a=13.5; //全局变量a
int main()
{
int a=5; //局部变量a
cout<<"a="<<a<<endl;
return 0;
}
【注】局部变量会屏蔽全局变量。为了在函数中访问全局变量C++提供了作用域运算符::,可以用来指定要访问的作用域。
#include <iostream>
using namespace std;
float a = 13.5; //全局变量a
int main()
{
int a = 5; //局部变量a
cout << "a=" << a << endl;
cout << "a=" << ::a << endl;
return 0;
}
10.字符串变量
(1)含义
C++提供了字符串类型string,实际上它不是C++的基本类型,它是在C++标准库中声明的一个字符串类,程序可以用它定义对象。
(2)定义字符串变量
格式:string 变量名表=字符串常量
【注】如用字符串变量,在程序开始要用包含语句把C++标准库的string头文件包含进来
(3)对字符串操作
- 对字符串变量赋值:字符串变量=字符串表达式
string st1,st2;
st1="王点点";
st2=st1;
- 访问字符串中的字符:C++允许把字符串作为字符数组,第一个字符的下标是0,第二个字符的下标是1,以此类推。
string w="then";
w[2]='a';
- 输入输出字符串:格式为cin>>(cout<<)字符串变量
- 字符串连接运算:字符串1+字符串2;把连接运算符两端的字符连接成一个字符串。表达式中可以用字符串常量也可以用字符串变量。
- 字符串的比较运算:>,>=,==,!=,<,<=(根据ASCII码)
11.动态分配/撤销内存的运算符new和delete
(1)分配内存运算
new 类型[(初值)]。类型是决定分配空间尺寸的关键因素,入宫运算结果正确,它的值是分配内存空间的起始地址,否则返回NULL。
int *a=new int;
int *b=new int(100);
char *ch=new char[10];
int *q=new int[5][4];
float *p=new float(3.14159);
(2)归还动态内存运算
delete[]指针变量。[]代表数组,如果不是数组可以省略。运算功能:撤销指针变量所指的动态内存空间,指针变量的数据类型绝对了空间尺寸的大小。
char *p=new char[10];
... ...
delete []p;
(3)用动态内存存放结构体变量
#include <iostream>
#include <string.h>
using namespace std;
struct student
{
char name[10];
int num;
char sex;
};
int main()
{
student *p;
p = new student;
strcpy(p->name, "Wang Fun");
p->num = 10123;
p->sex = 'M';
cout << p->name << " " << p->num << " " << p->sex << endl;
delete p;
return 0;
}
【注】
- 先声明了一个结构体类型student,定义一个指向它的指针变量p,用new开辟一个空间存放一个studet类型变量
- 如果无法正常分配内存,运算会返回一个空指针NULL,程序可以设计判断结构,根据判断结果决定怎样操作。
- 注意不要混合使用new,delete,malloc,free。要正确搭配。