主页
Featured image of post 程序设计——考点总结……

程序设计——考点总结……

程序设计课程中个人的部分考点总结……

文章字数:4535
预计阅读时长: 分钟

以下大部分总结于半期考试之前……

一、注意的点

1、用作为“累加、累乘”的变量的注意事项

例子——累加、累乘的变量
  • sum1 = sum1 + a;——作为累加求和。
  • sum2 = sum2 * a;——作为累乘求和。
  1. 是否定义时赋初值?

    • int sum1 = 0;——累加变量赋初值为0
    • int sum2 = 1;——累乘变量赋初值为1
  2. 循环里反复使用,要注意可能要将累加变量清零,累乘变量赋一

    例题

    题目:
    统计3组数据的和,其中每组数据会有n个数。

    部分代码:

    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;	//关键语句:这里即要注意每读完一组数据要清零!否则会带着上次计算的结果算下一组
    }
    

    输出:

    • 加了sum = 0;这句清零语句:
      正确答案
    • 未加sum = 0;这句清零语句:
      错误答案

2、有关函数的讲解和注意事项

函数的三个要点:

  1. 我要给他什么东西?(给几个东西、这些东西是什么类型)
  2. 我想要这个函数干嘛、完成什么事
  3. 他要给我返回个什么东西?(只能返回一个值,否则不叫函数)

一般要求写函数,都是基于这三点分析:

  • 根据1和3两点来确定怎么声明函数。
  • 根据2这点来确定怎么实现函数。

题目:要求写一个函数,用来返回两个整数的最大值。

分析与实现

分析如下:

  1. 我应该给这个函数两个int类型的数据。
  2. 这个函数应该找到这两个数谁最大
  3. 这个函数应该返回给我这两个数的最大值,也是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);
}

题目:要求写一个函数,用来确认某个数是否在某个数组a[10]里(为double类型数组)。

分析与实现

分析如下:

  1. 我应该给这个函数一个我要找的数,这个数为double类型;还要给我要找的数组,这个为数组的double*指针类型。
  2. 这个函数判断这个数是否存在于a这个数组。
  3. 这个函数应该返回给我这个数是否存在于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数组内";
}

函数的注意事项

  1. 如果把函数实现写在int main()之前,便不用在main声明函数了。【见书P86 第二个黑色方框】

  2. 函数一旦return后,便不会再执行之后的语句

  3. 不同函数(包括main这个“主函数”)里面的变量不能互相调用

    即假如main()里有个int a,则不能在子函数fx()中用a = 1这样。
    如果main()里有个int a,子函数fx()里也有个int a:则main里只能用main里的afx里只能用fx里的a

    这个其实就是局部变量的原因,函数里的变量为局部变量,只能在这个函数里用。

二、需要记住的模板

