zoukankan      html  css  js  c++  java
  • C博客作业05--指针

    0.展示PTA总分

    1.本章学习总结

    1.1 学习内容总结

    思维导图

    指针与指针变量的概念

    • 指针:内存中的一个存储单元的地址,即内存单元的编号
    • 指针变量:声明一个变量并使用地址作为该变量的值,即一个能存放地址值的变量,通过它存放的地址值能间接访问它所指向的内容

    指针变量的定义、使用方法、初始化

    • 定义:类型名 *指针变量名。例如 : char *p;int *p ; 指针变量的类型应与其所指向内容类型一致
    • 使用方法:使指针变量指向某个变量,(即将某变量的地址值赋给指针变量)。例如:int x; int *p=&a;使用指针变量时必须先赋值后引用,没有被赋值的指针是野指针,它所指向的内容无法确定
    • 初始化:int a;int *p; p=&a; 指针变量不能被赋值,不能直接让指针指向整型数据,指针代表的是一个变量的地址。(可以将0或者NULL赋给指针,但是有的系统不支持赋0)

    指针运算的优先级与结合性

    • &a等同于a,均代表内容; &p等同于&a,均代表地址。(单目运算符优先级是相同的,但从右向左结合。)
    • p++等同于(p++),代表的是内容。
    • (p)++与(p++)的区别:前者是指针p所指向的内容自增相当于a++,而后者是运算完p所指向的内容后将指针向下移了一个位置

    指针与动态内存分配

    我们以往的定义如 :int a[10]; int b等等都是系统的静态内存分配,这些内存在程序运行前就分配好了,不可改变。但是如果我们不知道所输入的内存是多大时,我们定义内存的大小就不能够符合题目的输入,这时我们就应该使用动态申请内存。

    malloc动态申请内存

    int n;//记录输入总个数
    int *p;
    scanf("%d",&n);
    p=(int *)malloc(n * (sizeof(int));
    

    calloc动态申请内存

    int n;//记录输入总个数
    int *p;
    scanf("%d",&n);
    p=(int *)calloc(n , (sizeof(int));
    

    realloc动态申请内存

    int n;//记录输入总个数
    int **p=NULL;
    scanf("%d",&n);
    p=(int **)calloc(p , n * (sizeof(int *));
    

    动态内存释放
    free();
    动态申请内存后都要释放内存,避免数据泄漏和碎片化问题。一个动态申请对应一个释放函数。
    malloc、calloc、realloc区别

    • 相同点:都是从堆上申请空间;都需要类型转化(这三个函数返回值类型都是void);都需要用户free释放;
    • 不同点:三个函数传入的参数不同;calloc会对申请空间初始化,并且初始化为0,而其他两个不会;realloc是对已经存在的空间进行调整,当第一个参数传入NULL的时候和malloc一样;

    指针做循环变量做法

    int a[20];
    int n;
    int *p;
    p=a; //一维数组的数组名就是代表数组的首地址,一般不轻易改变原来的地址,引入一个新的指针变量去遍历
    fgets(a,20,stdin)
    for(p=a;*p&&*p!='
    ';p++)
        printf("%d",*p);
    

    字符指针如何表示字符串

    字符数组,指针遍历

    char str[]="Hello,World";
    char *ptr;
    for(ptr=str;*ptr&&*ptr!='
    ';ptr++)
        printf("%c",*ptr);
    

    指针指向字符串

    char *str="Hello,World"
    char *st;
    st=str;
    for(;*st&&*st!='
    ';st++)
        printf("%c",*st);
    

    数组形字符串存放在全局数据区或栈区,可读可写。指针字符串存放在常量区,只读不能写

    指针数组及其应用

    定义:int *p1[]

    int i;
    char *pch[6]={"妹","妹","你","坐","船","头"};
    for(i=0;i<6;i++)
        printf("%s",pch[i]);
    

    二级指针、行指针

    二级指针

    int i;
    char *color[]={"red","blue","yellow","green","black"};
    char **pc;
    for(i=0;i<5;i++)
        printf("%s",*(pc+i));
    

    行指针

    int i;
    char color[6][7]={"red","blue","yellow","green","black"};
    char (*p)[7];
    for(i=0;i<5;i++)
        printf("%s",*(p+i));
    

    函数返回值为指针

    查找子串
    返回子串第一个字符所在位置用指针表示

    char *match()
    {
        char ch,str[80],*s=str;
        scanf("%s",str);
        getchar();
        ch=getchar();
        while(*s!='')
        {
            if(*s==ch)
                return s;
            else
                s++;
        }
    return (NULL);
    }
    

    1.2 本章学习体会

    学习感受

    指针类型的题集,我几乎都是用数组做的,因为数组先入为主,掌握基本的知识比之前做数组的题目要上手一些。我对指针的了解也只是皮毛,运用的不是得心应手。很多时候用数组可以处理的问题,用指针我反而不会了。何时使用指针会简化PTA的题目,而何时用指针反而使题目复杂化,对于这样的使用指针的一个程度我还没有把握到。指针的使用是有一个限度的,学习它就要找到那个限度才能算是真正的征服了指针,不然就是指针碾压我们。后续要再多练习,仍旧不能对指针有松懈,林老师说下周一指针测试的时候我的内心慌的不行。总感觉指针这一章,我什么都没学到,而且一直想知道明明学了数组,为什么还要再学指针(在我心里觉得指针和数组是等价的)!!!最明显的感受是这两周代码量明显降低了,而且学C的热情也有所降低,没有之前的关注了,之前一道题目我可以调试一个小时两个小时的,现在调半个小时我就烦了,会把问题拖到明天,之前是今天的问题今天一定要解决。因为心态发生变化了,积极性也降低了,后果就来了,上一次数组的小测,直接爆炸。这次的事情给了我提醒,要想学好一门语言,不拿出百分之二百的热情对待它根本学不好,中途也不能开小差,不能有任何的侥幸心理。坚持下去......一路走到底,未来仍可期。有一句话,要时时刻刻放在心上,铭记在心里。不忘初心,方得始终。想想当初学习IT的那份决心,万不可松懈。学习如逆水行舟,不进则退。可能是因为长时间的写博客作业,加上我们理科生对文字并不敏感,在完成博客作业上,我感觉到了逐渐的松懈,但是博客作业对我们来说是一种总结,我们不能把它当成作业来完成,而是要享受这个过程,这是一个自我复习、自我巩固的过程,也能帮助我们自我完善,改观疲倦心态,不忘初心!

    代码量

    2.PTA实验作业

    2.1 题目名1-7-4 说反话-加强版

    2.1.1 伪代码

    定义一个字符指针char *str用来储存输入字符
    定义一个整型变量int min用来储存第一个单词最后一个字符所在位置
    动态申请字符指针的内存大小str = (char*)malloc(500005 * sizeof(char))防止栈溢出,所以在堆里申请
    输入字符串
    int len=strlen(str)-1;
    int p=len;//每次输出最后一个单词后,长度要对应减少用p来储存
    for int i=0 to len do i++
        if(str[i]!=' ')
            把此时的i储存在min中
            break
        end if
    end for
    for i=len-1 to 0 do i--
        if (str[i] == ' ' && ((str[i + 1] >= 'a' && str[i + 1] <= 'z') || (str[i + 1] >= 'A' && str[i + 1] <= 'Z')))//找到最后一个单词的首字符
            for int j=i+1 to p do j++
                if (str[j] == ' ')
                    break;
                end if
                输出字符str[j]
            end for
            if((j-1)!=min)//防止最后一个单词多输出空格
                输出空格
            end if
            p=i;
        end if
    end for
    for i=0 to min+1 do i++
        输出字符str[i]
    end for
    释放动态申请的空间free(str)
    

    2.1.2 代码截图

    2.1.3 总结本题的知识点

    定义指针字符串,更能动态了解当初字符及其位置
       如果头文件包括#include<string.h> 可以直接使用strlen函数
       没有#include<string.h> 的头文件,就直接最字符串进行扫描让指针指到最后一个字符 while(*str&&*str!='
    ') str++
    找到字符串中第一个空格的位置,防止最后输出时字符串后面多了一个空格。
       while(str[min]!=' ') min++;
    找到子字符串的首字符,当前字符是空格下一个字符为字母就是子字符串的首字符
       if (str[i] == ' ' && ((str[i + 1] >= 'a' && str[i + 1] <= 'z') || (str[i + 1] >= 'A' && str[i + 1] <= 'Z')))
    

    2.1.4 PTA提交列表及说明

    Q1:两个测试点没过,最大字符长度还有最后一个单词有空格
    A1:重新写所有的代码,提交。
    Q2:多种错误所有测试点都没有过,总感觉自己写的没毛病,可是它就是不按照我预期的输出
    A2:有一个循环进入进入了死循环,而且有好几个循环即使满足了条件也不会进入,然后对这些问题进行修改,再提交
    Q3:代码没有救了,各种测试点,各种错误,卡着,不给你过。
    A3:没有办法了,只能去百度搜这道题目了。
    Q4:运行我写的代码还是不能正确的输出,百度上的代码还使用了一个我之前没有见过的函数strtok,尽管是这样还是错了很多
    A4:这个时候,代码的可读性已经很低了,参杂了自己的代码,还加入了百度上面的代码。我就决定在纸上重新整理一下自己的思路。
    Q5:明明样例输出和我运后的结果是一样的,可是PTA这个测试点sample没给我过
    A5:因为空格不好看出错误,我就把空格用#来代替,果然就发现了,输出后的字符在末尾都多加了一个空格,用一个变量储存第一个空格的位置,这样在输出空格时加一条判断语句,就可以末尾不输出空格
    Q6:最后一个测试点,最长长度的字符串输出没过
    A6:灵机一闪,把字符串长度比题目的要求加5,果然就过了
    

    2.2 题目名2-6-9 合并两个有序数组

    2.2.1 伪代码

    定义一个整型指针*temp
    动态申请空间temp = (int*)malloc((m + n) * sizeof(int))
    for int k=0 to  do k++ 
        if(a[int i=0]<b[int j=0]
            把a[i]储存在temp[k]中
            i++
        else
            把b[j]储存在temp[k]中
            j++;
        ende if
    end for
    while(i<m) do
        依次把a数组中剩余的元素赋值给temp
    end
    while(j<n) do
        依次把b数组中剩余的元素赋值给temp
    end
    for i=0 to m+n do i++
        把temp中的元素依次赋值给a数组
    释放内存free(temp)
    

    2.2.2 代码截图

    2.2.3 总结本题的知识点

    使用指针扫描两个有序数组并有序储存,运行时间少于先合并两个数组再将合并数组进行排序
    两个数组长短不一样时,for循环结束时不能扫描完全,要继续用循环将没有扫描到的数组元素放入到temp中
    

    2.2.4 PTA提交列表及说明

    Q1:程序不能运行
    A1:错误太多了,改一个又错一个,只能重新写程序了
    Q2:写了一个新的代码,先合并两个数组再将合并数组进行排序
    A2:部分正确,当两个数组的长度都达到极限时,运行超时。
    Q3:上面那种情况我不知道怎么处理,就去向助教请教了....
    A3:助教说,用一个新的数组存放两个数组元素较小的那一个数,又重新写过了代码
    Q4:答案错误,数组储存不完整,没有把所有的元素都放进去
    A4:用两个while循环,将没有遍历的元素放进新数组中去
    

    2.3 题目名3- 删除字符串中的子串

    2.3.1 伪代码

    定义一个数组str1[83]用来储存主串
    定义一个数组str2[83]用来储存子串
    定义一个变量k用来储存当前主串所在位置
    输入主串
    输入子串
    int len1=strlen(str1)-1
    int len2=strlen(str2)-1
    for int i=0 to len1 do i++
        k=i
        int j=0
        while(str1[k] == str2[j]&&str1[k + 1]&&str2[j + 1]) do
            k++;j++
        end
        if(str2[j] == '' ||str2[j] == '
    ')
            for int m=0 to len2 do m++
                for int t=i to len1 do t++
                    将数组str1[]往前移,达到删除子串的目的
                end for
                给数组最后一个字符赋0
            end for
            len1=len1-len2
            i=-1
        end if
    end for
    输出数组str1[]
    

    2.3.2 代码截图

    2.3.3 总结本题的知识点

    运用指针,判断主串里面是否含有子串,储存子串首字符在主串中的位置然后将主串向前移动len2次 
    主串删除子串后,长度减少len2,所有每一次删除后,都要对len1进行减法运算
       len1=len1-len2
    每删除一次子串后,让循环位置回到0,从头开始进行扫描,这样就能解决嵌套子串的问题
       i=-1
    

    2.3.4 PTA提交列表及说明

    Q1:数据是原样输出,没有可删除的测试点可以过,与输出样例不符合
    A1:修改代码,调试....
    Q2:程序进不去是否为子串那个if语句的判断
    A2:发现if语句变量写错了....修改代码
    Q3:全删空的测试点可以过,但是样例仍然不能过,只能删除一次子串
    A3:去百度了,阅读别人的代码,与我的结合起来
    Q4:东拼西凑的代码显然过不了PTA的法眼
    A4:没办法了,又去麻烦助教去了,他说每次删除完子串后,让最外层循环回到字符串的首字符进行重新扫描删除,重复上述工作,就可以了
    

    3.阅读代码

    代码功能

    给定一组不同长度的木棒,是否可以将它们端对端地连接起来形成正方形,对于每种情况,如果可以形成正方形,则输出包含“yes”的行;否则输出“no”。

    代码优点

    • 使用bool函数,返回真假。而我一般使用flag或者是1/0判断真假,这个函数可以学习一下。
    • 使用递归函数dog,刚好我们前两天也学了递归函数,学习该代码的优秀地方,dog函数是一个void函数类型,但是有一些判断语句后,加了return,直接结束了该函数的运行,方便而且节省时间
    • 给a[0]=-100000,b[0]=1灵活赋值,然后代入dog函数里面,完成函数功能。
  • 相关阅读:
    纯css改变下拉列表select框的默认样式
    jquery 购物车
    如何统计页面标签使用次数?
    uni-app—从安装到卸载
    详解Vue 方法与事件处理器
    LoadRunner
    Python-函数
    Python-函数
    python-列表
    python-循环
  • 原文地址:https://www.cnblogs.com/springxinxin/p/11949193.html
Copyright © 2011-2022 走看看