以下大部分总结于半期考试之前……
一、注意的点
1、用作为“累加、累乘”的变量的注意事项
例子——累加、累乘的变量
sum1 = sum1 + a;
——作为累加求和。sum2 = sum2 * a;
——作为累乘求和。
-
是否定义时赋初值?
int sum1 = 0;
——累加变量赋初值为0。int sum2 = 1;
——累乘变量赋初值为1。
-
在循环里反复使用,要注意可能要将累加变量清零,累乘变量赋一。
例题
部分代码:
int sum = 0; //赋初值为0 for (int i = 1; i <= 3; i++) //循环3组数据 { cout << "请输入第" << i << "组数据有多少个数:"; cin >> n; cout << "请输入n个数:"; for (int j = 1; j <= n; j++) //读入并统计这组数据里n个数的和 { cin >> a; sum = sum + a; } cout << "这组数据和为:" << sum << endl; sum = 0; //关键语句:这里即要注意每读完一组数据要清零!否则会带着上次计算的结果算下一组 }
输出:
2、有关函数的讲解和注意事项
函数的三个要点:
- 我要给他什么东西?(给几个东西、这些东西是什么类型)
- 我想要这个函数干嘛、完成什么事?
- 他要给我返回个什么东西?(只能返回一个值,否则不叫函数)
一般要求写函数,都是基于这三点分析:
- 根据1和3两点来确定怎么声明函数。
- 根据2这点来确定怎么实现函数。
分析与实现
分析如下:
- 我应该给这个函数两个
int
类型的数据。 - 这个函数应该找到这两个数谁最大。
- 这个函数应该返回给我这两个数的最大值,也是
int
类型的数据。
故声明部分为:
int max(int, int);
实现部分为:
int max(int num1, int num2)
{
if (num1 > num2)
return num1;
else
return num2;
}
使用部分为:
int main()
{
int max(int, int);
cin >> a >> b;
cout << "两个数的最大值为:" << max(a,b);
}
分析与实现
分析如下:
- 我应该给这个函数一个我要找的数,这个数为
double
类型;还要给我要找的数组,这个为数组的double*
指针类型。 - 这个函数判断这个数是否存在于
a
这个数组。 - 这个函数应该返回给我这个数是否存在于
a
数组,是个bool
类型的数据。
故声明部分为:
bool if_inside(double, double*);
实现部分为:
bool if_inside(double num, double* arr)
{
for (int i = 0; i <= 9; i++)
{
if (arr[i] == num) //如果与数组中某个数相等,代表找到,返回true
return true;
}
return false; //遍历完数组都没找到,代表真的没有,返回false
}
使用部分为:
int main()
{
bool if_inside(double, double*);
cin >> n;
if ( if_inside(n) ) //判断n是否在a数组内
cout << "n这个数在a数组内";
else
cout << "n这个数不在a数组内";
}
函数的注意事项
-
如果把函数实现写在
int main()
之前,便不用在main
里声明函数了。【见书P86 第二个黑色方框】 -
函数一旦
return
后,便不会再执行之后的语句。 -
不同函数(包括
main
这个“主函数”)里面的变量不能互相调用。即假如
main()
里有个int a
,则不能在子函数fx()
中用a = 1
这样。
如果main()
里有个int a
,子函数fx()
里也有个int a
:则main
里只能用main
里的a
,fx
里只能用fx
里的a
。这个其实就是局部变量的原因,函数里的变量为局部变量,只能在这个函数里用。
二、需要记住的模板
1、生成随机数
-
必须写上的代码(提供随机种子)
直接写在
int main()
后面的第一句话就好。int main() { srand(time(NULL)); ... }
-
使用方法
- 要取得$(a,b)$的随机整数,使用
( rand() % (b-a+1) ) + a + 1
; - 要取得$[a,b)$的随机整数,使用
( rand() % (b-a) ) + a
; - 要取得$[a,b]$的随机整数,使用
( rand() % (b-a+1) ) + a
; - 要取得$(a,b]$的随机整数,使用
( rand() % (b-a) ) + a + 1
;
例子——随机生成1到100内的整数(含1和100)
代码:
int num = rand() % (100 - 1 + 1) + 1;
或者直接写成:
int num = rand() % 100 + 1;
- 要取得$(a,b)$的随机整数,使用
记忆方法:
想象$rand()$是能返回完全任意的数。
当你对这个任意的数$\mod 100$(对100取余数)后,那么余数范围只能是$0\sim99$。
再加个$1$,范围变成了$1 \sim 100$。
2、最大公约数(GCD)和最小公倍数(LCM)的计算
这个比较重要,也很难背。
直接背代码。
老师给的版本
int GCD(int a, int b) //求a和b的最大公约数
{
int c, r;
if (a > b) //保证a是两数中较小的数
{
c = a;
a = b;
b = c;
}
r = b % a;
while (r != 0) //这个过程背住orz……
{
b = a;
a = r;
r = b % a;
}
return a; //最后的a值为求得的结果
}
int LCM(int a, int b) //求a和b的最小公倍数
{
return (a * b) / GCD(a, b);
}
这里用函数的形式来写,以后求解可可以直接用这个函数。如:
cin >> n >> m;
cout << n << "和" << m <<"的最大公约数为:" << GCD(n,m) << endl;
cout << n << "和" << m <<"的最小公约数为:" << LCM(n,m);
不用函数的话,就把那里面的东西直接写到main()
里就行。
更好记的版本
利用递归思想求最大公约数,可以极大简化代码。
可以尝试理解下这个代码,能很好的锻炼递归思想。
int GCD(int a, int b)
{
return b ? GCD(b, a % b) : a; //意思是如果b不为0,则a=b,b=a%b辗转相除;否则就返回a
}
或者采用这个递推的思想,极其好记!
int GCD(int a, int b)
{
while (b ^= a ^= b ^= a %= b);
return a;
}
【但原理就不要求掌握了,其中的^=
是位运算……
3、判断某数是否为质数
直接背代码。
代码里有几个要注意的点。
bool if_Prime(int num)
{
if (num == 1) return false;
//!特别注意!:当num=1的时候很可能之后会判断失误,故需要“打补丁”:当num=1的时候直接返回false
bool flag = true; //刚开始假设是素数
for (int i = 2; i <= num-1; i++) //!注意!:这里是(2~num-1),而不是(2~num),很容易在这里写错
if (num % i == 0) //找到能被(2~num-1)之中的数除尽,证明不是素数,设置flag并退出循环
{
flag = false;
break;
}
return flag; //如果循环完都没有被除尽,证明是素数,会返回true;否则会返回flase
}
这里用函数的形式来写,以后判断就可以直接用这个函数。如:
cin >> n;
if ( if_Prime(n) )
cout << n << "是素数";
else
cout << n << "不是素数";
4、对数组的排序
就两种排序方法:
- 冒泡排序
- 选择排序
两种方法仅存在写法上的区别,建议自己选择一种自己背得到的记住。
而且写法的差别并不大,仅是for
循环范围的区别。
很可能会考到写法【个人感觉【……
【模板见老师的PPT,如果没记的话可以问我……
5、二分查找(折半查找)
有可能要考,考的话会专门指出“请用二分查找来找出…”。
不然的话就可以用“从头到尾遍历数组”来找。
【模板见老师的PPT,如果没记的话可以问我……
使用二分查找,需要先让数组有序,如果是无序的数组先要排序。
三、常用头文件及函数
#include <...>
-
#include<iostream>
最基本的库。
cin
、cout
等基本指令都需要这个库,写程序直接写上即可。
记忆方法
- io ————> input&output 输入输出
- stream ————> stream n.流
即“输入输出流”。
-
#include<ctime>
使用随机生成时要用到的库。
即生成种子时用的time()
需要这个库。记忆方法
- c ————> 值c++
- time ————> time n.时间
即用来管时间的库。(随机函数需要用时间来作为种子,这样才能保证随机生成不重复)
-
#include<iomanip>
控制输出格式要用到的库。
setw(...)
、fixed()
、precision(...)
(基本为这三个)需要用到这个库。记忆方法
- io ————> input&output
- manip ————> manipulator n.操控器 的前五个字母
即“输入输出控制器”。
-
#include<string>
使用c++的字符串要用到的库。
对字符串大致使用不了解的看书P132-134。(会点很基础的输入输出就行,不用太了解)
【库这些东西多写了没坏处,可以写之前就把这些库都写上,之后复制粘贴就行xd……
四、常见非编译问题和错误弹窗解释
1、未赋初值类
- 中文意思:“val”(橙色圈出)这个变量没被初始化(赋初值)就在使用。
- 出现原因:一般出现在累加变量未赋初值为0,就在用
sum=sum+a
。 - 解决方法:找到变量名为引号里的变量,在使用其前赋相应初值。
2、数组越界类
- 中文意思:变量“a”周围的栈被破坏。【理解不到没关系看下面_(:з」∠)_……
- 出现原因:出现在对数组元素的访问中,访问的下标超过数组最大个数。
- 解决方法:找到变量名为引号里的数组的声明部分,将其空间开大点。
错例
这也是数组中很常见的误区和错误需要注意!
3、死循环类
这类错误不会报错,但会感觉程序怪怪的……
比如:
- 一直黑屏,没有任何反应。
(如果不确定是不是电脑卡了的原因,可在int main()
最开始加一句cout<<"test"
来判断:如果输出了test
,则证明不是程序卡了。) - 明明只想读入几个数,却发现一直在读入。
- 明明只想输出几个数,却发现一直在输出。
这几类便是说明你的程序陷入了“死循环”。
如下程序:
本意是只读入五个数,输出这五个数的和。
运行时:
- 出现原因:
- 循环变量没有改变。
如忘了
i++
、i--
、i=i+2
等。 - 循环条件不可能中止。
如
for (i = 1; i >= 0; i++)
,$i\geq 0$会一直成立。 - 循环里不小心改变了循环变量。
如:
for (i = 1; i <=10; i++) { ... i = 0; }
每次循环
i
又会变为0,则会一直循环造成死循环。
- 循环变量没有改变。
还可能有其他各种原因,反正问题都出在循环里,仔细检查下自己写的循环部分。
五、其他杂类
-
有关
i++
和++i
的区别,不懂看书P45。 -
有关条件运算符
... ? ... : ...
的用法(不一定会用,但是要看得懂),不懂看书P45。 -
强制类型转换
(int)4.8
、(double)1
是否还记得?不记得看书P50。 -
对
const
(符号常量)这个东西是否还记得?如
const double PI = 3.1415926
不记得看书P31。
-
确定是否掌握
setw
、precision
等控制输出格式的用法,不会看书P34-P35。 -
对字符数组
char a[100]
,了解这是什么即可(c里面的字符串),不必掌握。 -
字符串最后会有个看不见的
\000
这个空字符:如字符串
"MinatoAqua"
- 长度为$10$。
- 存储时存放$11$个字符串。
-
一定注意
{}
的匹配! 特别牢记你的这个if
或for
要管哪几句话,就把哪几句话打上{}
-
强烈建议把程序写的规范一点
- 一句话(用
;
结尾的)就是一行 {
和}
单独占一行{
之后的语句空两格(或者按“Tab”这个键)}
之后(包含这一行)的语句往前删两个空格(用的“Tab”的删一次就可以)- 具体样式就是以上我写的那种样子。
这样不只是好看,更能让你的整体思路保持清晰,不然很容易犯
{}
不匹配的问题! - 一句话(用
-
要知道你每写一句话是在干嘛,这句话我写出来是什么目的。【有点抽象,不过确实很需要知道自己的目的,怎么实现这个目的,等熟练后这个自然也就会很清楚了orz……
以上,
祝武运昌隆!……