1、生成随机数

  1. 必须写上的代码(提供随机种子)

    直接写在int main()后面的第一句话就好。

    int main()
    {
        srand(time(NULL));
    
        ...
    }
    
  2. 使用方法

    • 要取得$(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;
    

记忆方法:

想象$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、对数组的排序

就两种排序方法:

  1. 冒泡排序
  2. 选择排序

两种方法仅存在写法上的区别,建议自己选择一种自己背得到的记住。
而且写法的差别并不大,仅是for循环范围的区别。

很可能会考到写法【个人感觉【……

【模板见老师的PPT,如果没记的话可以问我……

5、二分查找(折半查找)

有可能要考,考的话会专门指出“请用二分查找来找出…”。
不然的话就可以用“从头到尾遍历数组”来找。

【模板见老师的PPT,如果没记的话可以问我……

使用二分查找,需要先让数组有序,如果是无序的数组先要排序。

三、常用头文件及函数

#include <...>
  1. #include<iostream>

    最基本的库。
    cincout等基本指令都需要这个库,写程序直接写上即可。

    记忆方法
    • io ————> input&output 输入输出
    • stream ————> stream n.流

    即“输入输出流”。

  2. #include<ctime>

    使用随机生成时要用到的库。
    即生成种子时用的time()需要这个库。

    记忆方法
    • c ————> 值c++
    • time ————> time n.时间

    即用来管时间的库。(随机函数需要用时间来作为种子,这样才能保证随机生成不重复)

  3. #include<iomanip>

    控制输出格式要用到的库。
    setw(...)fixed()precision(...)(基本为这三个)需要用到这个库。

    记忆方法
    • io ————> input&output
    • manip ————> manipulator n.操控器 的前五个字母

    即“输入输出控制器”。

  4. #include<string>

    使用c++的字符串要用到的库。
    对字符串大致使用不了解的看书P132-134。(会点很基础的输入输出就行,不用太了解)

【库这些东西多写了没坏处,可以写之前就把这些库都写上,之后复制粘贴就行xd……

四、常见非编译问题和错误弹窗解释

1、未赋初值类

弹窗显示如图:

错误类型1
错误类型1

  • 中文意思:“val”(橙色圈出)这个变量没被初始化(赋初值)就在使用。
  • 出现原因:一般出现在累加变量未赋初值为0,就在用sum=sum+a
  • 解决方法:找到变量名为引号里的变量,在使用其前赋相应初值。
错例

错误1-例

红色划线为对val的使用处,橙色划线为val的定义处。
很明显看到val在使用前未被赋初值。
故在使用前赋个初值(这里为累加变量,所以赋初值为0),即:val = 0

2、数组越界类

弹窗显示如图:

错误类型2
错误类型2

  • 中文意思:变量“a”周围的栈被破坏。【理解不到没关系看下面_(:з」∠)_……
  • 出现原因:出现在对数组元素的访问中,访问的下标超过数组最大个数。
  • 解决方法:找到变量名为引号里的数组的声明部分,将其空间开大点。
错例

错误2-例

橙色划线定义个数组空间为$10$,即只能用a[0]~a[9]
但在红色划线里,却用了a[10],明显超出了最大范围,即越界了,所以会出现此错。
故在定义部分int a[10],把它空间开大点变成int a[11]即可。

这也是数组中很常见的误区和错误需要注意!

3、死循环类

这类错误不会报错,但会感觉程序怪怪的……

比如:

  • 一直黑屏,没有任何反应。
    (如果不确定是不是电脑卡了的原因,可在int main()最开始加一句cout<<"test"来判断:如果输出了test,则证明不是程序卡了。)
  • 明明只想读入几个数,却发现一直在读入。
  • 明明只想输出几个数,却发现一直在输出。

这几类便是说明你的程序陷入了“死循环”。

如下程序:

错误3-例
错误3-例

本意是只读入五个数,输出这五个数的和。

运行时:

错误3-运行界面
错误3-运行界面
发现一直在读入。

  • 出现原因:
    1. 循环变量没有改变。

      如忘了i++i--i=i+2等。

    2. 循环条件不可能中止。

      for (i = 1; i >= 0; i++),$i\geq 0$会一直成立。

    3. 循环里不小心改变了循环变量。

      如:

      for (i = 1; i <=10; i++)
      {
      	...
      
      	i = 0;
      }
      

      每次循环i又会变为0,则会一直循环造成死循环。

还可能有其他各种原因,反正问题都出在循环里,仔细检查下自己写的循环部分

五、其他杂类

  1. 有关i++++i的区别,不懂看书P45。

  2. 有关条件运算符... ? ... : ...的用法(不一定会用,但是要看得懂),不懂看书P45。

  3. 强制类型转换(int)4.8(double)1是否还记得?不记得看书P50。

  4. const(符号常量)这个东西是否还记得?

    const double PI = 3.1415926

    不记得看书P31。

  5. 确定是否掌握setwprecision控制输出格式的用法,不会看书P34-P35。

  6. 对字符数组char a[100],了解这是什么即可(c里面的字符串),不必掌握。

  7. 字符串最后会有个看不见的\000这个空字符:

    如字符串"MinatoAqua"

    • 长度为$10$。
    • 存储时存放$11$个字符串。
  8. 一定注意{}的匹配! 特别牢记你的这个iffor要管哪几句话,就把哪几句话打上{}

  9. 强烈建议把程序写的规范一点

    1. 一句话(用;结尾的)就是一行
    2. {}单独占一行
    3. {之后的语句空两格(或者按“Tab”这个键)
    4. }之后(包含这一行)的语句往前删两个空格(用的“Tab”的删一次就可以)
    5. 具体样式就是以上我写的那种样子。

    这样不只是好看,更能让你的整体思路保持清晰,不然很容易犯{}不匹配的问题!

  10. 要知道你每写一句话是在干嘛,这句话我写出来是什么目的。【有点抽象,不过确实很需要知道自己的目的,怎么实现这个目的,等熟练后这个自然也就会很清楚了orz……


以上,
祝武运昌隆!……