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。因为一场期末考试将我的日常安排搞得一团糟,同时也反应了我平时学习的不够专注,课后没有及时补差,导致考试将至才发现我有许多内容都没掌握清楚。这种情况不只是在线性代数中体现,在我的其他科目也有体现。就在上周,我甚至还弄不懂指针的用处到底是什么?我被自己这种状态吓到了,反省过后发现还需要继续努力。规律日常作息,及时补差,上课集中注意力,将需要完成的任务规划到每一天,让自己充实起来。我相信,只要静下心来,一步一步慢慢走,总能解决所有的问题。希望自己继续努力吧。

代码量统计

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 代码截图
C博客作业05--2019-指针_第1张图片

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提交列表及说明
C博客作业05--2019-指针_第2张图片

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 代码截图

C博客作业05--2019-指针_第3张图片

2.2.3 总结本题知识点

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

2.2.4 PTA提交列表及说明
C博客作业05--2019-指针_第4张图片

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

2.3 PTA题目3

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

2.3.1 伪代码

#include
#include
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] = '\0';
    puts(w);
    return 0;

2.3.2 代码截图
C博客作业05--2019-指针_第5张图片

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提交列表及说明

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


3.阅读代码:

C博客作业05--2019-指针_第6张图片

C博客作业05--2019-指针_第7张图片

  • 代码功能
    首先在第一行输入两个数字,这两个数字将用作矩阵中的行数(R)和列数(C)。然后部门输入信息的字母,沿着矩阵以螺旋模式编码。输入0 0,则结束程序,不做读取,然后对密文进行解密,最后输出解密完成后的字符串

  • 代码优点
  1. 该代码对于二维数组的处理十分厉害,定义了多个变量来对二维数组进行处理。
  2. 结构严谨,for循环,while循环,if语句的运用十分恰当,衔接的地方也处理得当,没有造成代码的多余和复杂。
  3. 多次运用getchar()来吸收换行符。

你可能感兴趣的:(C博客作业05--2019-指针)