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

    这个作业属于哪个班级 C语言--网络2011/2012
    这个作业的地址 C博客作业05--指针
    这个作业的目标 学习指针相关内容
    姓名 李兴果

    0.展示PTA总分

    1.本章学习总结

    1.1 指针定义、指针相关运算、指针做函数参数。

    指针的定义:

     指针是一个变量,用来存放地址的变量
    
    * 指针的值:是某个变量的地址
    p=&a:把a的值取给p,即p指向a;
    
    **指针变量的类型和它所指向变量的类型一致**
    
    *p:直接对内存单元操作,改变变量的数据
    &:取地址,*:取内
    &*p与&a相同,为地址
    *&a与a相同,是变量
     (*p)++相当于a++:将p所指向的变量值加一;
      *p++等价于*(p++):先取*p,然后p自加,此时p不再指向a;
    

    &a的含义:
    pointre_1=
    先对a取地址,之后
    为a所指向的变量,即
    &a与a等价;

    指针变量的初始化:

    (1)指针变量必须先定义,然后地址赋值
    int a;intp;p=&a;

    (2)定义指针的变量时,可同时对对它赋初值
    int a;int *p=&a;

    (3)不能用数值作为指针变量的初值,可将指针变量初始化为一个空指针
    p=0;p=NULL



    相同类型的指针才能相互赋值

    指针实现交换:

    • swap1(a,b),在swap函数中会改变形参的值,但不会影响实参的值
      不能改变main()中实参的值
    • swap2(&a,&b),定义swap(int p1,int p2)将p1和p2交换值之后,主调函数的ab,值也会跟着其变化



    传地址可以返回多个变量值

    形参:指针变量 int *p
    实参:地址&a,某个指针

    数组和地址间的关系:

    (1) 数组名代表一个地址,它的值是数组首元素的地址
    a+i是数组a基地址的第i个偏移量
    &a[i]=a+i;a[i]=*(a+i)

    (2) 指针与数组的关系:
    p=a or p=a[0]

    • 指针做循环变量时候条件
      for(p=a;p<a+n;i++)

    指针的运算:

    (1)指针+或者-一个数,表示指针加减这个数的类型所占内存的整数倍

    (2)指针减去一个指针,表示两个指针之间所差的内存单元或者元素个数,两个指针相加没有意义

    (3)关系运算,如果定义了两个指针变量p和q,并且都已经初始化了
    p-q:两者之间相差的元素
    (int)p-(int)q:两者之间相差的字节数

    *和&两个符号优先级是相同的,运算时自右向左

    int arr[5] = { 1,3,5,7,9 };
    
    int *p = arr;
    
      *++p:p先自+,然后*p,最终为3
    
      ++*p:先*p,即arr[0]=1,然后再++,最终为2
    
      *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
    
      (*p)++:先*p,即arr[0]=1,然后1++,该语句执行完毕后arr[0] =2
    
      *(p++):效果等同于*p++
    

    指针作为函数参数:

    实参和形参之间的数据传输是单向的,实参可以影响形参,而形参不能影响实参。指针但是可以改变实参指针变量所指向的变量的值


    1.2 字符指针

    (1) const:

    • 定义变量,相当于常量
    • 只读变量,必须在定义时就给之赋值

    (2)不要引用未赋值的指针

    • 定义指针时,先将它的初值置为空
      char*s=NULL;

    (3)常用字符串处理函数

    • 函数原型在stdio.h或string.h中给出
      输入:scanf or fgets
      输出:printf or puts

    (4)

    • 字符串复制:strcpy(str1,str2)

    • 字符串连接:strcat(str1,str2)

    • 字符串比较:strcmp(str,str2)
      比较字符串的内容:
      if(strcmp(str1,str2)>0)
      if(strcmp(str1,str2)<0)
      if(strcmp(str1,str2)==0)

    • 字符串长度:strlen(str)
      计算字符串长度,不包括'',fgets()会包括''

    • strcpy与strcat问题
      源字符串需要足够,否则会出现溢出现象

    char *strcpy(char *a,const char *b,size_t n)
    将b中所指向的字符串复制到a当中,最多复制n个字节,当b中字节少于n个字节时,a中剩余部分将用空字节填充

    char *strcat(char *a,const char *b,size_t n)
    将b中所指向的字符串追加到a所指向字符串的结尾,追加最多n个字符

    • strpbrk(str1,str2)
      char *strpbrk(const char *str1,const char *str2)
      检索字符串str1中第一个匹配str2中字符串的字符

    • strrchr()
      char *strrchr(const char *str,int c)
      参数str所指向字符串中最后一次出现字符c的位置

    • strstr()
      char *strstr(const char *haystack,const char *needle)
      字符串haystack中寻找第一次出现字符串needle的位置

    • 引用数组元素:
      指针法:*(a+i)or *(p+i)//a为第一个元素的地址,+i指向第i个元素,若为int类型,则i为四个字节

    三目运算符
    对于条件表达式b ? x : y,先计算条件b,然后进行判断。如果b的值为true,计算x的值,运算结果为x的值;否则,计算y的值,运算结果为y的值。一个条件表达式绝不会既计算x,又计算y。条件运算符是右结合的,也就是说,从右向左分组计算

    1.3 指针做函数返回值

    • 具体格式:
      char *fun()
    {
    char *;
    .......
    return p;
    }
    
    • 要求设计函数match(s,ch),在字符串s中查找字符ch,如果找到,返回第一次找到的该字符在字符串中的位置(地址),否则,返回空指针NULL

    1.4 动态内存分配

    为什么要动态内存分配,堆区和栈区区别。动态内存分配相关函数及用法。举例为多个字符串做动态内存要如何分配。
    (1)

    • 优点:能够根据实际输入数据的多少来申请和分配内层空间,从而提高内存使用率
      (2)
    • 堆区和栈区区别:
      1.申请方式不同
      栈:有系统自动分配
      注意:系统首先会去查看栈上是否有足够的区域去开辟该空间,如果有就直接开辟,如果没有则栈溢出
      堆:自己申请开辟,并且指明大小
      2.底层不同
      栈:是连续的空间
      堆:不是连续的空间

    (3)

    • molloc函数:malloc 函数的返回值是一个地址,这个地址就是动态分配的内存空间的起始地址。如果此函数未能成功地执行,如内存空间不足,则返回空指针 NULL。
      有molloc也要有free,申请后要释放,解放内存

    • free函数:无返回值,它的功能是释放指针变量 p 所指向的内存单元。此时 p 所指向的那块内存单元将会被释放并还给操作系统,不再归它使用。操作系统可以重新将它分配给其他变量使用。

    1.5 指针数组及其应用

    多个字符串用二维数组表示和用指针数组表示区别?

    一维数组定义的一般格式:类型名 *数组名[数组长度]
    指针可以相互转换(时间空间更优化)

    1.6 二级指针

    定义:指向指针的指针

    类型名 **变量名
    int a=10;
    int *p=&a;
    int **p=&p;
    

    1.p变了,pp也跟着变

    2.地址加数值还是地址

    3.二级地址,一个后是一级地址,2
    后才是内容
    a+i=a[i],二级指针

    *(a+i):a[i],表示第i行首元素地址,一级指针
    *(a+i)+j:a[i]+j=&a[i][j],第i行第j个地址,一级地址
    **(a+i):a[i][0]
    ((a+i)+j):a[i][j]
    a+i+j:第i+j行二级地址

    1.7 行指针、列指针

    定义格式、主要用法。
    行指针
    int (*p)[n]

    • 含义:p为指向含有n个元素的一维数组的指针变量,二级指针
    • 行指针p是行地址性质的指针,p+i=a+i!=a[i]二级指针
      (p+i)=(a+i)=a[i]一级指针
    • 行指针可以和数组名互相使用,p[i][j]=a[i][j]

    二级指针

    一个*,表示地址
    两个**,表示元素
    *(*(p+i)+j)=a[i][j]
    
    • 列指针:
    int
    *p;
    p=a[0];
    *(p+i),表示离a[0][0]第i个位置的元素
    
    • 行指针:
    p+i:表示第i行的首地址a[i],二级指针
    a[i][j]=*(*(p+i)+j)=(*(p+i))[j]=p[i][j]
    

    指针数组:

    int *p[n],int **p;p=pp;
    p[i]为指针
    p为二级指针
    

    2.PTA实验作业

    2.1 题目名1

    2.1.1 伪代码

    定义初始化变量s1,s2
    定义 i, num
      输入
    strstr(s1, s2)当s1寻找到在s2中第一次出现的词
       长度为s1中找到的
       char* p = strstr(s1, s2)返回在s1中找到的第一个s2字符串地址 
      定义cnt = strlen(p)  cnt等于所找到的当前s2字符串地址之后所有的字符串个数 
    		当i != strlen(s2)
    		对p中的s2字符串置'',并将p移至下一个地址 
    	往前移位,即num-cnt为当前s1字符串的字符个数 
    	num = strlen(s1)
    	输出
    

    2.1.2 代码截图

    2.1.3 找一份同学代码

    2.2 题目名2

    2.2.1 伪代码

     定义i = m - 1//i为a数组下标
     定义j = n - 1//b数组下标
    定义 k = m + n - 1//为新数组a的下标
       当i,j值都大于0
       如果(a[i] >= b[j])
     将两数组当中最大的值赋给新数组a中最大的位置
                i--
                j--
    当其中一组数排列完毕,剩下一组数则放置新数组a的前面位置
            a[k--] = b[j];
            j--
    

    2.2.2 代码截图

    2.2.3与同学代码区别

    • 我的代码:
      从下标开始,定义合并后数组下标
      从最后一个数开始遍历
      比较大小,移动数的位置

    • 同学的代码:
      采用动态内存分配
      循环条件直到数组读取结束
      分别存储a结束后存b/b存完存a

    2.3 题目名3

    (本题没有做出来)

    2.3.1 伪代码

    2.3.2 代码截图

    2.3.3 请说明和超星视频做法区别,各自优缺点。

    老师的代码

    知识点
    定义指针指字符串,更能动态了解当前字符及位置
    while (* endPtr&&* endPtr != ' ') endPtr++;
    逆向扫描字符串
    while (p != beginPtr) { p--; };
    寻找字符串中单词,即当前一个字符为空格时候
    if(* p != ' '&&* (p-1) == ' ');//当前字符非空格而前一个字符是空格
    输出指定长度字符printf("%.s",len,str);

  • 相关阅读:
    JS和C# 里的闭包及闭包在事件中的使用
    ***项目开发记录
    七牛云存储之应用视频上传系统开心得
    二维码及二维码接合短URL的应用
    EF批量添加,删除,修改的扩展
    ngTemplateOutlet递归的问题
    每日新知2019-06-03
    Spring boot初始
    纯前端播放本地音乐
    macbook 安装任意来源
  • 原文地址:https://www.cnblogs.com/lixinggio/p/14152152.html
Copyright © 2011-2022 走看看