c++(two)
c++的产生
c++是从c语言发展演变而来的,引入了类的机制,最初也被称为"带类的C"
特点
保持c的简洁,高效和接近汇编语言等特点
对c的类型系统进行改革和扩充
c++也支持面向过程的程序设计,不是一个纯正的面向对象的语言
支持面向对象的方法
实例
#include<iostream>
using namespace std;
int main(){
cout<<"Hello\n";
cout<<"Welcome to c++!\n";
}
结果
Hello!
Welcome to c++!
实例说明
在新的c++标准程序库中,所有标识符都声明在命名空间std中,且头文件不使用扩展名
头文件使用旧版(带扩展名)和新版(不带扩展名)皆可,但不可以混用
名字空间防止命名冲突
1. 命名空间声明:
namespace NS{
class File;
void fun();
}
2. 命名空间内标识符使用:
NS::File obj;
NS::Fun();
3. 简洁方法:
using namespace NS;
函数
把相关的语句组织在一起,注明相应的名称,利用这种方法把程序分块,这种形式的组合就叫做函数
一个c++程序由一个主函数(main)和若干个函数构成
分类
标准库函数和用户自定义函数
由主函数调用其他函数,其他函数也可以相互调用
函数驱动机制
c++字符集
大小写的英文字母:A~Z,a~z
数字字符:0~9
特殊字符:
空格 ! # % ^ & * __(下划线) + = -(减号) ~ < > / \ ’ " ; . , () [ ] {}
关键字
https://blog.csdn.net/wuxinliulei/article/details/9787901
词法记号
- 关键字:C++预定义的单词
- 标识符:程序员声明的单词,它命名程序正文的一些实体
- 文字:在程序中直接使用符号表示的数据
- 操作符:用于实现各种运算的符号
- 分隔符:用于分隔各个词法记号或程序正文,分隔符是() {} , ;
- 空白:空格,制表符(TAB键产生的字符),换行符(Enter键所产生的字符)和注释的总称
标识符的构成规则
-
以大写字母,小写字母或下划线(_)开始
-
可以由以大写字母,小写字母,下划线(_)或数字0·9组成
-
大写字母和小写字母代表不同的标识符
注释两种(/….****/或则//)
基本数据类型和表达式
C++的基本数据类型
数据类型
常量与变量
整型数据
变量
在程序执行过程中其值可以变化的量,需用名字标识
声明和定义
变量在使用之前需要首先声明其类型和名称
声明语句的形式
变量赋初值
注:C++中有字符串常量,却无字符串变量
整型数据及取值范围
实型数据
字符型数据(一)
布尔型数据
符号常量
为常量命名,这就是符号常量
符号常量在使用之前一定要首先声明
常量声明语句的形式
符号常量在声明时一定要赋初值,而在程序中间不能改变其值
例:
不同类型数据混合运算时的类型转换
不同类型数据进行混合运算时,C++编译器会自动进行类型转换
为了避免不同的数据类型在运算中出现混淆,应尽量使用同种类型数据。
可以采用强制类型转换:
例如:
变量的存储类型
auto:采用堆栈方式分配内存空间,属于暂时性存储,其存储空间可以被若干变量多次覆盖使用
register:存放在通用寄存器中
extern:在所有函数和程序段中都可以引用
static:在内存中都是以固定地址存放的,在整个程序运行期间都有效
运算符和表达式
表达式是计算求值的基本单位
表达式组成
有运算符(例:+,-,*,/),运算量(也称操作符,可以是常量,变量等等)和括号组成
例:a+b,x/y
表达式的值
执行表达式所规定的运算,所得到的结果值是表达式的值
表达式的定义
一个常量或表示对象的标识符是一个最简单的表达式,其值是常量或对象的值
一个表达式的值可以用来参与其他操作,即用作其他运算符的操作数,这就形成了更复杂的表达式
包括在括号中的表达式仍是一个表达式,其类型和值与未加括号时的表达式相同
运算符的种类:算术,关系,逻辑。
运算符的分类:
一元运算符(单目运算符)
二元运算符(双目运算符)
算术运算符与算术表达式
基本算术运算符
优先级与结核性
先乘除,后加减,同级自左至右
++,–
例:i++;j–;
增量和减量运算符
增量运算符:前增量和后增量
前增量操作++a:先修改变量使之增1,然后将增1过的a的值作为表达式的值
后增量操作a++:先将变量a的值作为表达式的值确定下来,再将a增1
赋值运算符和赋值表达式
简单的赋值运算符 “=”
例:n=n+5,a=b=c=5
作用
将等号右边表达式的值赋给等号左边的对象
类型
等号左边对象的类型
值
等号左边对象被赋值后的值
运算的结合性为自右向左
复合的赋值运算符
有10种符合运算符
这10种复合的赋值运算都是二元运算符,优先级与“=”相同,结合性也是自右向左。
逗号运算和逗号表达式
格式
表达式1,表达式2
求解顺序及结果
先求解1,再求解2,最终结果为表达式2的值,若多个表达式,结果为最后表达式的值
关系运算与关系表达式
关系运算是比较简单的一种逻辑运算,优先次序为:
关系表达式是一种最简单的逻辑表达式其结果类型为bool,值只能为true或false.
关系运算
关系运算的结果true或false是逻辑值
关系运算在C++中,0表示假,任意一个非0的数都表示真
关系运算注意不要将=和==用错
逻辑运算与逻辑表达式
逻辑运算符
!(非) &&(与) ||(或)
优先次序:高$\rightarrow$ 低
逻辑表达式
其结果类型为bool,值只能为true或false.
条件运算符与条件表达式
一般形式
表达式1?表达式2:表达式3
表达式1必须是bool类型
执行顺序
- 先求解表达式1
- 若表达式1的值为true,则求解表达式2,表达式2的值为最终结果
- 若表达式1的值为false,则求解表达式3,表达式3的值为最终结果
sizeof操作符
语法形式
sizeof(类型名)或sizeof(表达式)
结果值
“类型名”所指定的类型或“表达式”的结果类型所占的字节数
注意不用对括号中的表达式本身求值
位运算(按位与(&))
运算规则
将两个运算量的每一个位进行逻辑与操作
用途
将某一位置0,其它位不变。例如:
将char型变量a的最低位置0:a=a&0376;
取指定位。例如:
位运算(按位或(|))
运算规则
将两个运算量的每一个位进行逻辑或操作
用途
将某些位置1,其它位不变。
例如:将int型变量a的低字节位置1:
a=a|0xff;
位运算(按位异或(^))
运算规则
两个操作数进行异或:
若对应位相同,则结果该位为0
若对应位不同,则结果该位为1
用途
使特定位翻转(与0异或保持原值,与1异或取反)
例如:
位运算(取反(~))
单目运算符
对一个二进制数按位取反
位运算(移位)
左移运算(«)
左移后,低位补0,高位舍弃
右移运算
右移后,低位:舍弃;
高位:
无符号数:补0
有符号数:补“符号数”
运算符优先级
混合运算时数据类型的转换(隐含转换)
一些二元运算符(算符运算符,关系运算符,逻辑运算符,位运算符和赋值运算符)要求两个操作数的类型一致
在算数运算和关系运算中如果参与运算的操作数类型不一致,编译系统会自动对数据进行转换(即隐含转换),基本原则是将低类型数据转换为高类型数据。
类型转换的规则举例
混合运算时数据类型的转换(强制类型转换)
语法形式:
类型说明符(表达式)或(类型说明符)表达式
强制类型转换的作用是将表达式的结果类型转换为类型说明符所指定的类型
强制类型转换的规则举例
语句
C++语言的语句
声明语句,表达式语句,选择语句,循环语句,跳转语句,复合语句,标号语句几类。
表达式与表达式语句的区别
表达式可以包含在其它表达式中,而语句不能。
注意
C++语言没有赋值语句也没有函数调用语句,赋值与函数调用功能都是通过表达式来实现的。
如果在赋值表达式后面加上分号,便成了语句。
数据的输入与输出
I/O流
流
在C++中,将数据从一个对象到另一个对象的流动抽象为“流”
提取操作
从流中获取数据的操作称为提取操作
插入操作
向流中添加数据的操作称为插入操作
预定义的插入符和提取符
数据的输入和输出通过I/O流(stream)来实现
插入操作符“«”
预定义的流类对象cout
cout用来处理标准输出,即屏幕输出格式:cout«表达式«表达式…
提取操作符“»”
预定义的流类对象:cin
cin用来处理标准输入,即键盘输入
**格式:cin»表达式»表达式… **
例:
int x,y;
cin>>x>>y;
从键盘上输入两个int型数,两数之间以空格分隔。
I/O标准流类
标准流的设备名
cout原理
cout是iostream流类的对象,它在iostream头文件中作为全局对象定义:
ostream cout(stdout)
标准设备名作为其构造时的参数
cin原理
cin是istream全局对象
除了标准输入输出设备,还有标准错误设备cerr
简单的I/O格式控制
流的默认格式输出有时不能满足特殊要求
希望显示的是9.40,即保留两位小数,可是却显示了9.40007;默认显示6位有效位
用控制符(manipulators)可以对I/O流1的格式进行控制
I/O流的常用控制符
I/O流的常用控制符(举例)
**例:控制浮点数值显示 **
设置值的输出宽度
除了使用空格来强制输出间隔外,还可以用setw(n)控制符。
如果一个值需要比setw(n)确定的字符数更多的字符,则该值将用它所需要的所有字符
超过setw(4)将会原样输出
如果一个值的字符比setw(n)确定的字符个数少,则在数字字符前显示空白。
若要每个数值都有宽度8,则每个值都要设置
输出8进制和16进制
3个常用的控制符是hex,oct和dec
这3个控制符在iostream.h头文件中定义
设置填充字符
用setfill控制符可以确定一个非空格的别的字符
setfill在头文件iomanip.h中定义
左右对齐输出
默认时,I/O流左对齐显示的内容。
使用头文件iomanip.h中的setiosflags(ios::left)可输出左对齐
使用头文件iomanip.h中的setiosflags(ios::right)可输出右对齐
强制显示小数
使用头文件iomanip.h中的setiosflags(ios::showpoint)可强制显示小数(后六位,包括小数点)以及显示正负号
算法的基本控制结构
顺序结构,分支结构,循环结构
if语句(多种形式)
if语句(空语句)
编译器必须在if条件表达式的后面找到一个作为语句结束的分号“;”,以标志if语句的结束。
例:
if(条件表达式)://空语句做if中的语句
语句;
则不管条件表达式为真为假,总是接着执行语句
else if 语句
if语句(嵌套)
一般形式
c++
if()
if() 语句1
else 语句2
else
if() 语句3
else 语句4
注意
语句1,2,3,4可以是复合语句,每层的if与else配对,或用{}来确定层次关系
switch语句(特殊的多分支结构)
一般形式
特殊的多分支结构
执行顺序
以case中的常量表达式值为入口标号,由此开始顺序执行。因此,每个case分支最后应该加break语句
例:输入一个0~6的整数,转换成星期输出
#include<iostream>
void main(void){
int day;
cin>>day;
switch(day){
case0:cout<<"Sunday"<<endl;break;
case1:cout<<"Monday"<<endl;break;
case2:cout<<"Tuesday"<<endl;break;
case3:cout<<"Wednesday"<<endl;break;
case4:cout<<"Thursday"<<endl;break;
case5:cout<<"Friday"<<endl;break;
case6:cout<<"Saturday"<<endl;break;
default:
cout<<"Day out of range Sunday...Saturday"<<endl;break;
}
}
使用switch语句应注意的问题
- case分支可包含多个语句,且不用{}.
- switch语句后面的表达式,可以是整型,字符型,枚举型
- 各个常量表达式的值不能相同,但次序不影响执行结果
- 每个case分支的最后应该加break语句,用来结束整个switch结构
- 当若干分支需要执行相同操作时,可以使多个case分支共用一组语句
循环语句(while)
形式:
while(条件表达式)
循环体 //可以是复合语句,其中必须含有改变条件表达式值的语句
执行顺序
先判断表达式的值,为true时,再执行循环体
组成
while循环由四部分组成:循环变量初始化,继续条件,循环体,改变循环变量的值。
例:
#include<iostream>
void main(){
inti(1),sum(0); //循环变量初始化
while(i<=10) //继续条件
{ //循环体
sum+=i;
i++; //改变循环体变量的值
}
cout<<"sum="<<sum<<endl;
}
do-while语句
一般形式
do //语句(可以是复合语句,其中必须含有改变条件表达式值的语句)
while(条件表达式)
例:用2-7用do-while语句编程,求自然数1~10之和
#include<iostream>
void main(){
int i(1),sum(0);
do
{
sum+=i;
i++;
}while(i<=10);
cout<<"sum="<<sum<<endl;
}
do-while循环在循环的底部进行继续条件的测试,所以它至少执行一次循环体
while循环在循环的顶部进行测试,有可能永远不执行循环体
do-while循环中,while(条件表达式)后面的分号不要遗忘
for语句
语法形式
for(表达式1;表达式2;表达式3)语句
表达式1:循环先求解;
表达式2:循环控制条件,根据表达式2的值判断是否执行循环体,如果表达式2的值为true,则执行一次循环体;如果为false,则退出循环
表达式3:每执行一次循环体后,计算表达式3的值,然后再计算表达式2,根据表达式2的值决定是否继续执行循环体
表达式1,2,3都可以省略,分号不能省略
例:for(;;)语句 //相当于while(true)语句
表达式1一般用于给循环变量赋初值
表达式1可以省略.此时应在for语句之前给循环变量赋初值。若省略表达式1,其后的分号不能省略。
例:求和运算
i=1;
for(;i<=100;i++) //分号不能省略
sum+=i;
for语句的几点说明
表达式2是循环控制条件,如省略,循环将无终止地进行下去。
例:求和运算
for(i=1;;i++){ //分号不能省略
sum+=i;
if(i>=100)
break;
}
//等价于
for(i=1;1;i++){
sum+=i;
if(i>=100)
break;
}
表达式3一般用于改变循环控制条件的值.
如果表达式3省略或者是其他与循环条件无关的表达式,则应该在循环体中另有语句改变循环条件,以保证循环能正常结束。
例:求和运算
for(i=1;i<=100) //分号不能省略
sum+=i++ //同时改变循环变量
表达式1和表达式3可同时省略
i=1;
for(;i<=100;) //分号不能省略
sum+=i++; //同时改变循环变量
表达式1和表达式3都为逗号表达式;
for(i=0,j=100,k=0;i<=j;i++,j--)
k+=i*j;
表达式2和表达式3可以为赋值或算术表达式的情况;
for(i=1;i<=100;sum+=i++);
//循环为空语句
for(i=1;sum+=i++,i<=100;);
//表达式3省略,循环为空语句
循环结构的嵌套
#include<iostream>
void mian(){
int i(1),a(0);
for(;i<=5;i++){
do{
i++;
a++;
}while(i<3);
i++;
}
cout<<a<<","<<i<<endl;
}
循环结构与选择结构相互嵌套
#include<iostream>
void main(){
int n;
for(n=100;n<=200;n++){
if(n%3!=0)
printf("%d",n);
}
}
break和continue语句
break语句:
用在while,do-while,for和switch结构中在switch语句中,break使流程跳出switch语句中,break使流程跳出switch语句,继续执行switch后的语句在循环语句中,break用来从最近的封闭循环体中跳出
continue语句:
结束本次循环,接着判断是否执行下一次循环
区别
continue语句只结束本次循环;而不是终止整个循环的执行
break语句则是结束本次循环,不再进行条件判断。在循环语句中,break用来从最近的封闭循环体中跳出
自定义数据类型(typedef声明)
为一个已有的数据类型另外命名
语法形式
typedef 已有类型名 新类型名表;
例如:
typedef double area,volume;
typedef int natural;
natural i1,i2;
area a;
volume v;
枚举类型
只要将需要的变量值一一列举出来便构成了一个枚举类型
枚举类型的声明形式:
enum 枚举类型名 {变量值列表};
例如:
enum weekday
{sun,mon,tue,wed,thu,fri,sat};
注:整数值不能直接赋给枚举变量,如需要将整数赋值给枚举变量,应进行强制类型转换
#include<iostream>
using namespace std;
enum game_result{WIN,LOSE,TIE,CANCEL};
void main(){
game_result result;
//声明变量时,可以不写关键字enum
enum game_result omit=CANCEL;
//也可以在类型名前写enum
int count;
for(count=WIN;count<=CANCEL;count++){
result=(game_result)count; //强制类型转换,小类型可以转大类型,大类型转小类型必须要强制转换
if(result==omit){
cout<<"The game was cancelled\n";
}
else{
cout<<"The game was played";
if(result==WIN)
cout<<"and we won";
if(result==LOSE)
cout<<"and we lose";
cout<<"\n";
}
}
}
结构体(结构体的声明)
概念:结构是由不同的数据类型的数据组成的
声明结构体类型
struct 结构名{
数据类型 成员名1;
数据类型 成员名2;
.
.
数据类型 成员名3;
};
例:结构体变量的初始化和使用
#include<iostream>
#include<iomanip>
struct student{ //学生信息结构体
int num;
char name[20];
char sex;
int age;
}stu={97001,"LinLin",'F',19};
//在定义结构体的同时,生命结构类型的变量stu
void main(){
cout<<setw(7)<<stu,num<<setw(10)<<stu.name<<set(3)<<stu.sex
<<setw(3)<<stu.age<<endl;
}
结构体(结构变量说明)
变量说明形式
结构名 结构变量名;
注意:
- 结构变量的存储类型概念,它的寿命,可见性及使用范围与普通变量完全一致
- 结构变量说明在结构类型声明之后,二者也可同时进行
- 结构变量占用内存大小可用sizeof运算求出:sizeof(类型名)
- 说明结构变量的同时可以直接设置初值
在定义结构体类型的同时声明变量
struct student{ //学生信息结构体
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}stu1,stu2;
直接定义变量
struct //省略结构体名称
{
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}stu1,stu2;
用typedef关键字给结构体取个别名
typedef struct student //学生信息结构
{
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}postgraduate;
定义2个struct student 类型的变量
postgraduate stu1,stu2
可以先定义结构体类型,然后取别名
struct student //学生信息结构
{
.....
}
typedef struct student postgraduate;
也可以省略结构体名称student
typedef struct //学生信息结构体
{
.....
}postgraduate;
下面几种情况要分清楚
struct student //student是类型名
{
.....
};
typedef struct
{
.....
}postgraduate; //postgraduate是类型名
typedef student postgraduate //postgraduate是类型名
struct{
....
}stu; //stu是变量名
struct student //student是类型名
{
.....
}stu; //stu是变量名
struct student stu; //stu是变量名
typedef struct student{ //student是类型名
...
}STUDENT;
//STUDENT是类型名,是student的别名
结构体(结构变量的初始化和使用)
初始化
说明结构变量的同时可以直接设置初值。
struct student stu={97001,"李明",'M',16,92,"北京市"}
但一定要注意,不能在定义结构体类型的时候,进行赋初值
struct student //下面的做法是错误的
{
int num =97001;
char name[20] = “Li Lin”;
char sex= “M”;
int age = 16;
float score = 92;
char addr[30] = “123 Bejing Road”;
}stu
使用(访问结构成员)
结构体成员的引用形式
结构变量名.成员名
例如:
cout<<stu.num<<","<<stu.name<<","<<stu.sex<<","<<stu.age
<<","<<stu.score<<","<<stu.addr;
下面这些写法都是错误的
1.strcpy(student.name,"wangli");
//student是结构体类型名,不是结构体变量
2.stu.book=6
//结构体student中没有定义"book"这个成员
初始化结构体部分成员
使用赋值语句对它们进行初始化了。
例如:
stu . Num = 97001;
strcpy(stu . name, “李明”);
stu . sex = ‘M’;
stu . age = 16;
stu . score = 91;
strcpy(stu . addr, “北京”);
当然,使用输入语句也可以实现部分结构体成员的初始化
例:
cin>>stu.Age;
把结构体变量当作整体赋值
-
结构体变量整体赋值
例:
stu2 = stu1; //通过这种模式,可以直接完成结构体之间的赋值
-
去结构体变量地址
例:
cout<<&stu1; //输出stu1的地址 cin>>stu1.Age; //输入stu1的年龄
需要注意,不能把结构体变量整体输入进来
例:
cin>>stu1; //错误
逐级访问成员
#include<iostream>
struct student //学生信息结构体
{
int num;
char name[20];
char sex;
struct date
{
int month;
int day;
int year;
}birthday;
float score;
char addr[30];
}stu;
//对成员进行逐级访问
void main(){
stu.birthday.month=9;
stu.birthday . day = 20;
stu.birthday . year = 1996;
cout<<stu.birthday .month<<"/ " <<stu.birthday . day<<"/ " <<stu.birthday . year<<endl;
}
说明结构变量的同时可以直接设置初值
#include <iostream.h>
#include <iomanip.h>
struct student //学生信息结构体
{ int num; //学号
char name[20]; //姓名
char sex; //性别
int age; //年龄
float score; //成绩
char addr[30]; //住址
}stu={97001,“李明”,‘F’,19, “北京“};
void main()
{ cout<<setw(7)<<stu.num<<setw(20)
<<stu.name<<setw(3)<<stu.sex<<setw(3)
<<stu.age <<setw(7) <<stu.addr<<endl;
}
联合体
声明形式
union 联合名
{
数据类型 成员名1;
数据类型 成员名2;
.
.
数据类型 成员名n;
};
联合体类型变量说明的语法形式
联合名 联合名变量;
引用形式
联合变量名.成员名
例:
union uarea
{ char c_data;
short s_data;
long l_data;
}
联合体可以不声明名称
例:声明无名联合体
union{
int i;
float f;
}
无名联合体通常作结构体的内嵌成员
例:适用于描述战斗机,轰炸机,运输机的结构体
# include <iostream.h>
struct aircraft
{
int wingspan ; //翼幅
int passengers ; //乘客
union //无名联合作为结构体的内嵌成员
{
float fuel _load; //战斗机装载的燃料
float bomb _load; //轰炸机装载的燃料
int pallets ; //运输机的货盘
};
} fighter,bomber,transport ;
int main( )
{
fighter . wingspan = 40 ;
fighter . passengers = 1;
fighter . fuel_load = 12000.0 ;
bomber . wingspan = 90 ;
bomber . passengers = 12;
bomber . bomb_load = 14000.0 ;
transport . wingspan = 106 ;
transport . passengers = 4;
transport .pallets = 42 ;
transport . fuel_load = 18000.0 ;
fighter . pallets = 4 ;
cout<<“The fighter carries”<<fighter . Pallets<<“pallets.\n”;
cout<<“The bomber bomb load is”<<bomber . bomb_load<<“\n”;
return 0 ;
}
运行结果
The fighter carries 4 pallets.
The bomber bomb load is 14000
联合体类型的特点
- 从同一地址开始,将几个不同类型的变量存放到同一段内存单元中
- 同一个内存段可以用来存放几种不同类型的成员,但在每一瞬间只能存放其中一种,而不是同时存放几种。即每一瞬时只有一个成员起作用,其他成员不起作用
- 联合体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原成员就失去作用。