• C博客作业05--2019-指针


    0.展示PTA总分

    1.本章学习总结

    1.1 学习内容总结

    1.地址和指针

    • 地址和指针是计算机中的两个重要概念,在程序运行过程中,变量或者程序代码被储存在亿以字节位单位组织的储存器中。在C语言中,如果定义了一个变量,在编译时就会根据该变量的类型给他分配相应大小的内存单元。
    • 计算机为了对内存单元中的数据进行操作,一般是按“地址”存取的,也就是说对内存单元进行标识编号。如果把存储器看成一个建筑物,建筑物内的房间就是存储器单元,房间号就是地址。
    • 要注意区分内存单元的内容和内存单元的地址。

    2.指针变量的定义

    • 如果在程序中声明一个变量并使用地址作为该变量的值,那么这个变量就是指针变量。定义指针变量的一般形式为:
    类型名 *指针变量名
    例如:int *p
    
    • 类型名指定指针变量所指向变量的类型,必须时有效的数据类型,如int,float,char等。指针变量名时指针变量的名称,必须是一个合法的标识符。
    • 定义指针变量要使用指针声明符*。

    3.指针的基本运算

    • 常用的字符串处理函数:
    strlen  计算字符串s的长度
    strcpy  把字符串t复制到s中
    strcat  把字符串t连接到s,使s成为s和t连接后的新结果串
    strcmp  逐个比较字符串s和t中的对应字符,直到对应字符不等或比较到串尾
    strstr  在字符串s中查找字符串t首次出现的地址
    
    • 与申请动态内存分配有关的函数
    malloc   动态存储分配函数,申请空间并返回首地址
    calloc   计数动态存储分配函数,申请空间并返回首地址,而且将存储块初始化为0
    free     释放由动态存储分配函数申请到的整块内存空间,
    
    • 在使用了malloc函数申请动态内存之后,一定要用free函数释放掉申请得来的空间。

    4.二级指针、行指针

    • 二级指针即指向指针的指针,一般的形式为:
    int **pp
    
    • 行指针,顾名思义就是指向一行的指针。那么哪里会用到行指针呢,用的最多的,那就是二维指针了,大家都知道,我们通常把二维指针看成一个行列式,但是它在内存中的排序却是和一维指针一样的。
      • 比如组a[2][3]={{1,2,3}{4,5,6}},a是整个数组的首地址,同时也指向第一行元素,即a是一个行指针,它每加1,所指地址移动二维数组的一行,a+1指向第二行元素。
      • 对a取,即a指向第一行第一个数,(a+1)指向第二行第一个数,可见,对行指针取值就成了列指针,此时它还是个指针。它每加1,所指地址移动一个元素,a+1指向第二行第二个元素,也可以写成a[1]+1。
    **a
    ``` (也可写成a[0][0])就是这个二维数组第一行的第一个元素,```
     **(a+1)
    ```(也可写成a[1][0])就是第二行的第一个元素,```
    *(*(a+1)+1)
    ```(也可写成a[1][1])是第二行的第二个元素。可见,对行指针取2次*就成了某个元素的值了,而不再是地址。
    
    **5.指针做函数返回值及其注意**
    - C语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数。用指针作为函数返回值时需要注意的一点是,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量、局部数组和形式参数,函数返回的指针请尽量不要指向这些数据,C语言没有任何机制来保证这些数据会一直有效,它们在后续使用过程中可能会引发运行时错误。
    
    ###1.2 本章学习体会
      
    **学习感受**
    这两周进一步学习了指针的运用,同时也学习了递归的运用以及预编译的知识。但是可能是上周的线性代数期末考试,我大大减少了写代码的时间和数量,甚至好几天都没上PTA。因为一场期末考试将我的日常安排搞得一团糟,同时也反应了我平时学习的不够专注,课后没有及时补差,导致考试将至才发现我有许多内容都没掌握清楚。这种情况不只是在线性代数中体现,在我的其他科目也有体现。就在上周,我甚至还弄不懂指针的用处到底是什么?我被自己这种状态吓到了,反省过后发现还需要继续努力。规律日常作息,及时补差,上课集中注意力,将需要完成的任务规划到每一天,让自己充实起来。我相信,只要静下心来,一步一步慢慢走,总能解决所有的问题。希望自己继续努力吧。
    
    **代码量统计**
    ![](https://img2018.cnblogs.com/blog/1772965/201912/1772965-20191204215226804-265799489.png)
    
    ##2.PTA实验作业
    
    ****
    
    ###2.1 PTA题目1
    
    

    2019-c10-指针
    6-9 合并两个有序数组(2)
    要求实现一个函数merge,将元素个数为m的升序数组a和长度为n的升序数组b合并到数组a,合并后的数组仍然按升序排列。假设数组a的长度足够大。

    
    **2.1.1  伪代码**
    

    void merge(int* a, int m, int* b, int n)

    定义循环变量i, j, k, 并赋值i = m - 1; j = n - 1; k = m + n - 1;
    
    定义指针c int *c
    申请空间c = (int*)malloc((m + n) * sizeof(int));
    while i >= 0 && j >= 0
    	if a[i] > b[j] then
    		c[k--] = a[i--];
    	else
    		c[k--] = b[j--];
    while i >= 0
    	c[k--] = a[i--];
    while j >= 0
    	c[k--] = b[j--];
    for i = 0 to m+n-1 do
    	a[i] = c[i];
    free(c);
    
    
    **2.1.2 代码截图**
    ![](https://img2018.cnblogs.com/blog/1772965/201912/1772965-20191201104410167-1157523001.png)
    
    
    **2.1.3 总结本题知识点**
    
    

    1.当进行两个有序数组的连接并重新排序时,个人认为从大的开始排序会更理解一点
    即: while (i >= 0 && j >= 0)
    {
    if (a[i] > b[j])
    {
    c[k--] = a[i--];
    }
    else
    {
    c[k--] = b[j--];
    }
    }
    2.当申请了动态空间时,结束时要记住释放。
    3.当两个数组大小不一样时,当较小数组遍历完后,要记得处理另一个数组的剩余数据
    即: while (i >= 0)
    {
    c[k--] = a[i--];
    }
    while (j >= 0)
    {
    c[k--] = b[j--];
    }
    4.后来测试发现从大的开始输出时,可以不需要重新再定义一个*c,可以直接在a数组上进行重构,这样可以大大减少代码量。

    
    
    **2.1.4 PTA提交列表及说明**
    ![](https://img2018.cnblogs.com/blog/1772965/201912/1772965-20191201105425037-301431396.png)
    
    

    Q1:编译错误
    A1:编写代码时忘记加分号
    Q2:部分正确
    A2:一开始没有看清楚题目,以为是两个函数,所以一开始做的方法是直接将b数组连接到a数组后方,在第二个函数输出是再开始排序,后来发现只用一个函数,于是改用循环比较大小开始重构a数组,但是当n很大时就会超时。
    Q3:全部正确
    A3:林丽老师讲了之后,我尝试用逆着输出,思路与林丽老师的差不多,定义了一个*c,申请动态空间是为了防止越界,从大的开始往前赋值,最后将c数组的值重新赋给a数组,完成题目。

    
    ****
    
    ###2.2 PTA题目2
    
    

    2019-c10-指针
    6-5 字符串反正序连接
    先将在字符串s中的字符按逆序存放到t串中,然后把s中的字符按正序连接到t串的后面.

    
    **2.2.1 伪代码**
    

    void fun(char* s, char* t)
    定义count = 0;
    定义指针char * p;
    p = s;
    while *p do//计算传入字符串的长度
    count++;
    p++;
    for p--; count; count--, p--, t++ do
    *t = *p;//此时的p指向的地址是字符串的最后一位,所有从后往前赋值给t,即倒序赋值;
    for p = s; *p; p++, t++ do
    *t = *p;//进行上一步循环后,p指向的地址变为第一位,正序赋值
    *t = 0;//再赋值完后加结束符号

    
    **2.2.2 代码截图**
    
    ![](https://img2018.cnblogs.com/blog/1772965/201912/1772965-20191203192826724-393689910.png)
    
    **2.2.3 总结本题知识点**
    
    

    1.再定义指针,进行循环计算字符串长度时,地址要记得一起自增
    即:while (p)
    {
    count++;
    p++;
    }
    2.在对t进行重新赋值后要记得加结束符
    即:
    t = 0;
    3.在进行循环时要对循环条件判断,变量的变化做好判断

    
    **2.2.4 PTA提交列表及说明**
    ![](https://img2018.cnblogs.com/blog/1772965/201912/1772965-20191203202413904-370005962.png)
    

    Q1:答案错误
    A1:一开始没有定义*p,而是定义了一个字符串来储存传入的字符串再进行倒叙的赋值,虽然在VS中的测试值与样例答案一样但是PTA的测试却显示答案错误,同时有可能会造成字符数组的对应数值的错误
    Q2:全部正确
    A2:后来重新看来超星视频和翁恺老师的关于指针的视频课后,对指针有了重新的认识,就有了现在这个代码的思路,利用一个新指针的地址来进行赋值,这样不会造成数值的错误,同时也精简了代码。

    
    ****
    
    
    ###2.3 PTA题目3
    
    

    2019-c10-指针
    7-2 藏尾诗
    本题要求编写一个解密藏尾诗的程序。

    
    **2.3.1 伪代码**
    
    

    include<stdio.h>

    include<string.h>

    int main()
    定义字符数组w来储存藏尾诗的输出内容 char w[16];
    定义s来储存诗词 char s[4][20];//储存诗词
    定义len来储存每行诗词的长度;
    定义循环变量i;
    for i = 0 to 3 do
    scanf("%s", &s[i]);
    for (i = 0 to 3 do
    len = strlen(s[i]);//计算每一行的长度
    w[2 * i] = s[i][len - 2];//最少1个汉字,最多9个汉字
    w[2 * i + 1] = s[i][len - 1];
    w[2 * i] = '';
    puts(w);
    return 0;

    
    **2.3.2 代码截图**
    ![](https://img2018.cnblogs.com/blog/1772965/201912/1772965-20191203221751866-924709390.png)
    
    **2.3.3  总结本题知识点**
    
    

    1.一个汉字是占两个字节,因此在寻找对应位置的时候要注意
    即: w[2 * i] = s[i][len - 2];//最少1个汉字,最多9个汉字
    w[2 * i + 1] = s[i][len - 1];

    **2.3.4 PTA提交列表及说明**
    ![](https://img2018.cnblogs.com/blog/1772965/201912/1772965-20191203221837286-556214429.png)
    
    

    Q1:全部正确
    A1:两次运用了不同的写法,第一次是一次遍历每一行的字符串,找到最后一个汉字后进行储存。这个新的代码思路大同小异,但是是对新字符串进行赋值,同时代码会精简很多。

    
    ****
    
    ********
    
    ##3.阅读代码:
    
    ![](https://img2018.cnblogs.com/blog/1772965/201912/1772965-20191204214613869-139407875.png)
    
    ![](https://img2018.cnblogs.com/blog/1772965/201912/1772965-20191204215322441-1020244397.png)
    
    - **代码功能**
    首先在第一行输入两个数字,这两个数字将用作矩阵中的行数(R)和列数(C)。然后部门输入信息的字母,沿着矩阵以螺旋模式编码。输入0 0,则结束程序,不做读取,然后对密文进行解密,最后输出解密完成后的字符串
    
    - **代码优点**
    1. 该代码对于二维数组的处理十分厉害,定义了多个变量来对二维数组进行处理。
    2. 结构严谨,for循环,while循环,if语句的运用十分恰当,衔接的地方也处理得当,没有造成代码的多余和复杂。
    3. 多次运用getchar()来吸收换行符。
  • 相关阅读:
    为什么说 Java 程序员必须掌握 Spring Boot ?(转)
    Vert.x 之 HelloWorld
    Vert.x Web 文档手册
    Vert.x Core 文档手册
    Android数据存储五种方式总结
    设置简单的定时
    自定义dialog
    Android DrawerLayout 高仿QQ5.2双向侧滑菜单
    Fragments碎片
    理解Fragment生命周期
  • 原文地址:https://www.cnblogs.com/caihaoweideboke/p/11965269.html
Copyright © 2020-2023  润新知