指针

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



0.展示PTA总分(0----2)

1.本章学习总结(3分)

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

⭐指针定义

指针也就是内存地址,指针变量是用来存放内存地址的变量,不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。有了指针以后,不仅可以对数据本身,也可以对存储数据的变量地址进行操作。

· int* p --- p为指向一个整型数据(int型)的指针变量;

· int* p[n] --- 指针数组P由n个指向整型数据的指针元素组成,每个元素都是int*类型;

· int (*p)[n] --- p为指向含有n个元素的一维数组的指针变量,数组内元素均为int型;

· int (*P)() --- p为指向函数的指针,该函数返回一个整型值;

· int **P --- p是一个指针变量,它指向一个指向整型数据的指针变量。

· const char *color[i]=



⭐指针相关运算

  • 指针变量加/减一个整数
    p++,p--,p+i,p-i

  • 指针变量赋值

可以将一个变量或一个函数的入口地址赋值给相应的指针变量

p=&a(则将a的地址赋给p),p=NULL或p=0为空指针,p1=p2(将p2的值赋给p1)

  • 指针变量相减
    不是单纯的两个值相减,而是指两个指针之间的元素个数。(前提:两个指针变量指向同一个数组的元素

  • 指针变量相加
    没有实际意义

  • 指针变量比较
    指向前面元素的指针变量小于指向后面元素的指针变量(前提:两个指针变量指向同一个数组的元素



⭐指针做函数参数

用指针变量作为函数参数, 在函数执行过程中使指针变量所指向的变量值发生变化,函数调用结束后,这些变量值的变化依然保留下来,这样就实现了”通过调用函数使变量的值发生了变化,在主调函数(如main函数)中使用这些改变了值”的目的.

用指针作函数参数可以将函数外部的地址传递到函数内部,使在函数内部可以对外部参数进行改变,并且这些参数的数据变化不会随着函数的结束而消亡

void splitfloat(float x, int* intpart, float* fracpart)
{
	*intpart = (int)x;
	*fracpart = x - (*intpart);
}

此段函数用指针作函数参数,尽管没有返回值,但依旧达到了改变主函数内部变量的目的



🌙1.2 字符指针

⭐指针如何指向字符串

char *p;
char str[10] = "abcd";
p = str;

指针p指向字符串str的首地址,我们可以通过p++来移动指针的指向,从而进行运算



⭐字符串相关函数



以上函数只能用于字符串,不能用于字符

  • tips:字符定义char str='a' 字符串赋值char str[]="a"

qsort()函数

使数组按从小到大的顺序重排。

  • 头文件:#include <stdlib.h>
  • 调用格式:qsort(str,strlen(str),sizeof(char/int),cmp)

一般使用qsort()函数要再写一个自定义函数cmp,来比较数组中相邻两个元素的大小,以达到从小到大排列的作用

int cmp(const void *a, const void *b)
{
	return *((char *)a) - *((char *)b);
}

strtok()函数

将字符串分割成一个个片段

  • 头文件:#include <string.h>
  • 调用格式:char *strtok(char s[], const char *delim)

strtok()函数作用于字符串s,以包含在delim中的字符为分界符,将s切分成一个个子串。即若在字符串s中发现参数delim中包含的分割字符时,则会将该字符改为'\0' 字符。

strtok(str,"\n");
if(str)
printf("%s",str);

可以使用strtok()函数去除字符串末尾的"\n"



🌙1.3 指针做函数返回值

char *search(char *s, char *t)
{
    int lens=strlen(s);//定义字符串s的长度
    int lent=strlen(t);//定义子串t的长度
    int i,j,k;
    int x=lens-lent;//计算二者长度差值
    
    for (i=0; i<=x; i++)
    {
        for (j=0,k=i; j<lent; j++,k++)
        {
            if (s[k]!=t[j]) 
               break;
        }
        if (j==lent)
            break;
    }
    if (i<=x)
        return s+i;//满足条件,返回对应指针
    else 
        return NULL;//不满足条件,返回空指针
}
  • tips1:指针返回时,注意不要返回局部定义的指针,会出现乱码

  • 解决方法
    ① 用局部变量定义(static int/char...)
    用堆定义而不用栈定义(mcollc)
    ③ 使用从主函数中引入的值来存放

  • tips2:指针返回时的类型要与函数定义时的类型保持一致



🌙1.4 动态内存分配

⭐堆区和栈区的区别

  • 栈区:由系统自动分配,速度较快,用于存放函数的參数值,局部变量的值等但程序员是无法控制的。(只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。)
  • 堆区:通过new、malloc、realloc分配的内存块,需要程序员主动进行释放,而平常所说内存泄也就发生在堆区。

⭐动态内存分配相关函数及用法

#include <stdlib.h>
 int *p;
p=(int*)calloc(30240000,sizeof(int))//动态内存申请(前一个为个数n,第二个数为每个单元的空间)
for(i=0;i<;i++)
p[i]=2*i//下标法
for(i=0;i<;i++)
printf("%d",p[i]);
free(p);//申请后要释放,否则会产生内存碎片,影响程序效率

calloc()函数和malloc()函数返回值类型为void(*),赋给其他指针变量时,要强转

int *p;
p=(int*)calloc(n,sizeof(int));

⭐为多个字符串做动态内存要如何分配

char* p[MAXR];
	char str[MAXC];
	for (int i = 0; i < MAXR; i++)/*输入诗歌*/
	{
		gets(str);
		p[i] = (char*)malloc(sizeof(str) + 1);
		strcpy(p[i], str);
	}

此部分为藏尾诗的部分代码,通过循环来对多个字符串进行动态内存分配



🌙1.5 指针数组及其应用

若要表示多个字符串:

·二维数组:char str[3][5]={"abc","bcd","cdef"};

·指针数组: char* str="abc"

  • tips:二维数组字符数组名是常量,不能进行运算,不能改变值。而指针数组的指针变量的值是可以改变的,可以进行运算
    eg:
char* str="abcd";
a++;


🌙1.6 二级指针

A(即B的地址)是指向指针的指针,称为二级指针

在如上的A指向B、B指向C的指向关系中,若A、B、C都是变量,即C是普通变量,B是一级指针变量,其中存放着C的地址,A是二级指针变量,其中存放着B的地址,B的值(即C的地址)是一级指针数据;A的值(即B的地址)是二级指针数据

char *a[3]={"I","love","you"};
char **p=a;
printf("%s %c",*(p+1),*(*(a+2)+2));

这段代码的输出为 love u

🌙1.7 行指针、列指针

⭐定义格式

int (*p)[4]

行指针是指向数组的指针,指的是一整行,不指向具体元素。

格式 解释 指针类型
a+0或&a[0] 指向第1个一维数组的地址(即指向第一行) 行指针
a+1或&a[1] 指向第2个一维数组的地址(即指向第二行) 行指针
a+2或&a[2] 指向第3个一维数组的地址(即指向第三行) 行指针
列指针是指向非常量的常量指针,指的是一行中某个具体元素。
---- ---- ----
a[0]+0或&a[0][0] 指向第1行第1列的地址 列指针
a[1]+1或&a[1][1] 指向第2行第2列的地址 列指针
a[1]+0或&a[1][0] 指向第2行第1列的地址 列指针
a[2]+0或&a[2][0] 指向第3行第1列的地址 列指针

⭐主要用法

用列指针输出二维数组

#include <stdio.h>

void main()
{
   int a[3][3]={1,3,5,7,9,11,13,15,17};
   int *p= a[0];   /*列指针*/

   for(; p < a[0] + 9; p++)/*输出第一行*/
   {
     printf("%d ",*p);
   }
    return 0;
}

用行指针输出二维数组

#include <stdio.h>

void main()
{
   int a[3][3]={1,3,5,7,9,11,13,15,17};
   int (*p)[3]= &a[0]; /*行指针,也可写为int (*p)[4]= a;*/
   int i, j;

   for(i = 0; i < 3; i++)/*输出整个二维数组*/
 {
     for(j = 0; j < 3; j++)
   {
     printf("%d ",*(*(p + i) + j));
   }
 }
    return 0;
}
  • 对行指针解引用,可以得到列指针,对列指针解引用,可以得到具体的元素值。


🌙1.8 易错点及注意事项

  • 指针一定要有指向
  • p=&a;p++,先自增再,但p++=p(p=p+1,因为是后自增)所以p++=a;但自增后p的值变为p+1,不再指向a,p变为野指针
  • NULL符号常量,值为0
  • 空指针:p=0或p=NULL
  • 形参是指针变量,实参一定要是地址。地址的加一是移动到下一个存储单元内,而不是单纯的数值相加。
  • for(p=a;p<a+n;p++)---a为数组a[MAX]


  • strlen()函数:计算\0前的字符串长度
  • len=strlen(str)语句不要放在循环内重复


2.PTA实验作业(7分)

==🌙2.1 输出月份英文名 ==

⭐2.1.1 伪代码

⭐2.1.2 代码截图

⭐2.1.3 找一份同学代码(尽量找思路和自己差距较大同学代码)比较,说明各自代码特点。

该同学使用的是case分支的写法,程序上看起来更清晰易懂,但却也更为繁琐;而我直接使用了数组并加以定义,达到输出月份英文名的效果。



🌙2.2 合并2个有序数组

⭐2.2.1 伪代码

⭐2.2.2 代码截图


⭐2.2.3 找一份同学代码(尽量找思路和自己差距较大同学代码)比较,说明各自代码特点。



该同学与我的做法大体相同,但在变量的设计上不够完备,首先变量名的设置上不够清晰,没有正确使用命名法,其次,他比我多设置了一个变量(而本来是可以不用的),程序更加繁琐了



🌙2.3 说反话-加强版

⭐2.2.1 伪代码


⭐2.3.2 代码截图


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

超星的做法更为清晰简洁

  • 超星使用了while (endP&&endP!='\n')来去掉末尾的"\n"
  • 超星使用了printf("%.*s",len,str)从len开始输出,使程序更加便捷
posted @ 2020-12-27 22:00  noyiie  阅读(103)  评论(0编辑  收藏  举报
// 侧边栏目录 // https://blog-static.cnblogs.com/files/douzujun/marvin.nav.my1502.css