美文网首页
[C语言] 数组的实际应用三则

[C语言] 数组的实际应用三则

作者: 入梦瞌睡 | 来源:发表于2019-08-02 01:10 被阅读0次

0.前言

1.上一篇文章中,我们重点讲述了:如何main函数的各个模块转化为函数,使得main函数简介合理,利于阅读、整理。
2.今天,则主要讲解c语言中数组的知识及其应用(包括进制转换以及两个有趣的游戏

1.文章目的:

  • 阐述数组的语法、特点等基础知识

  • 通过例子来探究c语言中数组的使用方法、使用思路、注意事项

2.本文主要提及的技术

2.1数组

2.1.1数组基本概念

数组能够开辟多个连续的空间,每个存储空间都能存放一个类型相同的元素
 
注意事项:

(1)此概念仅针对c语言,在java等语言中,同一个数组可以存放不同类型的元素
(2)数组分配的内存空间是连续的,所以如果数组分配空间较大,可能会失败
(3)静态数组定义时必须明确知道数组的大小

2.1.2数组的优缺点

(1)数组的语法定义较为简单
(2)由于有索引值,因此“查找”操作较为轻松
(3)删除数组中央的某个元素较为困难

2.1.3数组的定义

数组的定义方式有三种:
(1)初始化里面确定数组大小

int score[] = {29,13,23,11};

(2)在定义时,明确指定数组大小

int temp[5]; //没有立刻分配空间,int默认元素为0

(3)在定义时明确指定数组大小,且对数组进行一定的初始化

int temp2[5] = {1,2};

注意:

  • 静态数组定义时,不能使用变量
int a[m] = {};//这是错误的写法
2.1.4数组的其他重要知识

(1)数组名,这个变量所占用的内存空间中,存放着数组首地址(同时也是第一个元素的地址)

printf("%p\n", &score[0]);
printf("%p\n", score);
这两句话的效果相同,其中%p专门用来打印地址,而“&”则是代表取变量的地址

(2)数组与循环的关系较为密切

①一般情况下, 对于将某些元素逐个装入数组中的过程,会使用数组+循环的组合
②另外,如果是两个字符串的对比,实际上也是将字符串放入数组中,依靠循环进行比较(比如下文中会提到的猜数字游戏,就是这个道理)

3.技术的具体应用

接下来主要谈一谈标题所提到的数组的实际应用的思路,具体实现会放在下一部分

3.1 应用1——进制转换

(1)数组的主要应用:记录计算结果,并输出

(2)程序思路:
该程序的目的是将任意的十进制数,转换为其他进制数,并输出
如十进制中的数字20,转换为二进制形式,为10100
具体算法根据如下:

十进制转化为二进制方法.jpg
由图可见,转换结果为10100

我们要做的,就是把这个10100放入数组中。
但是按照这个算法得到数字的顺序是00101,(即数组的第一个元素放的是数字的最后一位)因此输出的时候必须倒过来输出(如何倒过来输出后面再说)

3.2 应用2——游戏1·最后谁留下来

效果如图:


image.png
image.png

(1)数组的主要应用部分:记录每个人的编号、是否被淘汰
(2)游戏过程:

先输入一个淘汰号码,每个人从1开始按顺序依次喊出号码,喊出淘汰号码的人便会被淘汰,下一个人从1开始重新喊
该程序的作用便是能够通过不断循环遍历数组,逐次找出被淘汰的编号,以得出最后的生还者

(3)代码思路:

①将每个人的编号记录在一个数组中,然后设置两个变量,一个记录数组下标,一个记录喊出的号码
②两个数同时增加,当喊出的号码等于淘汰号码时,将对应的编号设置为' * '(星号),然后重置喊出的号码(赋值为1),
③重复上述内容,当检测到数组中内容为星号时,跳过该次循环(因>为星号代表已经被淘汰)

3.3 应用3——游戏2·猜数字

先放效果图: image.png

(1)游戏规则:

①系统会随机生成四个不同的数字,玩家需要猜测分别是什么
②玩家允许对正确答案进行猜测,对于玩家的猜测,系统会给予一定的反馈
③反馈格式为:mA,nB
其中m为A的个数,n为B的个数,A表示位置和数字都同时猜对的数字个数,B表示数字猜对了但是位置不对的数字个数
④玩家一共有10次机会,需要不断根据反馈调整自己的答案,以找出正确的序列

(2)数组的主要应用:
数组在这个程序中,主要是用来存放两个序列(正确序列与猜测序列),然后比较两个序列中的值,并返回A与B的个数

4.实际应用(具体实现步骤)

三个例子,我们一个个分析

4.1进制转换的实现

(1)代码细节:

    int result[20] = {};
    int i = 0;//从第一个元素开始,而且最后i可以反映数组中有多少个元素

逐步分析代码:
①首先定义一个数组result[20]以及变量“i”,这个变量i十分重要,不仅可以在下面展示while循环中起到记录下标,其最终结果,还能展现出进制转换后的数字的位数(因为我们不知道转化后的数字有多少位,可以靠i来获取)

    //开始将转换后的数字按照逆序放入数组中
    while (num != 0) {
        result[i] = num % system;//把余数依次放在数组中
        num /= system;//被除数要更新为商
        i++;
    }

这个while循环是由辗转相除法得来的,system指的是进制数,num为待转换的数
result[i]依次装入num对system取余的结果

//开始输出
    printf("该数字的%d进制为",system);
    for (i--; i >= 0; i--) {
        if (result[i]>=10) {
            printf("%c", result[i]+'A'-10);
        }

        else {
            //0到9的数字直接输出即可
            printf("%d", result[i]);
        }
    }
    printf("\n");

最后输出即可,需要注意的是,由于数组中是按照逆序存储的最终结果,因此得倒过来输出
而最终结果的长度,就可以看上文所说的变量i

  • for循环中的第一个i--是因为上面额代码i多++了一次
  • if(result[i]>=10)主要是针对10以上的进制,如十六进制,这些进制会出现10以上的一些数字,并用大写字母代替,而printf("")中的result[i]+'A'-10,则是将数组中大于等于10的数字,转化为对应的英文大写字符(根据ASCII码)

4.2游戏1·最后谁留下来

(1)代码细节:

int nowNum = 1;//当前喊出来的号码
    int lastNum = 7;//剩余人数
    int totalNum = 7;
    int i = 0;

    //1.固定7个人游戏,每个人编号分别是1到7
    char order[7];
    for (int i = 0; i < 7; i++) {
        order[i] = i + '1';
        //printf("%c ", order[i]);
    }

①先定义一些变量,然后定义一个char类型的长度为7的数组,并逐个赋值'1','2',‘3‘ .......‘7’
使用char类型的主要原因是后面想要通过*星号来代表被淘汰的人(当然用int类型数组,然后用0表示淘汰也行)

②然后就是对结果进行验算:

//2.对结果进行验算
    while (lastNum > 1) {
        //此时喊出号码,并判断是否为死亡号码
        if (i == totalNum) {
            //如果已经到头了,回到开头
            i = 0;
        }
        if (order[i] == '*') {
            //已经死亡了,直接下一个
            i++;
            continue;
        }
        else if (nowNum == dieNum) {
            order[i] = '*';
            lastNum--;//剩余人数减1
            nowNum = 1;

            //淘汰一个人就输出一次
            for (int j = 0; j < 7; j++) {
                printf("%c ", order[j]);
            }
            printf("\n");
        }
        else {
            //否则继续喊出号码
            nowNum++;
        }
        i++;
        

    }

③其中lastNum表示剩余人数,totalNum表示总人数(这里其实是数组的长度,不会变化,该变量主要用于下标到6之后,能够通过if语句重新回到0)

④nowNum指的是当前喊出的号码,dieNum表示淘汰号码,当二者相同时,表明该选手被淘汰,则有:

if (nowNum == dieNum) {
            order[i] = '*';
            lastNum--;//剩余人数减1
            nowNum = 1;

            //淘汰一个人就输出一次
            for (int j = 0; j < 7; j++) {
                printf("%c ", order[j]);
            }
            printf("\n");
        }

被淘汰的人用星号表示,下一次星号,则只能下标++,nowNum(喊出的号码)不会变化,即:

else {
            //否则继续喊出号码
            nowNum++;
        }

另外,淘汰号码可以通过手动输入的方式进行更改:

printf("请输入淘汰号码:");
scanf_s("%d", &dieNum);
whoDie(dieNum);//淘汰游戏函数

4.3游戏2·猜数字

(1)代码细节:

int correctOrder[4];//放正确答案
    int guessOrder[4];//放猜测的
    srand((unsigned)time(NULL));//用来生成随机数的种子
    int num = 0;
    int numA = 0;
    int numB = 0;
    int totalTime = 10;//总共10次机会

①先定义变量
②然后下面开始制作正确的序列:

//1.准备好正确的数组序列
    for (int i = 0; i < 4; i++) {
        num = rand() % 10;//0到9随机取一个
        for (int j = 0; j < i; ) {//保证四个数字不重复
            if (num == correctOrder[j]) {
                num = rand() % 10;
                j = 0;
            }
            else {
                j++;
            }
        }
        correctOrder[i] = num;
        //printf("%d ", num);//测试用,打印看一下

    }

其中

 for (int j = 0; j < i; ) {//保证四个数字不重复
            if (num == correctOrder[j]) {
                num = rand() % 10;
                j = 0;
            }
            else {
                j++;
            }
        }

该for循坏主要效果是,将前面已经定好的数字与这次随机数产生的数字进行比较,如果有相同的,则重新去随机数

③获取猜测序列:

//3.输入猜测序列
        printf("输入你的猜测序列:\n");
        while (site != 4) {
            scanf_s("%d", &num);
            guessOrder[site] = num;

            site++;
        }

这里虽然是循环4次,每次只获取1个,但是可以一次性输入四个(中间要有一个空格)

④计算A和B的数量:

numA = numB = 0;//重新从零计算
        for (int m = 0, j = 0; m < 4; m++) {
            if (correctOrder[m] == guessOrder[m]) {
                //看看有没有A
                numA++;
            }
            else {
                //看看有没有B
                j = 0;//重新从头比较
                for (; j < 4; j++) {
                    if (m == j) {
                        //没有A,所以i和j相同的时候跳过
                        continue;
                    }
                    else if (correctOrder[m] == guessOrder[j]) {
                        numB++;
                        break;//B数目+1之后就退出循环
                    }
                }
            }
        }
        printf("%dA,%dB\n\n", numA, numB);

计算思路为:
将两个序列(正确的与猜测的)对齐,然后先看第一个下标的元素,将正确的元素与猜测的相比,如果正确,则numA++
如果不正确,则开始找有没有B,方法就是讲正确的第一个下标元素,以此与猜测序列后面的数字相比较,有相同的则numB++并停止循环

后面的同理,先比较相同位置,看有无A,没有的话再看有无B

⑤最后判断是否达成结束游戏的条件

//5.判断是否结束游戏
        if (numA != 4) {
            totalTime--;
            if (totalTime == 0) {
                printf("机会已经用光\n");
                exit(EXIT_FAILURE);
            }
            else {
                //机会还没有用光,但是还没有正确
                printf("还有%d次机会,请继续", totalTime);
            }

        }

先用if判断numA有没有4个(有就证明已经猜对了)
然后在让totalTime--,并判断机会用光了没有


从第③步到第⑤步,是个循环(毕竟有多次机会),需要用while套在外面,循环条件则是numA != 4

while (numA != 4) {
        site = 0;//每次重新赋值

        //3.输入猜测序列
        printf("输入你的猜测序列:\n");
        while (site != 4) {
            scanf_s("%d", &num);
            guessOrder[site] = num;

            site++;
        }

        //4.下面开始计算A和B的个数
        numA = numB = 0;//重新从零计算
        for (int m = 0, j = 0; m < 4; m++) {
            if (correctOrder[m] == guessOrder[m]) {
                //看看有没有A
                numA++;
            }
            else {
                //看看有没有B
                j = 0;//重新从头比较
                for (; j < 4; j++) {
                    if (m == j) {
                        //没有A,所以i和j相同的时候跳过
                        continue;
                    }
                    else if (correctOrder[m] == guessOrder[j]) {
                        numB++;
                        break;//B数目+1之后就退出循环
                    }
                }
            }
        }
        printf("%dA,%dB\n\n", numA, numB);

        //5.判断是否结束游戏
        if (numA != 4) {
            totalTime--;
            if (totalTime == 0) {
                printf("机会已经用光\n");
                exit(EXIT_FAILURE);
            }
            else {
                //机会还没有用光,但是还没有正确
                printf("还有%d次机会,请继续", totalTime);
            }

        }
    }
    printf("恭喜你猜对了!\n");

5.总结

(1)这次对于数组的三个应用练习,使得我对于数组的运用更加熟练,同时也使我能变得更好地把控函数的书写,以及如何搭建main函数中的逻辑构架
(2)而关于上文代码中需要注意的是,如果想要更改第一个游戏中的总游玩人数(如从键盘手动输入),需要用到动态数组,以及指针,如果有兴趣的可以自行修改,本文就布详细说明了

相关文章

  • [C语言] 数组的实际应用三则

    0.前言 1.上一篇文章中,我们重点讲述了:如何main函数的各个模块转化为函数,使得main函数简介合理,利于阅...

  • c语言的冒泡排序

    C语言菜鸟的入门 看了一天的C语言,出现了第一个关于数组的应用

  • [进阶]C++:数组形参

    使用表准库规范 传递多维数组 C++语言中实际上没有真正的多维数组,多为的多维数组实际上是数组的数组 等价定义 m...

  • [基础]C++:名字的作用域

    使用表准库规范 传递多维数组 C++语言中实际上没有真正的多维数组,多为的多维数组实际上是数组的数组 等价定义 m...

  • [C语言] 部分经典排序算法详解(有图解)

    目录 1.内容概括2.主要算法3.技术的具体应用4.算法实际应用5.总结 0.前言 在上一篇文章《[C语言] 数组...

  • C语言数组的升维与降维之说

    C语言数组的升维与降维之说 C语言数组的升维 C语言数组的降维

  • 11-GoLang切片

    ——引言:无论是C语言中的数组还是Go语言中的数组,数组的长度一旦确定就不能改变, 但在实际开发中我们可能事先不能...

  • 指针数组和数组指针

    指针数组|存储指针的数组 在C语言和C++语言中,数组元素全为指针的数组称为指针数组。 例如:int *p[10]...

  • C-字符串

    字符串 在 C 语言中,字符串实际上是使用 null 字符 '\0' 终止的一维字符数组。C 编译器会在初始化数组...

  • C语言基础教程之字符串

    C语言字符串 C 语言中,字符串实际上是使用null字符 '' 终止的一维字符数组。因此,一个以 null 结尾的...

网友评论

      本文标题:[C语言] 数组的实际应用三则

      本文链接:https://www.haomeiwen.com/subject/mmehdctx.html