1、Windows 开发环境的准备
1)下载 Visual Studio 2022 安装文件
从微软官方网站下载,网址:https://visualstudio.microsoft.com/zh-hans/
选中 Community 2022,它是 Visual Studio 2022 官方免费社区版,无需注册,不需要破解和盗版。
(请不要从国内的其它网站下载安装文件,有病毒和插件)
下载后的文件名是 VisualStudioSetup.exe。
2)安装 Visual Studio 2022
双击安装文件 VisualStudioSetup.exe。
2、Linux 开发环境
本课程适用于各种 Linux 发行版,建议采用 CentOS7.0 至 CentOS7.9 之间的版本,它是目前企业在
实际项目开发中最广泛采用的 Linux 版本。
用 root 登录,执行以下命令,将安装 gcc 和 g++编译器以及 gdb 调试器。
yum -y install gcc gcc-c++ gdb
几十秒即可安装完成。
3、第一个 C++程序
VS2022 太方便了,它可以帮我们生成一个最简单的 C++程序。
1)用 VS 生成最简单的 C++程序
鼠标双击 Visual Studio 2002,运行它。
点击"创建新项目"。
选择"控制台应用",再点"下一步"。
点击"创建"后将生成一个最简单的 C++程序。
2)运行 C++程序
选择"调试->开始执行"菜单,或快捷键 Ctrl+F5 运行程序。
3)示例
// 包含头文件。
#include <iostream>
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
// 在控制台输出一首诗。
std::cout << "\n\n 我是一只傻傻鸟\n";
std::cout << " 生活美好如鲜花,不懂享受是傻瓜;\n";
std::cout << " 傻呀傻呀傻呀傻,不如小鸟和乌鸦。\n";
std::cout << " 芳草地啊美如画,谁要不去是傻瓜;\n";
std::cout << " 我是一只傻傻鸟,独在枯枝丫上趴。\n";
// std::cout 向控制台输出内容的指令,只能小写,不能用大写。
// << 输出的运算符。
// "" 字符串内容的边界符,半角。
// Hello World! 输出字符串的内容,可以是中文、英文和任意符号,半角的双引号除外。
// \n 输出一个换行。
// ; C++语句结束的标志,半角。
}
4、C++输出数据
数据是信息的载体,写程序的目的就是为了处理数据。
1)数据的分类
数据有数字、字符和字符串三种类型。
数字:直接书写,如:100、18.52、0、9;
字符:用半角的单引号包含的一个符号,如:'A'、'Z'、'0'、'9'、'~'、'+',汉字和全角的标点符
号不是字符;
字符串:用半角的双引号包含的多个符号,如:"Hello World"、"我是一只傻鸟"、"西施"、"100"、
"X"。
2)输出数据
std::cout 可以输出各种类型的数据;
<<操作符可以拼接多个数据项;
std::endl 也可以用于换行;
using namespace std;指定缺省的命名空间。
3)示例
#include <iostream>
// 指定缺省的命名空间。
using namespace std;
int main()
{
// 用多个数据项输出超女信息,姓名:西施;年龄:25;体重:48.5;性别:X
// std::cout << "姓名:西施;年龄:25;体重:48.5;性别:X\n";
cout << "姓名:" << "西施" << ";年龄:" << 25 << ";体重:" << 48.5
<< ";性别:" << 'X' << endl;
}
5、程序的注释
在程序中添加的说明文字,对代码的流程或功能加以解释,方便自己和其他的程序员阅读和理解代码。
编译器在编译源代码的时候,会忽略注释。
1)单行注释
用两根反斜线打头,一般放在代码的上方,或者一行语句的末尾。
注意:字符串内容中的两根反斜线是内容的一部分,不是注释。
2)多行注释
从/*开始,到*/结束,把一些内容夹住。
注意:a)字符串内容中的/*和*/是内容的一部分,不是注释;b)/*和*/可以出现在一行代码的中间。
3)注释的注释
单行注释可以注释多行注释,多行注释也可以注释单行注释,但是,不建议使用。
4)VS 中的快捷键
添加注释:Ctrl+k+c
取消注释:Ctrl+k+u
5)示例
// 包含头文件。
#include <iostream>
using namespace std; // 指定缺省的命名空间。
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
// 在控制台输出一首诗。
cout << "\n\n 我是一只傻傻鸟\n";
cout << " 生活美好如鲜花,不懂享受是傻瓜;\n";
cout << " 傻呀傻呀傻呀傻,不如小鸟和乌鸦。\n";
cout << " 芳草地啊美如画,谁要不去是傻瓜;\n";
cout << " 我是一只傻傻鸟,独在枯枝丫上趴。\n";
cout << "姓名:" << "西施" << /*";年龄:" << 25 << */";体重:" << 48.5 << "。" <<
endl;
/*
std::cout 向控制台输出内容的指令,只能小写,不能用大写。
<< 输出的运算符。
"" 字符串内容的边界符,半角。
Hello World! 输出字符串的内容,可以是中文、英文和任意符号,半角的双引号除外。
\n 输出一个换行。
; C++语句结束的标志,半角。
*/
}
6、使用变量
变量是内存变量的简称,用于存放数据。
1)声明变量
变量在使用之前要先声明。
语法:数据类型 变量名
C++常用的数据类型有五种:整数(int)、浮点数(float 和 double)、字符(char)、字符串(string)
和布尔(bool)。
变量在声明的时候可以赋初始值。
语法:数据类型 变量名=值
2)变量的赋值
语法:变量名=值
3)示例
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
// 整数(int)、浮点数(float 和 double)、字符(char)、字符串(string)和布尔(bool)。
// 超女基本信息:姓名、年龄、体重、性别、颜值。
// 声明变量,存放超女基本信息的数据项。
string name = "西施"; // 姓名。
int age = 25; // 年龄。
double weight = 48.6; // 体重(kg)。
char sex = 'X'; // 性别:X-女;Y-男。
bool yz = false; // 颜值:true-漂亮;false-不漂亮。
cout << "姓名:" << name << ",年龄:" << age << ",体重:" << weight
<< ",性别:" << sex << ",颜值:" << yz << endl;
name = "冰冰"; // 字符串有双引号包含。
age = 23; // 整数直接书写。
weight = 50.5; // 浮点数直接书写。
sex = 'X'; // 字符用单引号包含。
yz = true; // 布尔型取值只能是 true 和 false,或 1 和 0。
cout << "姓名:" << name << ",年龄:" << age << ",体重:" << weight
<< ",性别:" << sex << ",颜值:" << yz << endl;
}
注意,布尔型变量输出的时候,如果值是 true,将显示 1,false 显示 0。
7、使用常量
常量是程序中固定不变的数据。
1)宏常量
一般在 main 函数的上面声明,用大写命名。
语法:#define 常量名 值
2)const 修饰的变量
在程序的任何地方都可以声明。
语法:const 数据类型 常量名=值
3)常量的特点
程序中不允许改变常量的值,否则编译的时候会报错。
4)示例
#include <iostream> // 包含头文件。
#define MONTHS 12 // 一年中的月份数。
#define PI 3.14159 // 圆周率。
using namespace std; // 指定缺省的命名空间。
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
const int days = 7; // 一个星期中的天数。
cout << "一年有" << MONTHS << "个月。" << endl;
cout << "圆周率的值是:" << PI << endl;
cout << "一个星期有" << days << "天。\n";
}
8、标识符的命名
1)C++命名规则
C++规定给标识符(变量、常量、函数、结构体、类等)命名时,必须遵守以下规则。
在名称中只能使用字母字符、数字和下划线;
名称的第一个字符不能是数字;
名称区分大写字符与小写字符;
不能将 C++关键字用作名称;
以下划线和大写字母打头的名称被保留给编译器及其使用的资源使用,如果违反了这一规则,会
导致行为的不确定性。
C++对名称的长度没有限制,但有些平台可能有长度限制(64 字符)。
C++提倡有一定含义的名称(望名知义)。
2)C++关键字
关键字也叫保留字,是 C++预先保留的标识符。
每个 C++关键字都有特殊的含义,用于声明类型、对象、函数、命名空间等,程序中不能声明与关
键字同名的标识符。
asm do if return typedef
auto double inline short typeid
bool dynamic_cast int signed typename
break else long sizeof union
case enum mutable static unsigned
catch explicit namespace static_cast using
char export new struct virtual
class extern operator switch void
const false private template volatile
const_cast float protected this wchar_t
continue for public throw while
default friend register true
delete goto reinterpret_cast try
9、输入数据
程序输入数据的方式有多种。
从控制台的界面中输入(网页、PC 桌面程序、APP 程序);
从文件中读取;
从数据库中读取;
从网络中读取。
1)用 std::cin 输入数据
语法:std::cin>>变量名;
注意:
a)布尔型变量的值在计算机内部用 1(true)和 0(false)存储;b)程序中可以书写 true 和
false,也可以书写 1 和 0,其它值将强制转换成 1;c)用 cin 输入时可以填 1 和 0,其它值也强
制转换成 1;d)用 cout 输出时只显示 1 和 0,不显示 true 和 false。
如果输入的数据与变量的数据类型不匹配,会导致行为的不确定性。
2)示例
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
string name; // 姓名。
cout << "请输入超女的姓名:";
cin >> name;
cout << "输入的超女姓名是:" << name << endl;
int age; // 年龄。
cout << "请输入超女的年龄:";
cin >> age;
cout << "输入的超女年龄是:" << age << endl;
double weight; // 体重(kg)。
cout << "请输入超女的体重(kg):";
cin >> weight;
cout << "输入的超女体重是:" << weight << endl;
char sex; // 性别:X-女;Y-男。
cout << "请输入超女的性别(X-女;Y-男):";
cin >> sex;
cout << "输入的超女性别是:" << sex << endl;
bool yz; // 颜值:true-漂亮;false-不漂亮。
cout << "请问输入超女的颜值(1-漂亮;0-不漂亮):";
cin >> yz;
cout << "输入的超女颜值是:" << yz << endl;
}
10、算术运算
运算符 描述
- 两个数相加。
- 一个数减另一个数。
* 两个数相乘。
/ 分子除以分母。
% 取模运算,整除后的余数。
注意:
整数进行除法运算时,如果分母为 0,程序将异常退出;
浮点数进行除法运算时,如果分母为 0.0,将得到 inf(infinite,无穷大);
两个整数进行除法运算时,将舍去小数部分,得到一个整数;
整数与浮点数进行除法运算时,得到的结果是浮点数;
进行除法运算时,在整数前面加(float)或(double)可以将整数转换为 float 或 double 类型;
取模运算只能用于整数(分母也不能为 0)。
11、自增和自减
运算符 描述
++变量名 先把变量的值加 1,然后再执行表达式。
变量名++ 先执行表达式,再把变量的值加 1。
--变量名 先把变量的值减 1,然后再执行表达式。
变量名-- 先执行表达式,再把变量的减 1。
12、赋值运算
1)赋值运算
运算符 示例 描述
= c = a + b; 将把 a + b 的值赋给 c。 把右边操作数的值赋给左边操作数。
+= c += a; 相当于 c = c + a; 加且赋值运算符,把右边操作数加上左边操作数的
结果赋值给左边操作数。
-= c -= a; 相当于 c = c - a; 减且赋值运算符,把左边操作数减去右边操作数的
结果赋值给左边操作数。
*= c *= a; 相当于 c = c * a; 乘且赋值运算符,把右边操作数乘以左边操作数的
结果赋值给左边操作数。
/= c /= a; 相当于 c = c / a; 除且赋值运算符,把左边操作数除以右边操作数的
结果赋值给左边操作数。
%= c %= a; 相当于 c = c % a; 求余数且赋值运算符,求两个操作数的模赋值给左
边操作数,浮点数不适用取余数。
注意:
字符串(string)只能使用等号(=)赋值,不能使用其它的赋值运算符;
浮点数不能使用%=运算符;
等号(=)赋值运算符可以连续使用;
如果赋值运算符两边操作数的数据类型不同,C++将自动转换数据类型,可能会损失精度,也可
能超出取值范围,如果转换不成功,编译时会报错。
2)示例
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
int a = 10;
int c = 20;
// c += a; // c=c+a;
// c -= a; // c=c-a;
// c *= a; // c = c * a;
// c /= a; // c = c / a;
//c %= a; // c = c % a;
// cout << "c=" << c << endl;
a = c = 30;
cout << "a=" << a<<endl;
cout << "c=" << c << endl;
}
13、C++11 初始化赋值
1)C++和 C++11 初始化赋值
把值写在小括号中,等于号可以省略(C++标准)
int a=(15); // 声明变量 a,初始化值为 15。
int b(20); // 声明变量 b,初始化值为 20。
把值写在花括号中,等于号也可以省略(C++11 标准),统一初始化列表。
int a={15}; // 声明变量 a,初始化值为 15。
int b{20}; // 声明变量 b,初始化值为 20。
注意:在 Linux 平台下,编译需要加-std=c++11 参数。
2)示例
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
int a = 10;
int b = (10);
int c(10);
int e = {10};
int f{ 10 };
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "c=" << c << endl;
cout << "e=" << e << endl;
cout << "f=" << f << endl;
}
14、关系运算
用于比较两个表达式的值,运算的结果为 1-true 和 0-false。
1)关系运算
关系 数学的表示 C++的表示
等于 = == 不等于 ≠ !=
小于 < <
小于等于 ≤ <= 大于 > >
大于等于 ≥ >= 注意:
关系运算符的两边可以是数值,也可以是表达式;
用 std::cout 输出关系运算表达式时,关系表达式要加括号;
关系运算也适用于字符串(string),字符串常用的关系运算是==和!=,其它的基本上不用。
2)示例
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
int a = 7;
int b = 7;
bool result;
result = a <= b-3; // a 和 b 先做比较(关系)运算,然后再赋值给 result。
cout << "result=" << result << endl; // 关系运算表达式需要括号,算术运算表达式可以
不用括号。
string str1 = "西施";
string str2 = "西瓜";
cout << (str1 ==> str2) << endl;
}
15、逻辑运算
1)逻辑运算
根据给定的逻辑因子(表达式或值)返回一个新的逻辑因子。
运算符 术语 示例 结果
&& 逻辑与 a&&b; 如果 a 和 b 都为真,则结果为真,否则为假。
|| 逻辑或 a||b;
如果 a 和 b 中有一个为真,则结果为真,二者都为假时,结
果为假。
! 逻辑非(反) !a; 如果 a 为假,则!a 为真; 如果 a 为真,则!a 为假。 注意:
逻辑运算符的两边可以是数值,也可以是表达式;
用 std::cout 输出逻辑运算表达式时,逻辑表达式要加括号;
在实际开发中,逻辑运算的多重组合是重点。
2)示例
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
bool a = false;
bool b = true;
// bool c = a && b; // 如果 a 和 b 都为真,则结果为真,否则为假。
// bool c = a || b; // 如果 a 和 b 中有一个为真,则结果为真,二者都为假时,结果为假。
bool c = !a; // 如果 a 为假,则!a 为真; 如果 a 为真,则!a 为假。
// cout << "c=" << c << endl;
// cout << "a&&b=" << (a && b) << endl;
// cout << "a||b=" << (a || b) << endl;
cout << "!a=" << c << endl;
}
///
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
// 超女必须满足四个条件:年龄 25 岁以下,身高 165 以上、体重 50 公重以下,颜值要漂亮。
int age = 23;
int height = 168;
double weight = 48.8;
bool yz = true;
cout << "result="<<(age<25&&height>165&&weight<50&&yz==true) << endl;
}
16、逗号运算
1)逗号运算
把一行语句中的多个表达式连接起来,程序将从左到右执行表达式。
语法:表达式一,表达式二,......,表达式 n;
逗号运算常用于声明多个变量。
int a,b; // 声明变量 a 和 b。
int a=10,b=20; // 声明变量 a 和 b 并初始化。
也可以用于其它语句中,但是,逗号运算符是所有运算符中级别最低的,以下两个表达式的效果是不
同的。
int a,b;
b=a=2,a*2;
b=(a=2,a*2);
2)示例
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
/*int a =10, b=20;
cout << "a=" << a << endl;
cout << "b=" << b << endl;*/
int a, b;
//b = a = 2, a * 2;
b = (a = 2, a * 2);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
}
17、运算的优先级
1)运算的优先级
一个表达式可以包含多个运算符,运算符的优先级决定了表达式各部分的执行顺序。
例如,按照运算规则, *的优先级比+高,所以的 b * c 将先执行:
a + b * c;
如果想让 a + b 先执行,则必须使用括号:
(a + b) * c;
如果一个表达式中操作符的优先级相同,那么它们的结合律(associativity)决定了它们的执行顺序
(从左到右或从右到左)。例如,算术运算的组合方式是从左到右,赋值运算则是从右到左。如下:
表达式 结合律 组合方式
a/b%c 从左到右 (a/b)%c
a=b=c 从右到左 a=(b=c)
下表是全部运算符的优先级和结合律:
优先级 运算符 名称或含义 使用形式 结合方向
1
[] 下标 地址[表达式]
左到右
() 圆括号 (表达式)/函数名(形参表)
. 成员选择(对象) 对象.成员名
-> 成员选择(指针) 对象指针->成员名
2
- 负号运算符 -表达式
右到左
(类型) 强制类型转换 (数据类型)表达式
++ 前置自增运算符 ++变量名
++ 后置自增运算符 变量名++
-- 前置自减运算符 --变量名
-- 后置自减运算符 变量名-- * 取值运算符 *指针变量
& 取地址运算符 &变量名
! 逻辑非运算符 !表达式
~ 按位取反运算符 ~表达式
sizeof 长度运算符 sizeof(表达式)
3
/ 除 表达式/表达式
* 乘 表达式*表达式 左到右
% 余数(取模) 整型表达式/整型表达式
4
- 加 表达式+表达式
左到右
- 减 表达式-表达式
5
<< 左移 变量
左到右
>> 右移 变量>>表达式
6
> 大于 表达式>表达式
左到右
>= 大于等于 表达式>=表达式
< 小于 表达式
<= 小于等于 表达式
7 == 等于 表达式==表达式
左到右
!= 不等于 表达式!= 表达式
8 & 按位与 表达式&表达式 左到右
9 ^ 按位异或 表达式^表达式 左到右
10 | 按位或 表达式|表达式 左到右
11 && 逻辑与 表达式&&表达式 左到右
12 || 逻辑或 表达式||表达式 左到右
13 ?: 条件运算符 表达式 1? 表达式 2: 表达式 3 右到左
14
= 赋值运算符 变量=表达式
右到左
/= 除后赋值 变量/=表达式
*= 乘后赋值 变量*=表达式
%= 取模后赋值 变量%=表达式
+= 加后赋值 变量+=表达式
-= 减后赋值 变量-=表达式
<<= 左移后赋值 变量
>>= 右移后赋值 变量>>=表达式
&= 按位与后赋值 变量&=表达式
^= 按位异或后赋值 变量^=表达式
|= 按位或后赋值 变量|=表达式
15 , 逗号运算符 表达式,表达式,... 左到右
注意:
如果不确定运算符的优先级,可以加括号;
多用括号,让代码的可读性更好。
2)示例
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
int a, b, c;
c = 10; // 赋值表达式的值为赋值符号右边的值。
cout << "(c = 10)=" << (c = 10) << endl;
a = b = c = 10; // 赋值运算的结合律是从右到左。
}
///
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// main 函数,程序从这里开始执行,每个程序只能有一个 main 函数。
int main()
{
int a, b, c, d;
a = 4, b = 2, c = 5;
d = a * (b / c); // 算术运算的结合律是从左到右。
cout << "d=" << d << endl;
}
18、if 语句的基本结构
语法:
if (表达式)
{
// 表达式为真时执行的语句。
}
else
{
// 表达式为假时执行的语句。
}
注意:
if (表达式)之间的空格可以不写。
表达式必须使用括号。
表达式可以是具体的值。
表达式一般是关系运算和逻辑运算表达式,也可以是赋值运算或其它的表达式。
不要把 if(变量名==值)写成 if(变量名=值)。
整个 if 语句可以没有 else 分支。
if 或 else 分支花括号内的代码如果只有一行,花括号可以不写;如果一行也没有,花括号一定要
写;如果有多行,花括号一定要写,如果不写,除了第一行,其它的代码将不是 if 语句的一部分。
if (表达式)和 else 后不能加分号,因为分号表示空语句。(C++用分号作为一条语句结束的标
志。如果在 C++程序中不小心多写了一个分号,那么该分号会被当成一条空语句。)
2)示例
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// C++用分号作为一条语句结束的标志。
// 如果在 C++程序中不小心多写了一个分号,那么该分号也许会被视作一个空语句。
// 判断超女的颜值,如果漂亮,在控制台输出"晋级下一轮",否则输出"冲关失败"。
// 1)声明一个 bool 型变量,用于存放超女的颜值数据。
bool yz;
// 2)显示输入超女颜值的提示信息。
cout << "请输入超女的颜值(1-漂亮;0-不漂亮):";
// 3)输入超女的颜值数据,存放在变量中。
cin >> yz;
// 4)用 if 语句判断超女的颜值,如果漂亮,显示"晋级下一轮",否则显示"冲关失败"。
if (yz == true)
{
cout << "小姐姐很漂亮哟!" << endl;
cout << "恭喜您,晋级下一轮!" << endl;
}
else
{
cout << "对不起,冲关失败!" << endl;
cout << "推荐一个美容院,......" << endl;
}
}
19、嵌套使用 if 语句
1)嵌套使用 if 语句
if 语句可以嵌套使用,实现多级(层)的条件判断(最多 127 层)。
语法:
if (表达式一)
{
if (表达式二)
{
// 表达式二为真时执行的语句。
}
else
{
// 表达式二为假时执行的语句。
}
}
else
{
// 表达式一为假时执行的语句。
}
2)示例
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// 超女选秀:1)性别(X-女,Y-男);2)颜值(1-漂亮,0-不漂亮);3)身材(1-火辣,
2-丰满,3-苗条)。
// 声明三个变量,存放超女的性别、颜值和身材数据。
char sex; // 性别(X-女,Y-男)。
bool yz; // 颜值(1-漂亮,0-不漂亮)。
int sc; // 身材(1-火辣,2-丰满,3-苗条)。
// 显示"请输入超女的性别(X-女,Y-男):"的提示文字。
cout << "请输入超女的性别(X-女,Y-男):";
// 输入超女的性别,存放在变量中。
cin >> sex;
// 判断超女的性别,如果是女,流程继续,否则程序结束。
if (sex == 'X')
{
// 显示"请输入超女的颜值(1-漂亮,0-不漂亮):"的提示文字。
cout << "请输入超女的颜值(1-漂亮,0-不漂亮):";
// 输入超女的颜值,存放在变量中。
cin >> yz;
// 判断超女的颜值,如果是漂亮,流程继续,否则程序结束。
if (yz == true) // 漂亮。
{
// 显示"请输入超女的身材(1-火辣,2-丰满,3-苗条):"的提示文字。
cout << "请输入超女的身材(1-火辣,2-丰满,3-苗条):";
// 输入超女的身材,存放在变量中。
cin >> sc;
// 判断超女的身材,如果是火辣,显示"晋级成功",如果是丰满,显示"待定",程
序结束。
if (sc == 1) // 1-火辣。
{
cout << "晋级成功!" << endl;
}
else
{
if (sc == 2) // 2-丰满
{
cout << "待定!" << endl;
}
}
}
}
}
20、嵌套 if 语句的坑
嵌套使用 if 语句时候,会出现 if 与 else 的配对问题。
C++编译器处理该问题的原则是:else 总是与前面最近 if 配对。
如果要改变这种配对关系,可以使用花括号来确定新的配对关系。
if (sex == 'X')
if (yz == true)
cout << "sex==X,yz==true\n";
else
cout << "sex==Y,yz==true or false\n";
以上代码中的 else 与第二个 if 配对,如果想让它与第一个 if 配对,代码如下:
if (sex == 'X')
{
if (yz == true)
cout << "sex==X,yz==true\n";
}
else
cout << "sex==Y,yz==true or false\n";
21、多条件的 if 语句
1)多条件的 if 语句
语法:
if (表达式一)
{
// 表达式一为真时执行的语句。
}
else if (表达式二)
{
// 表达式二为真时执行的语句。
}
else if (表达式三)
{
// 表达式三为真时执行的语句。
}......
else if (表达式 n)
{
// 表达式 n 为真时执行的语句。
}
else
{
// 全部表达式都不为真时执行的语句。
}
注意:
多条件的 if 语句本质上是嵌套的 if 语句。
最多只能有 127 个条件分支。
最后一个 else 可以没有。
2)示例
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// 超女的身材:1-火辣;2-丰满;3-苗条;4-强壮;5-肥胖;>5-未知 。
// 声明存放超女身材数据的变量。
int sc;
// 显示"请输入身材的代码(1-火辣;2-丰满;3-苗条;4-强壮;5-肥胖;>5-未知):"的提
示文字。
cout << "请输入身材的代码(1-火辣;2-丰满;3-苗条;4-强壮;5-肥胖;其它表示未知):
";
// 输入超女身材的代码,存放在变量中。
cin >> sc;
// 用多条件的 if 语句,判断身材代码,显示身材的中文描述。
if (sc == 1) cout << "火辣!\n";
else if (sc == 2) cout << "丰满!\n";
else if (sc == 3) cout << "苗条!\n";
else if (sc == 4) cout << "强壮!\n";
else if (sc == 5) cout << "肥胖!\n";
else cout << "未知!\n";
}
22、if 语句中的逻辑表达式
采用括号、对齐、空格、换行有助于更清晰的表达复杂的逻辑表达式。
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// 超女的数据:年龄(16-50 岁),身高(150cm-190cm),身材(火辣;丰满;苗条)
// 颜值(漂亮;一般;歪瓜裂枣)。
// 晋级的标准:年龄 25-30 岁,身高 165cm-175cm,身材火辣,颜值漂亮或者一般。
// 已准备好的超女数据。
int age = 28;
int height = 170;
string sc = "火辣";
string yz = "漂亮";
if ( (age > 25 && age < 30 ) && // 年龄
(height > 165 && height < 175 ) && // 身高
(sc == "火辣" ) && // 身材
(yz == "漂亮" || yz == "一般" ) ) // 颜值
{
cout << "晋级成功!\n";
}
}
23、三目运算
三目运算也叫条件运算或三元运算,可以实现简单 if 语句的功能,但是书写更简洁。
语法: 表达式一 ? 表达式二 : 表达式三
先计算表达式一的值,如果为真,整个表达式的结果为表达式二的值,如果为假,整个表达式的结果
为表达式三的值。
int a,b,c;
a=7;
b=6;
c=(a>b)?a:b;
等同于
if (a>b) c=a;
else c=b;
三目运算表达式可以嵌套使用,但是,过于复杂的三目运算表达式不方便理解。
比如判断 year 是不是闰年,是则返回 1,不是返回 0。
int year;
year=(year%100==0)?(year%400==0?1:0):(year%4==0?1:0)
1 、普通年能被 4 整除且不能被 100 整除的为闰年。
2 、世纪年能被 400 整除的是闰年。
3 、对于数值很大的年份,这年如果能整除 3200,并且能整除 172800 则是闰年。如 172800 年是
闰年,86400 年不是闰年。
24、switch 语句
switch 也是一种选择结构的语句,可以代替简单的多条件的 if 语句。
语法:
switch (表达式)
{
case 值一:
语句一;
break;
case 值二:
语句二;
break;
...... case 值 n:
语句 n;
break;
default:
上述条件都不满足时执行的语句;
}
注意:
case 后面必须是整数和字符,或者是结果为整数和字符的表达式,但不能使用变量。
default 不是必须的,当没有 default 时,如果全部的 case 匹配失败,那么就什么都不执行。
每个分支不要漏写 break;语句。
25、while 循环语句
语法:
while (表达式)
{
语句块
}
先计算表达式的值,如果为真就执行语句块,执行完语句块后,回到循环首部再次计算表达式的值,
如果为真又执行一次语句块......,这个过程会一直重复,直到表达式的值为假时不再执行语句块。
注意:
如果表达式的值永远为真,那么将进入死循环,所以在循环中应该有改变表达式的值的方法。
如果循环体中的语句块只有一行代码,大括号可以不书写。
有疑问先放一边,在以后的课程中,会介绍循环的各种使用方法。
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// 有十个超女,编号是 1-10,在控制台输出这十个超女的编号。
int no = 1; // 超女的编号。
while (no <= 10)
{
cout << "这是第" << no++ << "名超女的编号。\n";
}
}
26、循环的跳转
break 和 continue 两个关键字用于控制循环体中代码的执行流程。
break 跳出(中止)当前循环语句。
continue 回到当前循环语句的首部。
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// break 跳出(中止)当前循环语句,continue 回到当前循环语句的首部。
// 程序运行后一直工作,逐个输入超女的数据,判断是否晋级,如果到了休息时间,就把程序停
下来。
// 超女选秀的流程:1)如果漂亮,直接晋级;2)不漂亮也行,身材火辣的也可以晋级。
bool once = true; // 是否为第一次执行循环。
while (true)
{
if (once == false)
{
// a)显示"是否继续下一名超女选秀(1-继续,0-结束):"的提示文字。
cout << "是否继续下一名超女选秀(1-继续,0-结束):";
// b)输入是否继续的决定,存放在变量中。
bool exist; cin >> exist;
// c)判断输入的决定,如果是结束,流程跳出循环。
if (exist == false) break;
}
once = false; // 表示循环已经被执行过。
// 1)显示"请输入超女的颜值(1-漂亮,0-不漂亮):"的提示文字。
cout << "请输入超女的颜值(1-漂亮,0-不漂亮):";
// 2)输入超女的颜值,存放在变量中。
bool yz; cin >> yz;
// 3)判断超女的颜值,如果漂亮,显示"晋级成功",流程跳转到循环的首部。
if (yz == true)
{
cout << "晋级成功\n"; continue;
}
// 4)显示"请输入超女的身材(1-火辣,0-不辣):"的提示文字。
cout << "请输入超女的身材(1-火辣,0-不辣):";
// 5)输入超女的身材,存放在变量中。
bool sc; cin >> sc;
// 6)判断超女的身材,如果火辣,显示"晋级成功"。
if (sc == true) cout << "晋级成功\n";
}
}
27、for 循环语句
语法:
for (语句一 ; 表达式 ; 语句二)
{
语句块
}
1)循环开始的时候,先执行语句一,在整个循环过程中语句一只会被执行一次。
2)计算表达式的值,如果为真,就执行一次循环体中的语句块。
3)执行完语句块后,执行一次语句二。
4)重复第 2)步和第 3),直到表达式的值不为真才结束 for 循环。
注意:
不要纠结 for 循环与 while 循环的区别,它们本质上没有区别。
for 循环一般需要一个相当于计数器的变量,在语句一中对它进行初始化,在语句二中进行计数
操作。
在 for 循环的语句一中,可以声明计数器变量。
在 for 循环中,语句一、表达式和语句二都可以为空,for (;;)等同于 while (true)。
continue 和 break 两个关键字也可以用在 for 循环体中。
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// 有十个超女,编号是 1-10,在控制台输出这十个超女的编号。
for (int no = 1; no <= 10; no++)
{
cout << "这是第" << no << "名超女的编号。\n";
}
}
28、嵌套使用循环
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// 超女分 4 个小组,每个小组有 3 名超女,在控制台显示每个超女的小组编号和组内编号。
// 用一个循环,显示 4 个小组的信息。
//for (int ii=1; ii<=4; ii++)
//{
// // 再用一个循环,显示一组中 3 名超女的信息。
// for (int jj = 1; jj <= 3; jj++)
// {
// cout << "这是第" <<ii<<"个小组的第" << jj << "名超女。\n";
// }
//}
// 在控制台输出九九乘法表。
for (int ii=1; ii<=9; ii++)
{
for (int jj = 1; jj <= ii; jj++)
{
cout << ii << "*" << jj << "=" << ii*jj <<" ";
}
cout << endl;
}
}
29、do...while 循环语句
语法:
do
{
语句块
} while (表达式);
功能与 while 语句类似,不同的是:
进入循环时,先执行一次语句块,再计算表达式的值。
循环的首部书写在循环的尾部,(表达式)后面还有一个分号。
30、goto 语句
goto 语句也称为无条件转移语句。
goto 的语法:goto 语句标号;
语句标号的语法:语句标号:
如果在程序中使用了 goto,程序的流程将跳转到语句标号的位置,并执行它后面的代码。
其中语句标号是按标识符规定书写的符号,放在某一语句行的前面,可以独占一行,标号后加半角冒
号。
语句标号用于标识语句的位置,与 goto 语句配合使用。
在实际开发中,goto 语句容易造成程序流程的混乱,不方便理解,调试也更麻烦,不建议使用。
31、函数的声明和定义
在复杂的程序中,如果全部的代码都写在 main 函数中,main 函数体将非常庞大臃肿。
把任务分工到其它的函数中,main 函数只负责程序的核心流程,具体的任务由其它函数完成。
这种思想就是模块化编程。
声明和定义函数的语法:
返回值的数据类型 函数名(参数一的数据类型 参数一, 参数二的数据类型 参数二,......)
{
实现函数功能的代码。
return 返回值;
}
函数的声明:让编译器知道函数的存在,包括返回值的数据类型、函数名和参数列表。
函数的定义:函数的实现过程。
注意:
函数的声明和定义可以书写在一起,也可以分开,如果书写在一起,一般放在 main 函数的上面,
如果分开,一般在 main 函数的上面声明,在 main 函数的下面定义。
如果函数的声明和定义分开书写,函数的声明后面一定要有分号,函数的定义后面一定不能写分
号。
在同一个程序中,函数只需要声明和定义一次,也可以多次声明,但只能定义一次。
函数的声明必须和函数的定义一致(返回值的数据类型、函数名和参数列表),如果函数名和参
数列表不同,表示它们不是同一个函数。
return 语句返回值的数据类型必须与函数的声明一致。
在函数体中,return 语句可以多次使用。
如果函数的重点是实现功能,不关心返回值,返回值的数据类型填 void,return 语句后面就空
着。
函数可以没有任何参数。
函数名是标识符,必须满足标识符的命名规则。
在函数的声明和函数的定义中,参数命名可以不同,但是没必要这么书写。
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// 写一个函数,给它两个整数,让它比较两个整数的大小,返回较大的那个整数。
int max(int a, int b); // 函数声明后面的分号不能少。
// 写一个函数,给它一个字符串,让它在控制台显示出来。
void print(string str);
// 写一个函数,在控制台输出九九乘法表。
void printmt();
int main()
{
}
int max(int a, int b) // 函数定义后面不能加分号。
{
if (a > b) return a;
return b;
}
void print(string str)
{
cout << str << endl;
return;
}
void printmt()
{
// 在控制台输出九九乘法表。
for (int ii = 1; ii <= 9; ii++)
{
for (int jj = 1; jj <= ii; jj++)
{
cout << ii << "*" << jj << "=" << ii * jj << " ";
}
cout << endl;
}
return;
}
32、函数的调用
语法:函数名(参数一,参数二,......)
注意:
声明函数的代码必须放在调用之前,定义函数的代码可以放在调用之后。
调用函数的时候,参数列表必须与函数的声明一致(参数的个数、书写的顺序和数据类型)。
不管在什么地方,都不能调用 main 函数,但是,在普通函数中,可以调用其它的普通函数。
调用函数的代码可以独占一条语句,也可以用于表达式(赋值运算、算术运算、关系运算、函数
的参数)。
如果函数用于表达式中,返回值的数据类型要匹配(否则可能会被隐式转换或编译错误)。
如果函数有返回值,可以不关心它,忽略它。
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// 写一个函数,给它两个整数,让它比较两个整数的大小,返回较大的那个整数。
int max(int a, int b); // 函数声明后面的分号不能少。
// 写一个函数,给它两个参数:no-超女编号,str-表白的内容。
void print(int no,string str);
// 写一个函数,在控制台输出九九乘法表。
void printmt();
int main()
{
cout << "max(5,8)=" << max(5,8) << endl;
print(8, "请借给我五分钱吧。");
printmt();
}
int max(int a, int b) // 函数定义后面不能加分号。
{
if (a > b) return a;
return b;
}
void print(int no, string str)
{
cout << "亲爱的"<<no<<"号:"<<str << endl;
return;
}
void printmt()
{
// 在控制台输出九九乘法表。
for (int ii = 1; ii <= 9; ii++)
{
for (int jj = 1; jj <= ii; jj++)
{
cout << ii << "*" << jj << "=" << ii * jj << " ";
}
cout << endl;
}
return;
}
33、变量的作用域
作用域是指程序中变量存在(或生效)的区域,超过该区域变量就不能被访问。
变量分全局变量和局部变量两种,全局变量在整个程序中都可以访问,局部变量只能在函数或语句块
的内部才能访问。
C++中定义变量的场景主要有五种:
1)在全部函数外面定义的是全局变量。
2)在头文件中定义的是全局变量。
3)在函数和语句块内部定义的是局部变量。
4)函数的参数是该函数的局部变量。
5)函数内部用 static 修饰的是静态局部变量。
1)全局变量
在整个程序生命周期内都是有效的,在定义位置之后的任意函数中都能访问。
全局变量在主程序退出时由系统收回内存空间。
2)局部变量
在函数或语句块内部的语句使用,在函数或语句块外部是不可用的。
局部变量在函数返回或语句块结束时由系统收回内存空间。
3)静态局部变量
用 static 修饰的局部变量生命周期和程序相同,并且只会被初始化一次。
其作用域为局部,当定义它的函数或语句块结束时,其作用域随之结束。
当程序想要使用全局变量的时候应该先考虑使用 static(考虑到数据安全性)。
4)注意事项
全局变量和静态局部变量自动初始化为 0。
局部变量不会自动初始化,其值是不确定的,程序中应该有初始化局部变量的代码,否则编译可
能会报错(不同的编译器不一样)。
局部变量和全局变量的名称可以相同,在某函数或语句块内部,如果局部变量名与全局变量名相
同,就会屏蔽全局变量而使用局部变量,如果想使用全局变量,可以在变量名前加两个冒号(::)。
for 循环初始化语句中定义的变量的作用域是 for 语句块。
34、函数参数的传递
调用函数的时候,调用者把数值赋给了函数的参数。
实参:调用者程序中书写的在函数名括号中的参数,可以是常量、变量和表达式。
形参:函数的参数列表。
在函数定义的代码中,修改形参的值,会不会影响实参。
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
// 调用函数的时候,调用者把数值赋给了函数的参数。
// 实参:调用者程序中书写的在函数名括号中的参数,可以是常量、变量和表达式。
// 形参:函数的参数列表。
// 在函数定义的代码中,修改形参的值,会不会影响实参?
void func(int no, string str); // 向超女表白的函数。
int main()
{
int bh = 3; // 超女的编号。
string message = "我是一只傻傻鸟。"; // 向超女表白的内容。
// func(bh, message); // 调用向超女表白的函数。
// func(7, "小姐姐好漂亮哟。"); // 调用向超女表白的函数。
{
int no=7;
string str= "小姐姐好漂亮哟。";
no = 5; str = "我有一只小小鸟。";
cout << "亲爱的" << no << "号:" << str << endl;
}
cout << "亲爱的" << bh << "号:" << message << endl;
}
void func(int no, string str) // 向超女表白的函数。
{
no = 5; str = "我有一只小小鸟。";
cout << "亲爱的" << no << "号:" << str << endl;
}
35、函数分文件编写
头文件(*.h):需要包含的头文件,声明全局变量,函数的声明,数据结构和类的声明等。
源文件(*.cpp):函数的定义、类的定义。
主程序:main 函数,程序的核心流程,需要用#include "头文件名"把头文件包含进来。
编译:
Windows 是集成开发环境,不需要写编译指令。
在 Linux 系统下,把全部的源文件一起编译,如:g++ -o demo demo.cpp tools.cpp girls.cpp
示例:
/*demo01.cpp*/
#include "tools.h" // 包含头文件 tools.h,min 和 max 函数在里面。
#include "girls.h" // 包含头文件 girls.h,print 函数在里面。
int main()
{
cout << "max(5,8)=" << max(5, 8) << endl;
cout << "min(5,8)=" << min(5, 8) << endl;
print(3, "我是一只傻傻鸟。");
}
/*girls.cpp*/
#include "girls.h" void print(int no, string str) // 表白神器。
{
cout << "亲爱的" << no << "号:" << str << endl;
}
/*tools.cpp*/
#include "tools.h"
int max(int a, int b) // 比较两个数的大小,返回较大者。
{
return a > b ? a : b;
}
int min(int a, int b) // 比较两个数的大小,返回较小者。
{
return a < b ? a : b;
}
/*girls.h*/
#pragma once
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
void print(int no, string str); // 表白神器。
/*toolss.h*/
#pragma once
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int max(int a, int b); // 比较两个数的大小,返回较大者。
int min(int a, int b); // 比较两个数的大小,返回较小者。
36、VS 中调试程序
F9 设置/取消断点。
F5/F10 开始调试。
Shift+F5 放弃调试。
F10 逐过程执行。
F11 逐语句执行(可进入函数内部)。
局部变量窗口显示了变量的值,也可以修改。
37、递归函数
一个函数可以调用另一个函数,作为特例,如果函数调用了自己,就像故事中提到了同样的故事一样,
我们把函数在运行时调用自己的情况叫做递归。
递归函数中一定要有递归终止的条件,否则是死递归。
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int f(int x) // 递归函数。
{
if (x == 0) return 0; // 递归终止的条件。
return x + f(x - 1); // 在函数体中调用了自己。
}
int main()
{
cout << "f(100)=" << f(100) << endl;
// 100+99+98+....+1+0
// 嵌套的调用函数 进入函数的过程是递去 函数返回的过程是归来
// 计算从 1 加到 100 的和。
int sum = 0; // 存放累加的值。
for (int ii = 1; ii <= 100; ii++)
sum = sum + ii;
cout << "sum=" << sum << endl;
}
38、sizeof 运算符
sizeof 运算符用于求数据类型或变量占用的内存空间。
用于数据类型:sizeof(数据类型)
用于变量:sizeof(变量名) 或 sizeof 变量名
注意:
在 32 位和 64 位操作系统中,同一种数据类型占用的内存空间可能不一样。
字符串(string)不是 C++的基本数据类型,用 sizeof 求它占用内存的大小没有意义。
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// 用于数据类型:sizeof(数据类型)
// 用于变量:sizeof(变量名) 或 sizeof 变量名
// C++常用的数据类型:整数(int)、浮点数(float 和 double)、字符(char)和布尔(bool)。
cout << "sizeof(int)=" << sizeof(int) << endl;
cout << "sizeof(float)=" << sizeof(float) << endl;
cout << "sizeof(double)=" << sizeof(double) << endl;
cout << "sizeof(char)=" << sizeof(char) << endl;
cout << "sizeof(bool)=" << sizeof(bool) << endl;
int i; cout << "sizeof(int)=" << sizeof i << endl;
float f; cout << "sizeof(float)=" << sizeof f << endl;
double d; cout << "sizeof(double)=" << sizeof d << endl;
char c; cout << "sizeof(char)=" << sizeof c << endl;
bool b; cout << "sizeof(bool)=" << sizeof b << endl;
}
39、整型的基本概念
C++用 int 关键字来声明整型变量(int 是 integer 的简写)。
在声明整型变量的时候,可以在 int 关键字之前加 signed、unsigned、short 和 long 四种修饰符。
signed:有符号的,可以表示正数和负数。
unsigned:无符号的,只能表示正数,例如超女的身高和体重等。
short:短的,取值范围小,占用内存少。
long:长的,取值范围大,占用内存多。
类型简写 类型全称 长度 取值范围
short signed short int 2 字节 -32768~32767
unsigned short unsigned short int 2 字节 0~65535
int signed int 4 字节 -2147483648~2147483647
unsigned unsigned int 4 字节 0~4294967295
long signed long int 8 字节
-9223372036854775808~
9223372036854775807
unsigned long unsigned long int 8 字节 0~18446744073709551615
注意:
整数的取值范围与计算机操作系统和 C++语言编译器有关,没有一个固定的数值,我们可以根
据它占用的内存大小来推断它的取值范围。
一个位的取值是 0 1 1=2
1-1
两个位的取值是 00 01 10 11 3=2
2-1
三个位的取值是 000 001 ...... 111 7=2
3-1
a)一个字节有 8 个位,表示的数据的取值范围是 2
8-1,即 255。
b)如果占用的内存是两个字节,无符号型取值范围是 2
8ⅹ2
8-1。
c)如果占用的内存是四个字节,无符号型取值范围是 2
8ⅹ2
8ⅹ2
8ⅹ2
8-1。
d)如果占用的内存是八个字节,无符号型取值范围是 2
8ⅹ2
8ⅹ2
8ⅹ2
8ⅹ2
8ⅹ2
8ⅹ2
8ⅹ2
8-1。
e)如果是有符号,取值范围减半,因为符号占一个位。
f)计算机用最高位 1 位来表达符号(0-正数,1-负数),unsigned 修饰过的正整数不需要符号
位,在表达正整数的时候比 signed 修饰的正整数取值大一倍。
给整型变量赋值不能超出它的取值范围,否则能产生不可预后的后果。
在实际开发中,为了防止超出取值范围,应该保证有足够的空间。
40、整数的书写
整数默认是十进制,一个表示十进制的数字不需要任何特殊的格式。
1、二进制
二进制由 0 和 1 两个数字组成,书写时必须以 0b 或 0B(不区分大小写)开头。
以下是合法的二进制:
int a = 0b101; // 换算成十进制为 5
int b = -0b110010; // 换算成十进制为 -50
int c = 0B100001; // 换算成十进制为 33
以下是非法的二进制:
int m = 101010; // 无前缀 0B,相当于十进制
int n = 0B410; // 4 不是有效的二进制数字
注意,C++标准并不支持上面的二进制写法,只是有些编译器自己进行了扩展,才支持二进制数字。
换句话说,并不是所有的编译器都支持二进制数字,只有一部分编译器支持,并且跟编译器的版本有关系。
2、八进制
八进制由 0~7 八个数字组成,书写时必须以 0 开头(注意是数字 0,不是字母 o)。
以下是合法的八进制数:
int a = 015; // 换算成十进制为 13
int b = -0101; // 换算成十进制为 -65
int c = 0177777; // 换算成十进制为 65535
以下是非法的八进制:
int m = 256; // 无前缀 0,相当于十进制
int n = 03A2; // A 不是有效的八进制数字
3、十六进制
十六进制由数字 0~9、字母 A~F 或 a~f(不区分大小写)组成,书写时必须以 0x 或 0X(不区分
大小写)开头。
以下是合法的十六进制:
int a = 0X2A; // 换算成十进制为 42
int b = -0XA0; // 换算成十进制为 -160
int c = 0xffff; // 换算成十进制为 65535
以下是非法的十六进制:
int m = 5A; // 没有前缀 0X,是一个无效数字
int n = 0X3H; // H 不是有效的十六进制数字
4、需要注意的坑
在 C++中,不要在十进制数前面加 0,会被编译器当成八进制。
还有,不要随便删掉别人程序中整数前面的 0,它不是多余的。
41、C++11 的 long long 类型
在 VS 中,long 是 4 字节,32 位。 -2147483648~2147483647
在 Linux 中,long 是 8 字节,64 位。 -9223372036854775808~9223372036854775807
C++11 标准增了 long long 类型的整数,至少 64 位,且至少与 long 一样长。
在 VS 中,long long 是 8 字节,64 位。 -9223372036854775808~9223372036854775807
在 Linux 中,long 和 long long 类型都是 8 字节,64 位。
42、浮点型(实数型)
C++浮点型分三种:float(单精度)、double(双精度)、long double(扩展精度)。
三者的区别是表示有效数字的范围不同。
数据类型 占用空间 有效数字范围
float 4 字节 7 位有效数字 8 位
double 8 字节 15~16 位有效数字 17 位
long double 不少于 double 不低于 double 17 位
注意:
在 VS 和 Linux 中,long double 占用的内存空间分别是 8 和 16 字节。
有效数字包括了小数点前面和后面的数字。
C++缺省显示 6 位有效数字,如果要显示更多的有效数字,可以用 printf()函数。
浮点数的存储方法和整数不一样,比较复杂,如无必要,不用研究。(百度"为什么浮点数的小
数位很多"、"为什么浮点数不精确")
在实际开发中,用整数代替浮点数,整数的运算更快,精度更高。9223372036854775807
示例:
#include <stdio.h> // 使用 printf 函数需要包含这个头文件。
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// float 7 位有效数字;double 15~16 位有效数字;long double 不低于 double
float aa = 1234.45f; cout << "aa=" << aa << endl;
double bb = 12345123056789.45; cout << "bb=" << bb << endl;
long double cc = 12345126789.459; cout << "cc=" << cc << endl;
printf("aa=%lf\n", aa);
printf("bb=%lf\n", bb);
printf("cc=%lf\n", cc);
}
43、字符型的基本概念
字符型(char)占用的内存空间是 1 个字节,书写用单引号包含。
在内存中,不存放字符本身,而是存放与它对应的编码,即 ASCII 码。
ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是现今
最通用的单字节编码方案,包含了 33 个控制字符(具有特殊含义无法显示的字符)和 95 个可显示字符。
'X' -> 88 01011000 'a'->97 01100001 '3'->51 00110011
1)ASCII 控制字符 (0~31)
十进制 符号 中文解释 十进制 符号 中文解释
0 NULL 空字符 16 DLE 数据链路转义
1 SOH 标题开始 17 DC1 设备控制 1
2 STX 正文开始 18 DC2 设备控制 2
3 ETX 正文结束 19 DC3 设备控制 3
4 EOT 传输结束 20 DC4 设备控制 4
5 ENQ 询问 21 NAK 拒绝接收
6 ACK 收到通知 22 SYN 同步空闲
7 BEL 铃 23 ETB 传输块结束
8 BS 退格 24 CAN 取消
9 HT 水平制表符 25 EM 介质中断
10 LF 换行键 26 SUB 替换
11 VT 垂直制表符 27 ESC 换码符
12 FF 换页键 28 FS 文件分隔符
13 CR 回车键 29 GS 组分隔符
14 SO 移出 30 RS 记录分离符
15 SI 移入 31 US 单元分隔符
2)ASCII 可显示字符 (32~127)
十进制 符号 中文解释 十进制 符号 中文解释
32 空格 80 P 大写字母 P
33 ! 感叹号 81 Q 大写字母 Q
34 " 双引号 82 R 大写字母 R
35 # 井号 83 S 大写字母 S
36 $ 美元符 84 T 大写字母 T
37 % 百分号 85 U 大写字母 U
38 & 与 86 V 大写字母 V
39 ' 单引号 87 W 大写字母 W
40 ( 左括号 88 X 大写字母 X
41 ) 右括号 89 Y 大写字母 Y
42 * 星号 90 Z 大写字母 Z
43 + 加号 91 [ 左中括号
44 , 逗号 92 \ 斜线
45 - 减号 93 ] 右中括号
46 . 句点或小数点 94 ^ 音调符号
47 / 反斜线 95 _ 下划线
48 0 数字 0 的符号 96 ` 重音符
49 1 数字 1 的符号 97 a 小写字母 a
50 2 数字 2 的符号 98 b 小写字母 b
51 3 数字 3 的符号 99 c 小写字母 c
52 4 数字 4 的符号 100 d 小写字母 d
53 5 数字 5 的符号 101 e 小写字母 e
54 6 数字 6 的符号 102 f 小写字母 f
55 7 数字 7 的符号 103 g 小写字母 g
56 8 数字 8 的符号 104 h 小写字母 h
57 9 数字 9 的符号 105 i 小写字母 i
58 : 冒号 106 j 小写字母 j
59 ; 分号 107 k 小写字母 k
60 < 小于 108 l 小写字母 l
61 = 等号 109 m 小写字母 m
62 > 大于 110 n 小写字母 n
63 ? 问号 111 o 小写字母 o
64 @ 电子邮件符号 112 p 小写字母 p
65 A 大写字母 A 113 q 小写字母 q
66 B 大写字母 B 114 r 小写字母 r
67 C 大写字母 C 115 s 小写字母 s
68 D 大写字母 D 116 t 小写字母 t
69 E 大写字母 E 117 u 小写字母 u
70 F 大写字母 F 118 v 小写字母 v
71 G 大写字母 G 119 w 小写字母 w
72 H 大写字母 H 120 x 小写字母 x
73 I 大写字母 I 121 y 小写字母 y
74 J 大写字母 J 122 z 小写字母 z
75 K 大写字母 K 123 { 左大括号
76 L 大写字母 L 124 | 竖线
77 M 大写字母 M 125 } 右大括号
78 N 大写字母 N 126 ~ 波浪号
79 O 大写字母 O 127 删除
a)32 是空格。
b)48~57 是 0 到 9 十个阿拉伯数字;
c)65~90 是 26 个大写英文字母;
d)97~122 号是 26 个小写英文字母;
e)其余的是一些标点符号、运算符号等;
f)第 127 个字符表示的是键盘上的删除键。
3)字符的本质
a)字符的本质是整数,取值范围是 0~127。
b)在书写的时候可以用单引号包含,也可以用整数。
c)如果书写的时候用单引号包含,程序执行的时候,将把符号解释为对应的整数。
d)显示的时候,把整数解释为对应的符号,也可以直接显示整数。
d)可以与整数进行任何运算,运算的时候,书写方式可以用字符,也可以用整数。
e)C++为什么没有提供 1 字节的整型?
f)字符型也可以用 unsigned 修饰,意义何在?
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// 字符型(char)占用的内存空间是 1 个字节,书写用单引号包含。
int a = 'X';
cout << "a=" << a << endl;
cout << "sizeof(a)=" << sizeof(a) << endl;
// 1234567 00000000 00010010 11010110 10000111
// 'X' -> 88 'a'->97 '3'->51
}
44、转义字符
在 C++程序中,使用转义字符的原因有两个:
控制字符没有符号,无法书写,只能用其它的符号代替。
某些符号已被 C++征用,语义冲突,只能用其它的符号代替。
ASCII 码值 转义字符 含义
0 \0 空,给字符型变量赋值时可以直接书写 0。
10 \n 换行(LF) ,将当前位置移到下一行开头。
13 \r 回车(CR) ,将当前位置移到本行开头
9 \t 水平制表(HT) (跳到下一个 TAB 位置)
92 \\ 斜线
34 \" 双引号,书写字符时不必转义。
39 \' 单引号,书写字符串中不必转义。
7 \a 警报
8 \b 退格(BS) ,将当前位置移到前一列
12 \f 换页(FF),将当前位置移到下页开头
ASCII 码值 转义字符 含义
11 \v 垂直制表(VT)
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// 字符型(char)占用的内存空间是 1 个字节,书写用单引号包含。
char a = '\'';
cout << "a=" << a << endl;
// 换行符 ASCII 值是 10 书写用\n
cout << "我是一'只傻傻鸟!\n";
// 水平制表符用于对齐输出的内容。
cout << "1\t 西施\n";
cout << "100\t 西瓜\n";
cout << "10000\t 冰冰\n";
}
45、C++11 的原始字面量
原始字面量(值)可以直接表示字符串的实际含义,不需要转义和连接。
语法:R"(字符串的内容)" R"xxx(字符串的内容)xxx"
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// 使用转义的方法
string path = "C:\\Program Files\\Microsoft OneDrive\\tail\\nation";
cout << "path is " << path << endl;
// 使用 C++11 原始字面量
string path1 = R"abcd(C:\Program Files\Microsoft OneDrive\tail\nation)abcd";
cout << "path1 is " << path1 << endl;
string str = R"(
<no>0001</no>
<name>西施</name>
<sc>火树银花</sc>
<yz>沉鱼</yz>
<age>23</age>
<weight>48.5</weight>
<height>170</height>)";
cout << str << endl;
}
46、字符串型
C++风格字符串:string 变量名="字符串的内容" ;
C 风格字符串:char 变量名[]="字符串的内容" ;
C 风格字符串的本质是字符数组,C++风格字符串的本质是类,它封装了 C 风格字符串。
C++风格字符串的常用操作:
赋值:变量名="字符串的内容" ;
拼接:变量名=变量名+"字符串的内容一"+"字符串的内容一"+......+"字符串的内容 n" ;
如果字符串的内容都是常量,不要写加号(+),如果内容很长,可以分成多行书写。
比较:支持==、!=、>和<关系运算符,常用的是==和!=。
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
string str="西施"; // 声明字符串变量并初始化。
str = "美女西施"; // 对字符串变量重新赋值。
cout << "请输入超女姓名:"; // 输出提示文字内容。
cin >> str; // 从控制台输入数据,保存在变量 str
中。
if (str == "冰冰") cout << "我喜欢\n"; // 用==可以判断两个字符串是否相同。
if (str != "冰冰") cout << "我不玩了\n"; // 用!=可以判断两个字符串是否不相同。
str = "姓名:" + str + ",这是我现女友。"; // 用+可以拼接多个字符串。
// 如果字符串的内容都是常量,不要写加号(+),如果内容很长,可以分成多行书写。
str = "超女姓名:"
"幂幂"
",这是我的前女友。";
cout << str << endl;
}
47、布尔型
在 C 和 C++中,关系运算和逻辑运算的结果有两种:真和假。
C 语言用 0 表示假,非 0 表示真。
为了提高代码的可读性,C++新增了 bool 类型,占用 1 字节的内存,用 true 表示真,false 表示假。
bool 类型本质上是 1 字节的整数(unsigned char),取值只有 1 和 0。
在程序中,书写的时候可以用 true 和 false,编译器把它们解释为 1 和 0。
如果对 bool 型变量赋非 0 的值,将转换成 1。
用 cin 输入和 cout 输出的时候,仍是 1 和 0,不会被解释为 true 和 false。
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
bool b = 1;
cout << "b+b=" << b+b << endl; // 将显示 2。
// 如果对 bool 型变量赋非 0 的值,将转换成 1。
b = 30;
cout << "b=" << b << endl; // 将显示 1。
// 找到布尔变量 b 的内存,把里面的数据强制为 8。
char* c = (char *) & b;
*c = 8;
cout << "b=" << b << endl; // 将显示 8。
}
48、数据类型的转换
计算机进行运算时,要求各操作数的类型具有相同的大小和存储方式。
在实际开发中,不同类型的数据进行混合运算是基本需求。
自动类型转换:某些类型的转换编译器可以隐式的进行,不需程序员干预。
强制类型转换:有些类型的转换需要程序员显式指定。
1)自动类型转换
不同数据类型的差别在于取值范围和精度,数据的取值范围越大,精度越高。
整型从低到高:
char -> short -> int -> long -> long long
浮点型从低到高:
float -> double -> long double
自动类型转换的规则如下:
如果一个表达式中出现了不同类型操作数的混合运算,较低类型将自动向较高类型转换。
当表达式中含有浮点型操作数时,所有操作数都将转换为浮点型。
赋值运算的右值类型与左值类型不一致时,将右值类型提升/降低为左值类型。
赋值运算右值超出了左值类型的表示范围,把该右值截断后赋给左值,所得结果可能毫无意义。
2)强制类型转换
为了让程序设计更灵活,转换的目的更清晰,C++提供了强制类型转换的方法,也称之为显式转换。
强制类型转换的语法:(目标类型)表达式或目标类型(表达式)
注意:
如果使用强制转换,表示程序员已有明确的目的。
如果转换的行为不符合理,后果由程序员承担。
如果采用了强制类型转换,编译的告警信息将不再出现。
类型转换运算符的优先级比较高,如果没把握就加括号。
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
char a = 30;
int b = 102400;
long long c = 15000000000001;
// 如果一个表达式中出现了不同类型操作数的混合运算,较低类型将自动向较高类型转换。
cout << "a+b+c=" << a + b + c << endl;
// 当表达式中含有浮点型操作数时,所有操作数都将转换为浮点型。
cout << "8/5=" << ((double)8) / 5 << endl;
// 赋值运算的右值类型与左值类型不一致时,将右值类型提升/降低为左值类型。
// 赋值运算右值超出了左值类型的表示范围,把该右值截断后赋给左值,所得结果可能毫无意义。
int d = (int)23.59; // 降低了精度。
cout << "d=" << d << endl;
unsigned int e = (unsigned int)4294967295+10; // 值被截断,从高位截断
cout << "e=" << e << endl;
// 4294967295 11111111111111111111111111111111
// 4294967296 000100000000000000000000000000000000
// 4294967297 000100000000000000000000000000000001
}
49、数据类型的别名 typedef
创建数据类型的别名有两个目的:
为名称复杂的类型创建别名,方便书写和记忆。
创建与平台无关的数据类型,提高程序的兼容性。
语法:typedef 原数据类型名 别名;
C++11 还可以用 using 关键字创建数据类型的别名。
语法:using 别名=原数据类型名;
示例:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
int main()
{
// 1)为名称复杂的类型创建别名,方便书写和记忆。
// 2)创建与平台无关的数据类型,提高程序的兼容性。
// 在 VS 中,short 是两个字节,int 是四个字节,long 也是四个字节,long long 是八个字节。
typedef short int16_t; // 16 位的整数。
typedef int int32_t; // 32 位的整数。
typedef long long int64_t; // 64 位的整数。
// 在 Linux 中,short 是两个字节,int 是四个字节,long 也是八个字节,long long 也是八个
字节。
typedef short int16_t; // 16 位的整数。
typedef int int32_t; // 32 位的整数。
typedef long int64_t; // 64 位的整数。
// 在程序源代码中,只使用别名 int16_t、int32_t、int64_t,不使用原名。
}