美文网首页
数据结构结课作业日记

数据结构结课作业日记

作者: 讲故事的万物 | 来源:发表于2020-06-03 18:11 被阅读0次

    直到昨天中午,我还在因为读错题而疯狂学习新知识。

    把整个任务脑补成了一个巨大的任务的错误太可怕了,以后要记住这次的教训,简直是白费了一天多的功夫。

    不过这两天也不仅仅做这个任务,还复习了计算机网络,但是考试居然不是今天,是下周的今天。

    这种事情怎么老是搞错呢。。。

    算了都是好事不在意它。

    结课作业中的问题

    长久不用C语言,导致语言基础爆炸,很多东西忘记怎么使用,频频报错。

    写两篇日志,分别是C语言的语法方面的问题和C语言算法的问题,本篇是语法问题。

    指针和数组

    这个问题一直是问题,在学C语言的时候草草就过去了,没有细致探讨,这里进行一定的实用性探讨。

    1. 数组名是数组首元素地址
      数组名和指针一样,存储的是地址,特殊在数组名内存储的是数组本身首元素的地址。
      一个词叫做解引用,把一个地址对应的数据取出就是解引用。
      对于一个数组a[N],我们进行了三步:第一步,取出数组元素首地址;第二步,目标地址=首地址+sizeof(type)*N,得到目标a[N]的地址;第三步,对地址解引用。
      对于一个指针p,只有两步,对p的地址解引用,获取到p的值,也就是p指向目标的地址;再对这个目标地址再次解引用,获得目标元素。

    数组名!=数组指针,而是等于数组首元素指针。

    1. 一维数组可以和一维指针混用,二维数组可以喝二维指针混用吗?不可!

    首先我们强调,把多维数组当做一维数组看待。
    比如char arr[3][3],我们就要把它当做一维数组,内里元素分别为arr[0]arr[1]arr[2],这三个char [3]型的数组。

    为什么?
    我们先来看二维数组名代表了什么在代码中:

    代码1:
    char buf[2][2]={{1,2},{3,4}};
    char *p = buf;
    编译结果:
    
    warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
    
    代码2:
    char buf[2][2]={{1,2},{3,4}};
    char (*p)[2] = buf;
    编译结果:
    无警告信息
    

    显然,二位数组的数组名指针类型是char*[2]型,我们应当把二维乃至多维数组看成嵌套型的一维数组,也就是俄罗斯套娃数组,我们可以看到,数组名指针指向的首元素指针既可以是普通变量,也可以是一维或多维数组。

    1. 那么如何用指针来指向数组呢?
      数组中的元素排列是顺序排列的,也就是一横排一横排连续,所以有以下代码可以用指针指向数组并且调用。
    #include<stdio.h>
    #include<stdlib.h>
    
    #define ROW 2
    #define COLUMN 2
    int main(void)
    {
        char buf[ROW][COLUMN]={{1,2},{3,4}};
    char *p = (char*)buf;
    //访问buf[x][y],即访问p[x*COLUMN+y]
    printf("buf = %d,%d,%d,%d\r\n",p[COLUMN*0+0],p[COLUMN*0+1],p[COLUMN*1+0],p[COLUMN*1+1]);
    system("pause");
    return 0;
    }
    

    结果是这样



    通过这个试验,我们可以了解到如何用指针来管理数组了。

    指针传递、引用传递

    函数中有各种参数,普通的直接调用没有什么可说的,仅仅是新建一个值,只存活在函数调用期间,而函数麻烦而又有用的地方就在这指针传递和引用传递。

    1. 二者有什么共同点?
      都是在函数中操作实参地址的,而值传递操作的不是实参地址。

    2. 有什么不同点?
      引用的规则是被引用的同时必须被初始化,同时不能有NULL引用,引用必须与合法的存储单元关联。
      一旦引用倍初始化,就不能改变引用的关系。
      而指针可以任何时候被初始化,可以是NULL,可以随时改变所指的对象。

    3. 二者不同的根本原因。
      从概念上讲。指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变。

      而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量)。

    用一段这个函数,展示下使用流程。

    #include<stdio.h>
    #include<stdlib.h>
    
    #define ROW 2
    #define COLUMN 2
    
    typedef struct TEST
    {
        int a;
        int b[5];
        int *c;
    }testOf;
    
    void tt(testOf *t);
    void ttt(testOf &t);
    int main(void)
    {
        testOf testa,testb;
        testOf *te;
        testOf *teb=&testb;
        te=&testa;
        testa.a=8;
        for(int i=0;i<5;i++){
        tt(te);
        ttt(testa);
        ttt(testb);
        tt(teb);
        }
        teb=te;
        
        printf("%d%d\n",testa.a,testa.c);
        system("pause");
    
        return 0;
    }
    void tt(testOf *t)
    {
        
        t->a++;
        printf("%d\n",t->a);
    
        t->c=&t->a;
    }
    void ttt(testOf &t)
    {
        t.a=100;
        printf("%d\n",t.a);
    
    }
    

    函数多返回值

    很多时候,我们都会碰到一个函数需要多个返回值,但是一个函数的返回值只有一个,如何用一个函数返回多个值呢?

    想到指针就对了,我们可以在参数中使用指针参数,传递我们主函数中的参数,通过这个函数来影响实参。

    我很喜欢一句话就是“编程的本质不就是改变量吗?”先有量的输入,然后改变成很多量,变型、变数、计算都是改变量。

    输入流

    输出的方法千篇一律,大多时候就是好看点和不好看的区别。

    每次写c的时候,做题没感觉,但是只要是写整个程序就会出现各种难受的问题,最大的问题就是输入的问题。

    如何能够方便输入、快速输入经常会成为一个大问题。

    如何能够快速输入呢?
    我们就想到一个方法,用空格隔开数组中的每一个数,用回车来确定。
    这样不仅能清晰看到我们的输入,也比一直敲数字敲回车优雅。

    粗略代码如下

    #include <stdio.h>
    int main(){
        int num;
        int i=0;
        int arr[10];
       while(1){
            scanf("%d",&num);
            char c=getchar();
            arr[i++]=num;
            if(c=='\n'){
                break;
            }
       }
      return 0;
    }
    

    getchar();读走了空格和回车并且在下面判定,空格再次循环,回车退出。

    因为这次是为了给结课作业中的二维数组邻接表做输入,我就简单再写一个给二维数组邻接表赋值的详细代码。

    #include<stdio.h>
    #include<stdlib.h>
    
    #define MAX_V_NUM 10
    #define MAX_INT 999 //不可能数
    //#define MAX_CITY_NUM 10
    
    typedef struct TEST
    {
        char chengshi[20] ;
        int arcsM[MAX_V_NUM][MAX_V_NUM];
        int Vnum,Lnum;
        int *c;
    }testOf;
    
    /*
    typedef struct CITY
    {
        testOf city[MAX_CITY_NUM];
    }TheWord
    */
    
    void init(testOf *map);//初始化邻接表,每个点到其他店为不可能值,到自己为0;
    void mapIn(testOf &map);//手动输入邻接表,按行输入,空格分开数,回车分开行。
    void mapShow(testOf *map);//展示邻接表
    
    
    
    int main(void)
    {
        testOf map,arcs;
        testOf *pmap;
        testOf *parcs;
        pmap=&map;
        parcs=&arcs;
    
        init(pmap);
        mapShow(pmap);
        mapIn(map);
        mapShow(pmap);
    
        system("pause");
        return 0;
    }
    
    /*初始化邻接表,*/
    void init(testOf *map)
    {
        int i,j;
        map->Vnum=MAX_V_NUM;
        for(i=0;i<MAX_V_NUM;i++)    //邻接矩阵的初始化
        {
            for(j=0;j<MAX_V_NUM;j++)
            {
                if(i==j)
                {
                    map->arcsM[i][j]=0;
                }
                else
                {
                    map->arcsM[i][j]=MAX_INT;
                }
            }
        }
    }
    
    /*手动输入邻接表*/
    void mapIn(testOf &map)
    {
        int num;
        int i=0;
        int j=0;
        int Vtime;
        printf("请输入城市中重要站点的数目\n");
        scanf("%d",&map.Vnum);
        Vtime=map.Vnum;
        getchar();
    
        printf("请输入邻接表值,格式为1 2 3 4,将这4个数赋值给邻接矩阵第一排\n");
    
    /*为邻接表手动赋值,0代表不改变*/
        for(i=0;i<map.Vnum;i++) 
        {   
            printf("现在是第%d行,共有%d行\n",i+1,map.Vnum);
            for(j=0;j<map.Vnum;j++)
            {
                scanf("%d",&num);
                char c=getchar();
    
                if(num!=0 && map.arcsM[i][j]!=0)
                {
                    map.arcsM[i][j]=num;
                }
                /*
                if(c==' '){
                    Vtime--;
                    if(Vtime==1){
                        break;
                    }
                }
                */
                if(c=='\n'){
                    break;
                }
            }
        }
    }
    
    /*展示邻接表*/
    void mapShow(testOf *map)
    {
        printf("--------此表如下----------\n");
        int i,j;
            for(i=0;i<map->Vnum;i++)    
        {   
    
            for(j=0;j<map->Vnum;j++)
            {
                printf("%d ",map->arcsM[i][j]);
            }
            printf("\n");
        }
    }
    
    这段代码实现了通过空格隔开数据,分行输入数据到数组中,效果如下

    虽然没有鲁棒性,没有错误显示,不过有了一个大的架子,试验中使用还是足够的。

    本次实验期间任务繁多,如果在最后较为空闲,会补出等同这段代码,会更加美观更加健壮。


    以下是我遇到问题后,上网查资料帮助到我的文章。

    ————————————————
    版权声明:本文为CSDN博主「千淘万漉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/matrix_google/article/details/76595439
    ————————————————
    版权声明:本文为CSDN博主「魏波-」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/weibo1230123/article/details/75541862

    相关文章

      网友评论

          本文标题:数据结构结课作业日记

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