0.展示PTA总分
1.本章学习总结
1.1指针定义、指针相关运算、指针做函数参数
定义:
C 语言规定所有变量在使用前必须先定义,指定其类型,并按此分配内存单元。指针变量不同于整型变量和其他类型的变量,它是专门用来存放地址的,所以必须将它定义为“指针类型”。
指针变量定义的一般形式为:
基类型 *指针变量名;
如:
int *p;
指针相关运算:
2.指针相关运算
(1).取地址运算和间接访问运算
int* p,a=1;
p=&a;
将整型变量a的地址赋给整型指针p,使指针p指向变量a。要注意指针的类型和它所指的类型需要相同。
(2).赋值运算
int a=1;
int *p1,*p2;
p1=&a;
p2=p1;
将a的地址给p1,再将p1的值给p2,所以指针p1与p2都指向a,即p1=p2=a。
(3).指针间的加减运算
一个指针加上一个整数代表着,访问在当前指针所指的位置挪动整数个位置后的数。
指针自增应为(*p)++
(4).赋值
指针变量要先赋值再使用。可以对指针p进行赋值p=0;和p=NULL都表示指针p为空指针,空指针不指向任何一个单元
3.指针做函数参数
主要用于函数的定义与使用
如:
void merge(int* a, int m, int* b, int n); /* 合并a和b到a */
1.2字符指针
(1).字符指针:指向字符型数据的指针变量。每个字符串在内存中都占用一段连续的存储空间,并有唯一确定的首地址。即将字符串的首地址赋值给字符指针,可让字符指针指向一个字符串。
(2).
char *ptr = "Hello";//将保存在常量存储区的"Hello"的首地址赋值给ptr与
char *ptr;
ptr = "Hello";//是等价的,注意不能理解为将字符串赋值给ptr
(3).
char str[10] = "Hello";
char *ptr = str;//数组名代表数组的首地址
//等价于
char *ptr;
ptr = str;//等价于ptr = &str[0];将数组的首地址赋给字符指针ptr
1.3 指针做函数返回值
(1).指针在函数内无返回值时应return NULL;
(1).指针在不同定义类型的函数内的返回值应切合题意返回,诸如int,double,int *,char *
1.4动态内存分配
c 语言主要是使用malloc / calloc / realloc 来进行内存申请的。
malloc / realloc / calloc三者的共同点与不同点:
共同点:
1.都是从堆上进行动态内存分配
2.释放内存都是需要使用free函数来释放
3.三者的返回值都是void*
4.都需要强制类型转换
5.都需要对申请出的空间判空(因为申请内存失败会返回空)
不同点:1)void *malloc( size_t size );
malloc的参数是用户所需内存空间大小的字节数,不会对申请成功的内存初始化。
malloc 申请空间时并不是需要多少就申请多少,而是会多申请一些空间,1)多申请一个32字节的结构体,里面对申请的空间进行描述,2)在申请的空间前后会各多申请 4 个字节的空间,这就是保护机制,当你操作不当越界了,这 8 个字节的内容会改变,操作系统会检查前后 4 个字节是否改变了,以此判断是否越界了。
2)void *calloc( size_t num, size_t size );
calloc的参数:第一个:元素的个数,第二个:单个元素所占字节;会把申请成功的空间初始化为 0
3)void *realloc( void *ptr, size_t size );
realloc的参数:第一个:地址,第二个:字节数
对于 realloc 的第一个参数:
如果指向空,那么此时realloc 就和 malloc 是一样的;
如果不为空,那么就将即将要申请的空间与原空间进行比较。
如果要申请的空间比原空间小,就将原空间缩小,并返回原空间首地址
如果要申请的空间比原空间大,那么分两种情况:
第一种:新旧空间之差小于原空间大小,直接在原空间进行延伸,并返回原空间的首地址。
第二种:新旧空间之差大于原空间的大小,那么直接开辟新空间,并将原空间的数据拷贝到新空间,并返回新空间首地址。
1.5 指针数组及其应用
指针数组的定义
类型名 *数组名[数组长度]
如:
int *a[100];//整型
指针数组是由指针变量构成的数组,在操作时,既可以直接对数组元素进行赋值和引用,也可以间接访问数组元素所指向的单元内容,改变或引用该单元的内容
二维字符数组与字符指针数组的区别
(1).二维数组:一旦定义,那么每个字符数组的字符串最大长度和首地址都不能改变
(2).指针数组:用于存放字符指针的 数组,仅能用来存放指针,所以它指向的每个字符串的首地址均可以改变,字符串的最大长度也可以改变,相比之下,字符指针数组比较灵活一点
1.6 二级指针
二级指针作用是为了获取指针的存放地址。
假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示:
将这种关系转换为C语言代码:
int a =100;
int *p1 = &a;
int **p2 = &p1;
指针变量也是一种变量,也会占用存储空间,也可以使用&获取它的地址。C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号。p1 是一级指针,指向普通类型的数据,定义时有一个;p2 是二级指针,指向一级指针 p1,定义时有两个*。
1.7 行指针、列指针
(1).行指针行指针:指向某一行,不指向具体的元素。
(2).列指针指向行中具体的元素。
&列指针--->行指针
*行指针---->列指针
2.PTA实验作业
2.1 藏尾诗
2.1.1 伪代码
!
2.1.2 代码截图
2.1.3 同学代码
#include <stdio.h>
#include <stdlib.h>
#include "math.h"
#include "string.h"
int main()
{
char *p[4],str[20];
int i;
for(i=0;i<=3;i++){
fgets(str,19,stdin);
p[i]=(char *)malloc(sizeof(str)+1);
strcpy(p[i],str);
}
int n;
for(i=0;i<=3;i++){
n=strlen(p[i])-1;
printf("%s",p[i]+n-2);
}
free(p);
return 0;
}
他运用malloc动态申请内存,调用库函数,代码更简洁,可以适用于更复杂的情况。
2.2 合并2个有序数组
2.2.1 伪代码
2.2.2 代码截图
2.2.3 同学代码
代码更简洁,运用二级指针知识编程,值得学习
2.3 说反话-加强版
2.3.1 伪代码
2.3.2 代码截图
2.3.3 和超星视频做法区别
超星视频做法:逆向遍历数组,每个单词计算其长度,读到空格时输出单词,并使len归0,循环下去直到读到第一个字符,如果第一个字符前无空格,则需加判断条件单独输出。
相比起来我的代码繁杂,判断不清晰。