- 大概林林总总用了一周多的时间看完了MOOC上北大的“程序设计与算法(一)”,但是刷OJ中的初步认识编程1.5章时,经常出现wrong
answer却有9分的情况,估摸着是因为很多基础知识都不太牢固,故开启期中复习模式。
(另:multimap、map;multiset、set;指针这部分的视频看的有些一知半解,后续做期末复习时再学习。)
以下全部内容均总结自《新标准C++程序设计教程》(郭炜 著)中的第一篇:结构化程序设计(共四篇)。
- C++的特点:支持面向对象程序设计(有封装、继承、多态性,易于维护)
- 支持泛型函数程序设计(参数多态化?→STL标准模板库)
第一章 计算机基础知识(进制,程序设计语言)
1.1 计算机电路由一个个开关组成,因此用0、1表示和存储各类信息。
比特b(bit):计算机用来存储信息最小单位,一个开关,代表一个0 or 1;
字节B(byte):8个bit等于一个字节,1024字节等于1KB。
ASCⅡ码:一个字节代表一个数字或字母。
进制:二转十六:1111 (15)→ 0xF(15),四个二进制数 == 一个十六进制数。
- 已知一个整数N,和进制K:
N = A0K0+A1*K1+……AnK^n = A0+K(A1+K(A2+……K(An)))
计算机有32位和64位的,32位的计算机跑不动64位的程序(除非程序员做功)
32位计算机,每个整数用32个bit表达和存储。
64位计算机,每个整数用64个bit表达和存储。
(为什么我的电脑带的动32位剑灵,却带不动64位的?或许这就是原因?)
- 整数的计算机表示:负数具有符号位(首位0为正,1为负),负数采用-原数绝对值取反(0变1,1变0)再加1。(unsigned T)
- 为什么16位的整数范围是:-32768~32767? -32768 = 1000 0000 0000 0000(绝对值)→ 0111
1111 1111 1111(取反) → 1000 0000 0000 0000(+1) 我以为绝对值的符号位也不能放数字!! - 小数的计算机表示:定点数(规定好整数和小数部分的位数)
浮点数(阶符、指数/阶码、尾符、尾数)
1.2 计算机程序设计语言
- 机器语言:传说中的打孔编程。
- 汇编语言: 用“助记符”代替难记的机器指令操作代码(寄存器?)。
- 高级语言:接近自然语言的编程语言(借助编译器将高级语言转换为机器指令)
疑问思考题:
- 如何用bit来表示和存储视频和声音?
2.小数如何转换二进制?
0.8125:→ 0.1101(0,12,8疯狂乘2,取整数位的1 or 0)
第二章 C++语言基本要素(变量、常量、运算符)
2.1 C++的标识符:A_number_of_students ,用下划线连接,不能以数字开头。
- 编译器内部的标识符一般以双下划线开头,命名时请规避。
2.2 C++的关键字:
- auto break case char const continue default do double else enum extern float for goto if int long register return short signed unsigned sizeof static struct switch typedef union void volatile while
此外还有C++独有关键字,我就不抄了,反正还没用到,用到再说
2.3 最简单的C++程序
// 听说C++并不遵循严格的缩进(such as python)
#include <iostream>
using namespace std;
int main()
{
int a, b;
cout<< “hhh = ”<< “23333” <<endl;
cin>> a >> b; // << 中间不能加空格,用cin可同时输入类型不同的变量。
return 0;
}
2.4 变量(类型名 变量名1,变量名2,……变量名n)
- 变量在定义时,可给它指定初始值,比如int sum = 0;不然它就是一个不确定的数。
- 不允许将同名的变量定义两次及以上:
→ int a; double a; //导致变量重复定义的错误 - 常变量:const int a = 5;
常变量的值只能用初始化的方式给出,以后不能被修改,不能赋值。
2.5 C++的数据类型与存储空间(列出常用的)
- 4字节: (undersigned ) int long;float(-3.4*10-38~3.4*1038)
- 2字节: (undersigned ) short
8字节: (undersigned )long
long;double(-1.7*10-308~1.7*10308)
1字节: (undersigned )char;bool(表真假)
(1)char类型的变量表示一个字符,字符型变量存放的是字符的ASCⅡ码。
char c = ‘a’; (a为61 → 01100001)
(2)数据类型自动转换:当等号两边变量类型不同时,如T1=T2,编译器会将T2类型自动转换为T1,自动类型转换不会改变赋值符号右边的变量。比如:
- char c = ‘a’; int n;
n = c; // n = 97 - double d1 = 2.33333; int n1;
n1 = d1; // n1 = 2
数据转换会造成信息丢失,如int变short。
2.6 常量
- 整型常量:十六进制整型常量:“0x”。
若要表示比32位整形常量更大的数,用long long n = 0xfffffff9LL; - 实数型常量
3.14e2; -23.078e-12(e可大写,E) - 布尔型常量:true false
- 字符型常量(用单引号 ’’ 括起来)
1. ‘a’、 ‘A’、 ‘8’、 ‘ ’(空格)。
2. 转义字符也为字符常量:
\n换行,输出位置移到下一行开头;
\r回车,输出位置移到本行开头;(后输入的覆盖先输入的)
\t制表符,输出位置跳到下一个制表位置;
\b退格;(覆盖)
\,输出斜杠\;
\’,输出单引号’;
\0,空字符;
\一个数字,八进制;\x一个数字,十六进制。 - 字符串常量(”1234567890”,它是一个字符串)
- 符号常量:用一个由字母和数字组成的符号来代表某个常量。
#define MAX_NUM 1000
以后所有的MAX_NUM都等于1000。
虽然符号常量好,但是C++中更应尽可能使用常变量const。
2.7 运算符和表达式
- 算术运算符:+,-,*,/,%,++(自增),–(自减)。
如若数字过分的长,有500位十进制,那么只能用数组存放数据。
若 int a = 10, b = 3; double d;
d = a/b; →3
d =(double) a/b; →3.33333 - 模运算符%:只能用于两个整数类型,双目运算符
- 自增、自减运算符
均为单目运算符,++i和i++不同,前置++运算速度大于后置++。比如:
int n1, n2=5;
n1 = n2++;
cout<<n1<<”,”<<n2 // 5,6
n1 = ++n2;
cout<<n1<<”,”<<n2 // 7,7 - 赋值运算符:=,+=,-=,*=,/=,%=,&=,|=,^=,>>=,<<=
可以:a = b = 5;不可(a = b) = 5,此时a=5,b=1(我这边是1)。
多个“=”连用时,计算顺序从右到左
a += b,等价于:a = a+b,但是前者计算速度快 - 关系运算符:>,<,==,!=,>=,<=。其输出true 或false(0 or 1)
- 逻辑运算符:&&且,||或,!非。逻辑表达式从左往右计算,在整个表达式的值 已经能够断定时,即停止,提高程序的执行效率(遇0值问题)
!0值为真, !5值为假。 - 位运算符(&,|,^,~,<<,>>):对某个数字二进制位进行操作
具体def见自己草稿本,不抄了
——使用按位异或^,进行加密和解密。
——左移右移运算符,快速乘除2的n次方。有符号数右移时,高位补符号位,
无符号数就补0
int a = 23333; cout << hex << a << dec;
cout和hex连用可输出无符号十六进制数,dec恢复十进制 - 条件运算符:表达式1 ? 表达式2 :表达式3;
含义:如果表达式1的值为true,则计算表达式2,并返回表达式2的值
如果1的值为false,则计算3,返回3 - sizeof运算符:求某一变量或某一数据类型变量占用内存的字节数。
sizeof(变量名); sizeof(类型名)。 - 强制类型转换运算符:(int)a 或 int(a)
- 逗号运算符:表达式1, 表达式2…, 表达式n。从左到右计算
- 运算符优先级:从前往后依次为
::
后置+±- () [] . ->
前置+±- ±(正负号) ! ~ 取指针*,取地址&
乘除取模
加减
左移右移
> < >= <= 之后 == != ……balabala
&& 之后是 || 之后? 之后= +=一类,最后是逗号运算符
2.8 注释://, /* */, 注释很重要,代码可读性
思考题
- 在字符串中输入双引号:\” \”
第三章 C++语言的控制结构(if, for, while, switch … )
- 选择结构,顺序执行结构,循环结构
3.1 用if语句实现选择结构
可以只写一个if,else必须放在最后。
当不正确的加{}时,else和离它最近的if相配对。
不要搞出if(a = 5),应写a==5来进行判断,不然会给a赋值
3.2用switch语句实现选择结构
switch(表达式){
case 常量表达式1:
语句组
break;
case 2 3 4 5……n
……
default
语句组n+1
}
switch中的case可以不加{},且最后也可以不包含default。
但是要牢记写break,不然可能会连续执行多个case,导致程序运行不正确。
3.3 用for语句实现循环结构
for(表达式1; 表达式2; 表达式3){
语句组
}
其中,表达式1和表达式3都可以是用逗号连接的若干个表达式。例如:
for(int i = 15, j = 0; i>j ; i-=2, j+=3)
cout<<i<<”,”<<j<<endl;
当一个for循环中包含另一个for循环时,就是二重循环。分别为外重循环和内重循环。
for( ; ; ;)这样子的就是死循环,但是我不知道该如何跳出,书中说后文会讲如何用break跳出来。
3.4 用while语句实现循环结构
当while(表达式)中的“表达式”值为真时,才会执行循环里面的语句组。
下面是一个死循环:
while(true){
语句组
}
牛顿迭代法:x = (xn+a/xn) /2 设定一个EPS=1e -7
- cout只能输出六位有效数字
3.5 用do…while语句实现循环结构
do{
语句组
}while(表达式);
使循环至少循环一次
3.6 用break语句跳出循环
适当时机跳出循环,可以避免无意义的计算,加快程序执行程度(但是我想不到)
3.7 continue语句
使用continue,立即结束本次循环,并回到循环开头判断是否要进行下一次循环。
3.8 goto语句
使用goto,无条件跳转到某个指定位置(句子标号),接着程序从位置标号后执行。
但是,使用goto语句会使程序可读性变差。
3.9 用freopen方便程序调试
freopen(“文件路径”, ”r”, stdin);
如:c:\tmp\test.txt \要写两次。 r:read,w:write
使用freopen进行程序调试
第四章 函数(功能模块—反复使用)
- 使用“函数(function)”,将实现了某一功能并需要反复使用的代码包装起来形成一个功能模块,之后在后续对该函数进行反复调用。
例如:编写一个复杂程序,可先将大问题分解成若干个小问题……其最小的问题便可用一个函数来解决。
4.1 函数的定义和调用
- 返回值类型 函数名(参数1类型 参数1名称,2类型 2名称,……){
语句组
}
好的函数名,应当做到能让人看到名字,就明白其功能大致是什么。
(后面是“参数表”和“函数体”)- 当函数返回值类型为void时,函数返回值写“return;”。遇见return语句时,函数会立即返回。
- 形参:函数中定义的参数
实参:调用函数时使用的参数。实参的个数和类型应与形参一一对应。
4.2 函数的声明:可以不写函数体,只写函数名称,从后在后续进行函数的调用。(因为多个文件需要调用同一个函数,因此在一个文件中编写函数定义,其他文件只写函数名称)
4.3 main函数
C++程序都是从main函数开始执行的。同样的,遇到return就结束。return 0表示程序正常执行结束,返回非零则表示发生异常(或其他含义)
4.4 函数参数的默认值
声明一个函数时,可以为函数的参数指定默认值。当调用有默认值参数值的函数时,可以不写参数。调用函数时,只能最右边的连续若干个参数默认
比如:Function(int x, int y = 2){……}
以后引用时,可以写:Function(2, ), 也可以写:Function(2,233 ),此时y=233
实参的好处如下:以后调用函数时,可以默认很多数为某一值,以后需要改啥就改啥。
4.5 引用和函数参数的传递
- 引用的概念
类型名&引用名 = 同类型的某变量名
int n;
int &r = n;
此种写法定义了一个某种类型的引用,并将其初始化为引用某个同类型的变量。
注意:定义引用时一定要将其初始化,否则便已无法通过。引用只能引用变量。
两个引用之间可以互相初始化。T &的引用和T的变量之间可以互相赋值。 - 引用作为函数的返回值:
int n = 4;
int &SetValue()
{
return n;
} - 参数传值:函数的形参是实参的一个拷贝,形参的改变不会影响到实参
void Swap(int a, int b){……} - 参数传引用:形参是对应实参的引用,形参的改变会影响到实参
void Swap(int &a, int &b){……} - 常引用:const int &a
常引用和普通引用之间不能互相引用,除非强制转换。
不能通过常引用修改其引用的内容。以后a貌似都改不了了
4.6 内联函数(最好不要内联循环?)
调用函数需要花费额外时间。当一个函数被成千上万次被调用时,会使程序明显变慢。
(你在这里等着,爸爸给你买个橘子。爸爸再去给你买个橘子 →路程往返时间长)
因此,在定义函数时,在返回值类型前面加上inline,使函数在被调用处像重写了一遍。
(使用内联函数比使用普通函数会使可执行程序的体积增加。达到:以空间换时间)
注意:调用内联函数时,不能只有函数声明,还必须有函数体。
4.7 函数的重载
重载:C++不允许变量重名,但允许多个函数取相同的名字,只要参数表不同即可
有时会引发二义性,需要注意一下
4.8 库函数和头文件
C++语言标准中,规定了完成某些常用的特定功能的一些函数,编译器会提供这些函数。
#include
第五章 数组(快乐求矩阵)
5.1 一维数组
类型名 数组名[元素个数];
T a[N]; //从a[0]到 a[n-1]
该数组占据一片连续的、大小总共为N * sizeof(T)字节的存储空间。
比如a[0]放在地址n,那么a[i]就在n+i*sizeof(T)
“元素个数”必须是常量或常量表达式,不能是变量,且其值必须是正整数。
可以借助数组进行选择排序(小的排第一)、筛分(快刀斩乱麻,删删删!)
5.2 数组的大小限制
数组大小是有限制的,数组所占字节数最多不能超过0x7fffffff。
最好不要再函数内部定义大数组,应将大数组定义在所有函数之外。
定义在所有函数之外的变量,称为全局变量
5.3 二维数组
类型名 数组名[行下标][列下标]
T a[N][M];
该数组占据一片连续的、大小总共为N M sizeof(T)字节的存储空间。
5.4 数组的初始化
类型名 数组名[行下标][列下标] = {值, 值, …,值};
数组初始化时,{}中值得个数可以少于元素个数,未列出的自动赋值0。
在定义数组时,如果给全部元素赋值,则可以不给出数组元素的个数:
int a = {1,2,3,4,5};
二维数组初始化,则必须给出列数,并对每个行数初始化,如:
int a[][3] = {{80,75,92},{61,65}}
5.5 数组作为函数的参数
- 一位数组作为形参时,可以不写出数组的元素个数
- 二维数组作为形参时,必须写明数组有多少列(即每行有多少个元素),从而计算出元素a[i][j]的地址。
【例题】插入排序:左边为有序数列,右边为无序数列。
右边插入左边后,对左边元素比大小,并移位。
例题中的码挺邪乎的,用到了while语句,最后强行把无序最左放到有序中。
并不想在这儿抄一遍。到时候自己敲一下吧……
5.5 数组越界
数组下标超过数组元素个数,不在0~n-1范围内。
此时程序要访问的数组元素并不在数组内,导致数组越界,引发错误,进而改写与该数组相邻存放的变量。
所以,数组的元素个数不要卡着使用所需设定,应留有冗余空间。
总结:
- CSDN这个排版我是仿佛懂了一点了,以后再也不用小标题了,到时候直接写数。亏我word认真排版……枯了
- 书和视频的不同之处在于:查缺补漏。视频讲的真挺全乎的。
- 了解到了char要加单引号,数组的元素个数必须是常量。以后做题可以规避一下了。
- 希望在周末搞出后半段复习