目录
1.9 C++ 中的左值(Lvalues)和右值(Rvalues)
一、C++ 简介:
C++是C语言的继承,是一种编译型语言,既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。
C++ 综合了高级语言和低级语言的特点被认为是一种中级语言,它是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。研制C语言的初衷是用它编写UNIX系统程序,因此,它实际上是UNIX的“副产品”。它充分结合了汇编语言和高级语言的优点,高效而灵活,又容易移植。C++ 是由 C++历史悠久,运行高效,有大量的应用场景。 1979 年Bjarne Stroustrup 在新泽西州美利山贝尔实验室开始设计开发的。C++ 进一步扩充和完善了 C 语言,最初命名为带类的C,后来在 1983 年更名为 C++。C++ 是 C 的一个超集,事实上,任何合法的 C 程序都是合法的 C++ 程序。
二、C++ 环境设置:
本地环境设置:
如果您想要设置 C++ 语言环境,您需要确保电脑上有以下两款可用的软件,文本编辑器和 C++ 编译器。
文本编译器:
这将用于输入您的程序。在开始编程之前,请确保您有一个文本编辑器,且有足够的经验来编写一个计算机程序,然后把它保存在一个文件中,编译并执行它。
C++编译器:
写在源文件中的源代码是人类可读的源。它需要"编译",转为机器语言,这样 CPU 可以按给定指令执行程序。C++ 编译器用于把源代码编译成最终的可执行程序。
MacOS操作系统可用CLION,Windows系统可用Visual studio。
三、C++基本语法:
1.C++初识
1.1 第一个C++程序:
#include <iostream>//包含头文件
using namespace std;//编译器使用 std 命名空间
int main() // main() 是程序开始执行的地方
{
cout << "Hello world! \n\n - from NH木木木." << endl;//cout输出
return 0;
}
1.2 C++ 中的分号 & 块:
在 C++ 中,分号;是语句结束符。也就是说,每个语句必须以分号结束。它表明一个逻辑实体的结束。块是一组使用大括号{}括起来的按逻辑连接的语句。C++ 不以行末作为结束符的标识,因此,您可以在一行上放置多个语句。
1.3 注释:
程序的注释是解释性语句,您可以在 C++ 代码中包含注释,这将提高源代码的可读性。所有的编程语言都允许某种形式的注释。C++ 支持单行注释和多行注释。注释中的所有字符会被 C++ 编译器忽略。在 / 和 / 注释内部,// 字符没有特殊的含义。在 // 注释内,/ 和 / 字符也没有特殊的含义。因此,可以在一种注释内嵌套另一种注释。
//单行注释
/*
多行注释
*/
1.4 C++ 标识符
C++ 标识符是用来标识变量、函数、类、模块,或任何其他用户自定义项目的名称。一个标识符以字母 A-Z 或 a-z 或下划线 _ 开始,后跟零个或多个字母、下划线和数字(0-9)。
C++ 标识符内不允许出现标点字符,比如 @、$ 和 %。C++ 是区分大小写的编程语言。因此,在 C++ 中,Manpower 和 manpower 是两个不同的标识符。
C++规定给标识符(变量、常量)命名时,有一套自己的规则
- 标识符不能是关键字
- 标识符只能由字母、数字、下划线组成
- 第一个字符必须为字母或者下划线
- 标识符中字母区分大小写
- (建议:给标识符命名的时候,争取做到见名知意,方便自己和他人阅读。)
下面列出几个有效的标识符:
mohd zara abc move_name a_123
myname50 _temp j a23b9 retVal
1.5 C++ 关键字
下表列出了 C++ 中的保留字。这些保留字不能作为常量名、变量名或其他标识符名称。
asm | else | new | this |
---|---|---|---|
auto | enum | operator | throw |
bool | explicit | private | true |
break | export | protected | try |
case | extern | public | typedef |
catch | false | register | typeid |
char | float | reinterpret_cast | typename |
class | for | return | union |
const | friend | short | unsigned |
const_cast | goto | signed | using |
continue | if | sizeof | virtual |
default | inline | static | void |
delete | int | static_cast | volatile |
do | long | struct | wchar_t |
double | mutable | switch | while |
dynamic_cast | namespace | template |
1.6 C++ 中的空格
只包含空格的行,被称为空白行,可能带有注释,C++ 编译器会完全忽略它。在 C++ 中,空格用于描述空白符、制表符、换行符和注释。空格分隔语句的各个部分,让编译器能识别语句中的某个元素(比如 int)在哪里结束,下一个元素在哪里开始。
1.7 变量
作用: 给一段指定的内存空间起名,方便操作这段内存。
语法:数据类型 变量名 = 初始值;
int a = 10;
cout << "a = "<< a << endl;
1.8 常量
作用:用于记录程序中不可更改的数据。
C++定义常量的两种方法
1.#define宏定义
#define 常量名 常量值,通常在文件上方定义,表示一个常量。
2.const修饰的变量
const 数据类型 常量名 = 常量值,通常在变量定义之前加关键字const,修饰该变量为常量,不可修改。
1.9 C++ 中的左值(Lvalues)和右值(Rvalues)
C++ 中有两种类型的表达式:
- 左值(lvalue):指向内存位置的表达式被称为左值(lvalue)表达式。左值可以出现在赋值号的左边或右边。
- 右值(rvalue):术语右值(rvalue)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。
变量是左值,因此可以出现在赋值号的左边。数值型的字面值是右值,因此不能被赋值,不能出现在赋值号的左边。
2.数据类型
使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。存储各种数据类型(比如字符型、宽字符型、整型、浮点型、双浮点型、布尔型等)的信息,操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么。
2.1 基本的内置类型
C++ 为程序员提供了种类丰富的内置数据类型和用户自定义的数据类型。下表列出了七种基本的 C++ 数据类型:
类型 | 关键字 |
---|---|
布尔型 | bool |
字符型 | char |
整型 | int |
浮点型 | float |
双浮点型 | double |
无类型 | void |
宽字符型 | wchar_t |
2.2 整型
作用:整型变量表示的是整型类型的数据。
C++中能够表示整型的类型有以下几种方式,区别在于占用的内存空间不同。
类型 | 位 | 范围 |
---|---|---|
short(短整形) | 2个字节 | -2^ 15~2^ 15-1 |
int(整型) | 4 个字节 | -2^ 31~2^ 31-1 |
long(长整型) | window中为4个字节,Linux中为4个字节(32)位或8个字节(64位) | -2^ 31~2^ 31-1 |
long long(长长整型) | 8 个字节 | -2^ 63~2^ 63-1 |
数据 输入
作用:用于从键盘获取数据
关键字:cin
语法:
cin >> 变量
sizeof关键字
作用:统计数据类型所占空间的大小。
语法:
sizeof(数据类型/变量);
示例:
#include <iostream>
using namespace std;
int main()
{
cout << "int类型所占空间的大小是:" <<sizeof(int)<< endl;
cout << "short类型所占空间的大小是:" <<sizeof(short)<< endl;
cout << "long类型所占空间的大小是:" <<sizeof(long)<< endl;
cout << "long long类型所占空间的大小是:" <<sizeof(long long)<< endl;
return 0;
}
//输出结果:
//int类型所占空间的大小是:4
//short类型所占空间的大小是:2
//long类型所占空间的大小是:8
//long long类型所占空间的大小是:8
2.3 实型(浮点型)
作用:用于表示小数。
浮点型分为两种-单精度float-双精度double。
两者的区别在于有效数字的表示范围不一样。
类型 | 位 | 范围 |
---|---|---|
float | 4 个字节 | +/- 3.4e +/- 38 (~7 位有效数字) |
double | 8 个字节 | +/- 1.7e +/- 308 (~15 位有效数字) |
float f1 = 3.14f;
//编译器会默认把一个小数当做双精度,默认情况下输出一个小数会显示出6位有效数字
//后面加f是为了告诉编译器是float型,对数值大小没有关系
2.4 字符型
字符型
作用:字符型变量用于显示单个字符。
语法:
char sb = 'a';
/*注意:显示字符型变量时用单引号括起来,不是双引号。单引号内只能有一个字符,不可以是字符串。*/
C和C++中字符型变量只占1个字节。
字符型变量并不是把所有的字符本身放到内存中存储,而是将对应的ASCII编码放入到存储单元中。
2.5 转义字符
作用:用于表示一些不能显示出来的ASCII字符。
转义字符 | 含义 |
---|---|
\a | 响铃(BEL) |
\b | 退格(BS),将当前位置移到前一格 |
\f | 换页(FF),将当前位置移到下一页开头 |
\n | 换行(LF),将当前位置移到下一行开头 |
\r | 回车(CR),将当前位置移到本行开头 |
\t | 水平制表(HT) |
\v | 垂直制表(VT) |
\' | 输出单引号 |
\" | 输出双引号 |
\\ | 输出反斜杠 |
2.6 字符串
作用:用于表示一串字符串。
两种风格:
1.C风格字符串
//要用双引号括起来
char 变量名[] = "字符串值";
char str1[] = "hello world";
2.C++风格字符串
//需要加入头文件
#include<string>
//语法 string 变量名 = "字符串值";
string s = "hello";
C++ 中有大量的函数用来操作以 null 结尾的字符串:supports a wide range of functions that manipulate null-terminated strings:
序号 | 函数 & | 目的 |
---|---|---|
1 | strcpy(s1, s2); | 复制字符串 s2 到字符串 s1。 |
2 | strcat(s1, s2); | 连接字符串 s2 到字符串 s1 的末尾。 |
3 | strlen(s1); | 返回字符串 s1 的长度。 |
4 | strcmp(s1, s2); | 如果 s1 和 s2 是相同的,则返回 0;如果 s1s2 则返回大于 0。 |
5 | strchr(s1, ch); | 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。 |
6 | strstr(s1, s2); | 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。 |
P.S.使用前包含头文件<cstring>
#include <iostream>
#include <cstring>
using namespace std;
int main ()
{
char str1[10] = "Hello";
char str2[10] = "World";
char str3[10];
int len ;
// 复制 str1 到 str3
strcpy( str3, str1);
cout << "strcpy( str3, str1) : " << str3 << endl;
// 连接 str1 和 str2
strcat( str1, str2);
cout << "strcat( str1, str2): " << str1 << endl;
// 连接后,str1 的总长度
len = strlen(str1);
cout << "strlen(str1) : " << len << endl;
return 0;
}
2.7 布尔类型
作用:布尔类型数据代表真或假的值。
bool类型只有两个值:
- true——真(1)
- false——假(0)
bool类型占1个字节大小
2.8 typedef声明
可以使用 typedef 为一个已有的类型取一个新的名字。下面是使用 typedef 定义一个新类型的语法:
typedef type newname;
//例如,下面的语句会告诉编译器,feet 是 int 的另一个名称:
typedef int feet;
//现在,下面的声明是完全合法的,它创建了一个整型变量 distance:
feet distance;
2.9 枚举类型
枚举类型声明一个可选的类型名称和一组标识符,用来作为该类型的值。其带有零个或多个标识符可以被用来作为该类型的值。每个枚举数是一个枚举类型的常数。
创建枚举,需要使用关键字 enum。枚举类型的一般形式为:
enum enum-name { list of names } var-list;
在这里,enum-name 是枚举类型的名称。名称列表 { list of names } 是用逗号分隔的。
例如,下面的代码定义了一个颜色枚举,变量 c 的类型为 color。最后,c 被赋值为 "blue"。
enum color { red, green, blue } c;
c = blue;
默认情况下,第一个名称的值为 0,第二个名称的值为 1,第三个名称的值为 2,以此类推。但是,您也可以给名称赋予一个特殊的值,只需要添加一个初始值即可。例如,在下面的枚举中,green 的值为 5。
enum color { red, green=5, blue };
在这里,blue 的值为 6,因为默认情况下,每个名称都会比它前面一个名称大 1。
3. 运算符
3.1 算术运算符
下表显示了 C++ 支持的所有算术运算符。
假设变量 A 的值为 5,变量 B 的值为 10,则:
运算符 | 描述 | 实例 |
---|---|---|
+ | 把两个操作数相加 | A + B 将得到 15 |
- | 从第一个操作数中减去第二个操作数 | A - B 将得到 -5 |
* | 把两个操作数相乘 | A * B 将得到 50 |
/ | 分子除以分母 | B / A 将得到 2 |
% | 取模运算符,整除后的余数 | B % A 将得到 0 |
++ | 自增运算符,整数值增加 1 | A++ 将得到 6 |
-- | 自减运算符,整数值减少 1 | A-- 将得到 4 |
3.2 关系运算符
下表显示了 C++ 支持的所有关系运算符。
假设变量 A 的值为 5,变量 B 的值为 10,则:
运算符 | 描述 | 实例 |
---|---|---|
== | 检查两个操作数的值是否相等,如果相等则条件为真。 | (A == B) 不为真。 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真。 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 | (A > B) 不为真。 |
< | 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 | (A < B) 为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 | (A >= B) 不为真。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 | (A <= B) 为真。 |
3.3 逻辑运算符
下表显示了 C++ 支持的所有关系逻辑运算符。
假设变量 A 的值为 1,变量 B 的值为 0,则:
运算符 | 描述 | 实例 |
---|---|---|
&& | 称为逻辑与运算符。如果两个操作数都非零,则条件为真。 | (A && B) 为假。 |
丨丨 | 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。 | (A 丨丨 B) 为真。 |
! | 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。 | !(A && B) 为真。 |
3.4 位运算符
位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:
p | q | p & q | p 丨 q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
假设如果 A = 60,且 B = 13,现在以二进制格式表示,它们如下所示:
A = 0011 1100
B = 0000 1101
-----------------
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011
下表显示了 C++ 支持的位运算符。假设变量 A 的值为 60,变量 B 的值为 13,则:
运算符 | 描述 | 实例 |
---|---|---|
& | 如果同时存在于两个操作数中,二进制 AND 运算符复制一位到结果中。 | (A & B) 将得到 12,即为 0000 1100 |
丨 | 如果存在于任一操作数中,二进制 OR 运算符复制一位到结果中。 | (A 丨 B) 将得到 61,即为 0011 1101 |
^ | 如果存在于其中一个操作数中但不同时存在于两个操作数中,二进制异或运算符复制一位到结果中。 | (A ^ B) 将得到 49,即为 0011 0001 |
~ | 二进制补码运算符是一元运算符,具有"翻转"位效果。 | (~A ) 将得到 -61,即为 1100 0011,2 的补码形式,带符号的二进制数。 |
<< | 二进制左移运算符。左操作数的值向左移动右操作数指定的位数。 | A << 2 将得到 240,即为 1111 0000 |
>> | 二进制右移运算符。左操作数的值向右移动右操作数指定的位数。 | A >> 2 将得到 15,即为 0000 1111 |
实例:
#include <iostream>
using namespace std;
int main()
{
int a = 60; // 60 = 0011 1100
int b = 13; // 13 = 0000 1101
int c = 0;
c = a & b; // 12 = 0000 1100
cout << " 1 - c 的值是 " << c << endl ;
c = a | b; // 61 = 0011 1101
cout << " 2 - c 的值是 " << c << endl ;
c = a ^ b; // 49 = 0011 0001
cout << " 3 - c 的值是 " << c << endl ;
c = ~a; // -61 = 1100 0011
cout << " 4 - c 的值是 " << c << endl ;
c = a << 2; // 240 = 1111 0000
cout << " 5 - c 的值是 " << c << endl ;
c = a >> 2; // 15 = 0000 1111
cout << " 6 - c 的值是 " << c << endl ;
return 0;
}
/*输出结果
1 - c 的值是 12
2 - c 的值是 61
3 - c 的值是 49
4 - c 的值是 -61
5 - c 的值是 240
6 - c 的值是 15*/
3.5 赋值运算符
下表列出了 C++ 支持的赋值运算符:
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符,把右边操作数的值赋给左边操作数 | 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 |
<<= | 左移且赋值运算符 | C <<= 2 等同于 C = C << 2 |
>>= | 右移且赋值运算符 | C >>= 2 等同于 C = C >> 2 |
&= | 按位与且赋值运算符 | C &= 2 等同于 C = C & 2 |
^= | 按位异或且赋值运算符 | C ^= 2 等同于 C = C ^ 2 |
丨= | 按位或且赋值运算符 | C 丨= 2 等同于 C = C 丨2 |
3.6 杂项运算符
下表列出了 C++ 支持的其他一些重要的运算符。
运算符 | 描述 |
---|---|
sizeof | sizeof 运算符返回变量的大小。例如,sizeof(a) 将返回 4,其中 a 是整数。 |
Condition ? X : Y | 条件运算符。如果 Condition 为真 ? 则值为 X : 否则值为 Y。 |
, | 逗号运算符会顺序执行一系列运算。整个逗号表达式的值是以逗号分隔的列表中的最后一个表达式的值。 |
.(点)和 ->(箭头) | 成员运算符用于引用类、结构和共用体的成员。 |
Cast | 强制转换运算符把一种数据类型转换为另一种数据类型。例如,int(2.2000) 将返回 2。 |
& | 指针运算符 & 返回变量的地址。例如 &a; 将给出变量的实际地址。 |
* | 指针运算符 指向一个变量。例如,var; 将指向变量 var。 |
3.7 C++ 中的运算符优先级
运算符的优先级确定表达式中项的组合。这会影响到一个表达式如何计算。某些运算符比其他运算符有更高的优先级,例如,乘除运算符具有比加减运算符更高的优先级。
下表将按运算符优先级从高到低列出各个运算符,具有较高优先级的运算符出现在表格的上面,具有较低优先级的运算符出现在表格的下面。在表达式中,较高优先级的运算符会优先被计算。
类别 | 运算符 | 结合性 |
---|---|---|
后缀 | () [] -> . ++ - - | 从左到右 |
一元 | + - ! ~ ++ - - (type) * & sizeof | 从右到左 |
乘除 | * / % | 从左到右 |
加减 | + - | 从左到右 |
移位 | << >> | 从左到右 |
关系 | < <= > >= | 从左到右 |
相等 | == != | 从左到右 |
位与 | AND & | 从左到右 |
位异或 | XOR ^ | 从左到右 |
位或 | OR 丨 | 从左到右 |
逻辑与 | AND && | 从左到右 |
逻辑或 OR | 丨丨 | 从左到右 |
条件 | ?: | 从右到左 |
赋值 | = += -= *= /= %= >>= <<= &= ^= 丨= | 从右到左 |
逗号 | , | 从左到右 |
4. 选择结构
选择结构要求程序员指定一个或多个要评估或测试的条件,以及条件为真时要执行的语句(必需的)和条件为假时要执行的语句(可选的)。
下面是大多数编程语言中典型的判断结构的一般形式:
4.1 条件语句
C++ 编程语言提供了以下类型的判断语句。点击链接查看每个语句的细节。
语句 | 描述 |
---|---|
单行if 语句 | 一个 if 语句 由一个布尔表达式后跟一个或多个语句组成。 |
if...else 语句 | 一个 if 语句 后可跟一个可选的 else 语句,else 语句在布尔表达式为假时执行。 |
嵌套 if 语句 | 您可以在一个 if 或 else if 语句内使用另一个 if 或 else if 语句。 |
switch 语句 | 一个 switch 语句允许测试一个变量等于多个值时的情况。 |
嵌套 switch 语句 | 您可以在一个 switch 语句内使用另一个 switch 语句。 |
4.2 if语句
作用:执行满足条件的语句。
4.2.1 单行格式if语句
if(条件){ /*条件满足执行的语句*/ }
4.2.2 if...else 格式语句
if(条件)
{
//条件满足执行的语句
}
else
{
//条件不满足执行的语句
}
4.2.3 嵌套if格式语句
1.
if(条件1)
{
//条件1满足执行的语句
}
else if(条件2)
{
//条件2满足执行的语句
}
......
else
{
//都不满足执行的语句
}
2.
if()
{
if()
}
else
{
}
4.3 switch语句
作用:执行多条件分支语句
语法:
switch(表达式)
{
case 结果1:执行语句;break;//每个结果后都要有break,否则就会顺序执行在一个case
case 结果2:执行语句;break;
case 结果3:执行语句;break;
...
default:执行语句; break;
}
4.4 三目运算符
可以用来替代 if...else 语句。它的一般形式如下:
Exp1 ? Exp2 : Exp3;
其中,Exp1、Exp2 和 Exp3 是表达式。请注意,冒号的使用和位置。
?表达式的值是由 Exp1 决定的。如果 Exp1 为真,则计算 Exp2 的值,结果即为整个表达式的值。如果 Exp1 为假,则计算 Exp3 的值,结果即为整个表达式的值。
5.循环结构
5.1 C++ 循环
有的时候,可能需要多次执行同一块代码。一般情况下,语句是顺序执行的:函数中的第一个语句先执行,接着是第二个语句,依此类推。编程语言提供了允许更为复杂的执行路径的多种控制结构。
循环语句允许我们多次执行一个语句或语句组,下面是大多数编程语言中循环语句的一般形式:
5.2 循环类型
循环类型 | 描述 |
---|---|
while 循环 | 当给定条件为真时,重复语句或语句组。它会在执行循环主体之前测试条件。 |
for 循环 | 多次执行一个语句序列,简化管理循环变量的代码。 |
do...while 循环 | 除了它是在循环主体结尾测试条件外,其他与 while 语句类似。 |
嵌套循环 | 可以在 while、for 或 do..while 循环内使用一个或多个循环。 |
5.2.1 while循环语句
作用:满足循环条件,执行循环语句
语法:
while(循环条件){ 循环语句 }
//只要循环为真,则一直循环
5.2.2 for循环语句
作用:满足循环条件,执行循环语句
语法:
for(起始条件;条件表达式;末尾循环体)
{
循环语句
}
5.2.3 do-while循环语句
作用:满足循环条件,执行循环语句。
语法:
do{
循环语句
}while(循环条件)
//与while的区别在于do-while会先执行一次循环语句,再判断循环条件。
5.2.4 嵌套循环
作用:在循环体中再嵌套一层循环,解决一些实际问题。
初学者常用嵌套for循环,下面是利用嵌套for循环的冒泡排序:
#include<iostream>
using namespace std;
int main(void)
{
//冒泡排序的总轮数=元素个数-1
//每轮对比的次数 = 元素个数- 排序轮数
int nums[9] = {5,8,2,7,9,3,6,4,1};
int len=9
for (int i = 0; i < len ; i++)
{
//内层循环对比
for (int j = 0; j < len - i-1; j++)
{
//第一个数比第二个数大就交换他们两个的位置
int temp = 0;
if (nums[j] > nums[j + 1])
{
temp = nums[j+1];
nums[j + 1] = nums[j];
nums[j] = temp;
}
}
}
for (int i = 0; i < 9; i++)
{
cout << nums[i];
}
return 0;
}
5.3 循环控制语句
循环控制语句更改执行的正常序列。当执行离开一个范围时,所有在该范围中创建的自动对象都会被销毁。
控制语句 | 描述 |
---|---|
break 语句 | 终止 loop 或 switch 语句,程序流将继续执行紧接着 loop 或 switch 的下一条语句。 |
continue 语句 | 引起循环跳过主体的剩余部分,立即重新开始测试条件。 |
goto 语句 | 将控制转移到被标记的语句。但是不建议在程序中使用 goto 语句。 |
5.3.1 break语句
作用:用于跳出选择结构或者循环结构。
break使用的时机:
- 出现在switch语句中,作用是终止case并跳出swtich
- 出现在循环语句中,作用是跳出当前的循环语句
- 出现在嵌套语句中,跳出最近的内层循环语句
5.3.2 continue语句
作用:在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环。
5.3.3 goto语句
作用:可以无条件跳转语句
语法:goto标记;
解释:设置一个标志,执行到goto语句的时候,会跳转到标志的位置。
goto flag;...
flag:...
5.4无限循环
如果条件永远不为假,则循环将变成无限循环。for 循环在传统意义上可用于实现无限循环。由于构成循环的三个表达式中任何一个都不是必需的,您可以将某些条件表达式留空来构成一个无限循环。
#include <iostream>
using namespace std;
int main ()
{
for( ; ; )
{
cout<<a<<endl;
}
return 0;
}
//while或者do...while循环可使循环条件为1,则可无限循环
当条件表达式不存在时,它被假设为真。您也可以设置一个初始值和增量表达式,但是一般情况下,C++ 程序员偏向于使用 for(;;) 结构来表示一个无限循环。
注意:您可以按 Ctrl + C 键终止一个无限循环。
6. 数字
通常,当我们需要用到数字时,我们会使用原始的数据类型,如 int、short、long、float 和 double 等等。
6.1 C++ 定义数字
下面是一个 C++ 中定义各种类型数字的综合实例:
#include <iostream>
using namespace std;
int main () {
// 数字定义
short s;
int i;
long l;
float f;
double d;
// 数字赋值
s = 10;
i = 1000;
l = 1000000;
f = 230.47;
d = 30949.374;
// 数字输出
cout << "short s :" << s << endl;
cout << "int i :" << i << endl;
cout << "long l :" << l << endl;
cout << "float f :" << f << endl;
cout << "double d :" << d << endl;
return 0;
}
6.2 数学运算
在 C++ 中,除了可以创建各种函数,还包含了各种有用的函数供您使用。这些函数写在标准 C 和 C++ 库中,叫做内置函数。您可以在程序中引用这些函数。
C++ 内置了丰富的数学函数,可对各种数字进行运算。下表列出了 C++ 中一些有用的内置的数学函数。利用这些函数,需要包含引用数学头文件 <cmath>。
序号 | 函数 & | 描述 |
---|---|---|
1 | double cos(double); | 该函数返回弧度角(double 型)的余弦。 |
2 | double sin(double); | 该函数返回弧度角(double 型)的正弦。 |
3 | double tan(double); | 该函数返回弧度角(double 型)的正切。 |
4 | double log(double); | 该函数返回参数的自然对数。 |
5 | double pow(double, double); | 假设第一个参数为 x,第二个参数为 y,则该函数返回 x 的 y 次方。 |
6 | double hypot(double, double); | 该函数返回两个参数的平方总和的平方根,也就是说,参数为一个直角三角形的两个直角边,函数会返回斜边的长度。 |
7 | double sqrt(double); | 该函数返回参数的平方根。 |
8 | int abs(int); | 该函数返回整数的绝对值。 |
9 | double fabs(double); | 该函数返回任意一个十进制数的绝对值。 |
10 | double floor(double); | 该函数返回一个小于或等于传入参数的最大整数。 |
下面是一个关于数学运算的简单实例:
#include <iostream>
#include <cmath>
using namespace std;
int main () {
// 数字定义
short s = 10;
int i = -1000;
long l = 100000;
float f = 230.47;
double d = 200.374;
// 数学运算
cout << "sin(d) :" << sin(d) << endl;
cout << "abs(i) :" << abs(i) << endl;
cout << "floor(d) :" << floor(d) << endl;
cout << "sqrt(f) :" << sqrt(f) << endl;
cout << "pow( d, 2) :" << pow(d, 2) << endl;
return 0;
}
6.3 随机数
在许多情况下,需要生成随机数。关于随机数生成器,有两个相关的函数。一个是 rand(),该函数只返回一个伪随机数。生成随机数之前必须先调用 srand() 函数。
下面是一个关于生成随机数的简单实例。实例中使用了 time() 函数来获取系统时间的秒数,通过调用 rand() 函数来生成随机数:
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main () {
int i,j;
// 设置种子
srand( (unsigned)time( NULL ) );
/* 生成 10 个随机数 */
for( i = 0; i < 10; i++ )
{
// 生成实际的随机数
j= rand();
cout <<"随机数: " << j << endl;
}
return 0;
}
7. 数组
7.1 概述:
C++ 支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。数组的声明并不是声明一个个单独的变量,所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。
7.2 一维数组
数据类型 数组名[数组长度];
数据类型 数组名[数组长度] = {值1,值2......};
数据类型 数组名[] = {值1,值2......};;
7.2.2数组名的用途
1.可以统计整个数组在内存中的长度
sizeof(array)/sizeof(array[0]) -1
2.可以获取数组在内存中的首地址
int arr[] = {1,2,3,4};
int* p = arr;
//数组名是一个指针常量,其只能指向数组的首个元素所在地址。
7.3 二维数组
二维数组就是在一维数组的基础上多加一个维度,就是在一维数组里面存储一维数组。
7.3.1 定义:
数据类型 数组名[行][列];
数据类型 数组名[行][列] = {{数据1,数据2},{数据3,数据4}};
数据类型 数组名[行][列] = {数据1,数据2,数据3,数据4};
数据类型 数组名[][列] = {数据1,数据2,数据3,数据4};
建议:以上4种定义方式,利用第二种更加直观,提高代码的可读性。
- 查看二维数组所占内存空间
- 获取二维数组首地址
7.4 数组详解
在 C++ 中,数组是非常重要的,我们需要了解更多有关数组的细节。
下面列出了 C++ 程序员必须清楚的一些与数组相关的重要概念:
概念 | 描述 |
---|---|
多维数组 | C++ 支持多维数组。多维数组最简单的形式是二维数组。 |
指向数组的指针 | 您可以通过指定不带索引的数组名称来生成一个指向数组中第一个元素的指针。 |
传递数组给函数 | 您可以通过指定不带索引的数组名称来给函数传递一个指向数组的指针。 |
从函数返回数组 | C++ 允许从函数返回数组。 |
8. 函数
8.1函数概述:
函数是一组一起执行一个任务的语句。每个 C++ 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。
您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的,但在逻辑上,划分通常是根据每个函数执行一个特定的任务来进行的。
函数声明告诉编译器函数的名称、返回类型和参数。函数定义提供了函数的实际主体。
C++ 标准库提供了大量的程序可以调用的内置函数。例如,函数 strcat() 用来连接两个字符串,函数 memcpy() 用来复制内存到另一个位置。函数还有很多叫法,比如方法、子例程或程序,等等。
函数的常见样式:
无参无返、有参无返、无参有返、有参有返
8.2 定义函数
C++ 中的函数定义的一般形式如下:
return_type function_name( parameter list )
{
body of the function
}
返回值类型 函数名(参数列表)
{
函数语句;
return 表达式;
}
在 C++ 中,函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分:
- 返回类型:一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void。
- 函数名称:这是函数的实际名称。函数名和参数列表一起构成了函数签名。
- 参数:参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
- 函数主体:函数主体包含一组定义函数执行任务的语句。
8.3 函数声明
函数声明会告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
函数声明包括以下几个部分:
return_type function_name( parameter list );
针对上面定义的函数 max(),以下是函数声明:
int max(int num1, int num2);
在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此下面也是有效的声明:
int max(int, int);
当在一个源文件中定义函数且在另一个文件中调用函数时,函数声明是必需的。在这种情况下,您应该在调用函数的文件顶部声明函数。
8.4 调用函数
创建 C++ 函数时,会定义函数做什么,然后通过调用函数来完成已定义的任务。
当程序调用函数时,程序控制权会转移给被调用的函数。被调用的函数执行已定义的任务,当函数的返回语句被执行时,或到达函数的结束括号时,会把程序控制权交还给主程序。
调用函数时,传递所需参数,如果函数返回一个值,则可以存储返回值。
功能:使用定义好的函数
语法: 函数名(参数)
8.5 函数参数
如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。
形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。
当调用函数时,有两种向函数传递参数的方式:
调用类型 | 描述 |
---|---|
传值调用 | 该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。 |
指针调用 | 该方法把参数的地址复制给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
引用调用 | 该方法把参数的引用复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
默认情况下,C++ 使用传值调用来传递参数。一般来说,这意味着函数内的代码不能改变用于调用函数的参数。之前提到的实例,调用 max() 函数时,使用了相同的方法。
8.6 参数的默认值
当您定义一个函数,您可以为参数列表中后边的每一个参数指定默认值。当调用函数时,如果实际参数的值留空,则使用这个默认值。
这是通过在函数定义中使用赋值运算符来为参数赋值的。调用函数时,如果未传递参数的值,则会使用默认值,如果指定了值,则会忽略默认值,使用传递的值。
8.6.1 函数的分文件编写
作用:让代码结构更加清晰
1.在头文件创建后缀为.h的头文件。
2.在源文件创建后缀名为.cpp的源文件。
3.在头文件中写函数的声明。
#include <iostream>
using namespace std;
//函数的声明
void 函数名(参数列表);
4.在源文件中写函数的定义。
#include “.h”
返回值类型 函数名(参数列表)
{
函数语句;
return 表达式;
}
9. 指针
学习 C++ 的指针既简单又有趣。通过指针,可以简化一些 C++ 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的。所以,想要成为一名优秀的 C++ 程序员,学习指针是很有必要的。每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符(又叫取址符)访问的地址,它表示了在内存中的一个地址。
9.1 什么是指针?
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:
type *var-name;
在这里,type 是指针的基类型,它必须是一个有效的 C++ 数据类型,var-name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针。以下是有效的指针声明:
int *ip; /* 一个整型的指针 */
double *dp; /* 一个 double 型的指针 */
float *fp; /* 一个浮点型的指针 */
char *ch /* 一个字符型的指针 */
所有指针的值的实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,都是一样的,都是一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同。
9.2 指针所占内存空间
在32位操作系统下无论是什么类型的指针,都占4个字节的内存空间。
9.3 空指针
空指针:指针变量指向内存中编号为0的空间
用途:初始化指针变量
注意:空指针指向的内存空间是不可以访问的
int* p = NULL;
9.4 野指针
指针变量指向非法的内存空间。
9.5 const修饰指针
const修饰指针有3种情况
const修饰指针—常量指针
const修饰常量—指针常量
const既修饰指针,又修饰常量、
//const修饰的是指针,指针指向可以改,指针指向的值不可以改
const int* p1 = &a;
//const修饰的是常量,指针指向不可以改,指针指向的值可以更改
int* const p2 = &a;
//const既修饰指针,又修饰常量,指针的指向和指针指向的值都不可以改变
const int* const p = &a;
9.6 指针和数组
作用:利用指针访问数组元素
int arr[] = {1,2,3,4};
int* p = arr;
9.7 指针和函数
作用:利用指针作函数的参数,可以修改实参的值。
9.8 C++ 指针详解
概念 | 描述 |
---|---|
C++ Null | 指针 C++ 支持空指针。NULL 指针是一个定义在标准库中的值为零的常量。 |
C++ 指针的算术运算 | 可以对指针进行四种算术运算:++、--、+、- |
C++ 指针 vs 数组 | 指针和数组之间有着密切的关系。 |
C++ 指针数组 | 可以定义用来存储指针的数组。 |
C++ 指向指针的指针 | C++ 允许指向指针的指针。 |
C++ 传递指针给函数 | 通过引用或地址传递参数,使传递的参数在调用函数中被改变。 |
C++ 从函数返回指针 | C++ 允许函数返回指针到局部变量、静态变量和动态内存分配。 |
10. 结构体
C/C++ 数组允许定义可存储相同类型数据项的变量,但是结构体是 C++ 中另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项。
10.1 定义结构体
为了定义结构体,您必须使用 struct 语句。struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下:
struct 结构体名称
{ 结构体成员列表:
member definition;
member definition;
...
member definition;
}结构体变量;
/*
通过结构体创建变量的方式有三种
1.struct 结构体名 变量名
2.struct 结构体名 变量名 = (成员1值,成员2值…)
3.定义结构体时顺便创建变量
*/
每个 member definition 是标准的变量定义,比如 int i; 或者 float f; 或者其他有效的变量定义。在结构体定义的末尾,最后一个分号之前,您可以指定一个或多个结构体变量,这是可选的。
10.2 访问结构体成员
为了访问结构体的成员,我们使用成员访问运算符(.)。成员访问运算符是结构体变量名称和我们要访问的结构体成员之间的一个句号。
10.3 结构体数组
作用:将自定义的结构头放入到数组中方便维护
语法:
struct 结构体名 数组名[元素个数]= {{},{}...{}};
10.4 结构体指针
作用:通过指针访问结构体中的成员
您可以定义指向结构的指针,方式与定义指向其他类型变量的指针相似,如下所示:
struct Books *struct_pointer;
现在,您可以在上述定义的指针变量中存储结构变量的地址。为了查找结构变量的地址,请把 & 运算符放在结构名称的前面,如下所示:
struct_pointer = &Book1;
为了使用指向该结构的指针访问结构的成员,您必须使用 -> 运算符,如下所示:
struct_pointer->title;
10.5 结构体嵌套结构体
作用:结构体中的成员可以是另一个结构体,结构体是用户自定义的一个数据类型,因此可以作为结构体的一个成员变量。
10.6 结构体做函数参数
作用:将结构体作为参数向函数中传递,把结构体作为函数参数,传参方式与其他类型的变量或指针类似。
注:就是总结下知识点,方便以后查看学习。仅供学习和参考,难免会有错误,如有侵权希望告知。