0.展示PTA总分
1.本章学习总结
1.1 学习内容总结
1.指针变量的定义
一般形式:
类型名 *指针变量名;
类型名指定指针变量所指向变量的类型,必须是有效的数据类型,如:int、float、char等。指针变量名是指针变量的名称,必须是一个合法的标识符。
例如:
int i,*p;
定义多个指针变量时,每一个指针变量前面都加上*。
2.指针的基本运算
(1)取地址运算和间接访问运算
单目运算符&用于给定变量的地址。例如:
int *p,a=3;
p=&a;
指针的类型和它所指变量的类型必须相同。
(2)赋值运算
一旦指针被定义并赋值后,就可以如同其他类型变量一样进行赋值运算。例如:
int a=3,*p1,*p2;
p1=&a;
p2=p1;
只能将一个指针的值赋给另一个相同类型的指针。
3.指针变量的初始化
指针变量在定义后也要先赋值再引用。在定义指针变量时,可以同时对它赋初值。例如:
int a;
int *p1=&a;
int *p2=p1;
4.字符串和字符指针
如果定义一个字符指针接收字符串常量的值,该指针就指向字符串的首字符。字符数组和字符指针都可以用来处理字符串。例如:
char sa[]="arry";
char *sp="arry";
5.指针、数组和地址间的关系
指针是以地址作为值的变量,而数组名的值是一个特殊的固定地址,可以把它看作是指针常量。假设有如下定义:
int a[100],*p;
p=a+1是合法的,但a=a+1就是非法的。
6.常用的字符串处理函数
(1)字符串的输入和输出
在系统文件stdio.h中定义。
a.scanf(格式控制字符串,输入参数表)
格式控制字符串中使用格式控制说明%s,输入参数必须是字符型数组名。遇回车或空格输入结束,并自动将输入的数据和字符串结束符' '送入数组中。
例如:scanf("%s",s);
b.printf(格式控制字符串,输入参数表)
格式控制字符串中使用格式控制说明%s,输入参数可以是字符型数组名或字符串常量。输出遇' '结束。
例如:scanf("%s",s);
c.字符串输入函数gets(s)
参数s是字符数组名。遇回车输入结束,自动将输入的数据和字符串结束符' '送入数组中。字符串允许带空格。
d.字符串输出函数puts(s)
参数s可以是字符数组名或字符串常量。输出时遇' '自动将其转换为'
'。
(1)字符串的复制、连接和比较及计算字符串长度
在系统文件string.h中定义。
a.字符串复制函数char *strcpy(char *s2,char *s2)
该函数把字符串s2复制到s1,直到遇到s2中的' '为止。
简化形式为:strcpy(s1,s2);
参数s1必须是字符型数组基地址,参数s2可以是字符数组名或字符串常量。
b.字符串连接函数strcat(s1,s2)
该函数把字符串s2连接到字符串s1后面,s1原有的结束符' '被放置在连接后的结束位置上。
参数s1必须是字符型数组基地址,参数s2可以是字符数组名或字符串常量。
d.字符串比较函数strcmp(s1,s2)
参数s1和s2可以是字符数组名或字符串常量。
若s1和s2相等,返回0。
若s1大于s2,返回一个正数。
若s1小于s2,返回一个负数。
字符串比较规则:字符串比较函数strcmp的比较,两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇' '为止。基本形式为strcmp(str1,str2),若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数。
d.字符串长度函数strlen(s1)
参数s1可以是字符数组名或字符串常量。函数Strlen()返回字符串s1的' '之前的字符个数。
7.用指针实现动态内存分配
(1)动态内存分配的步骤
a.了解需要多少内存空间。
b.利用C语言提供的动态分配函数来分配所需要的存储空间。
c.使指针指向获得的内存空间,以便用指针在该空间内实施运算或操作。
d.当使用完毕内存后,释放这一空间。
(2)动态内存分配函数
a.动态存储分配函数malloc()
函数原型是:void *malloc(unsigned size)
功能:在内存的动态存储区中分配一连续空间,其长度为size。
b.计数动态存储分配函数calloc()
函数原型是:void *calloc(unsigned n,unsigned size)
功能:在内存的动态存储区中分配n个连续空间,每一个存储空间长度为size,并且分配后把存储块里全部初始化为0。
c.动态存储释放函数free()
函数原型是:void free(void *ptr)
功能:释放由动态存储分配函数申请到的整块内存空间,ptr为指向要释放空间的首地址。
d.分配调整函数realloc()
函数原型是:void *realloc(void *ptr,unsigned size)
功能:更改以前的存储分配。
8.指针数组
如果数组的各个元素都是指针类型,用于存放内存地址,那么这个数组就是指针数组。
一维指针数组定义的一般格式为:
类型名 *数组名[数组长度];
例如:int a[10];
char *color[5];
9.二级指针
一般定义为:
类型名 **变量名;
例如: int a=10;
int *p=&a;
int **pp=&p;
10.指针作为函数返回值
返回指针的函数一般都返回全局数据对象或主调函数中数据对象的地址。不能返回在函数内部定义的局部数据对象的地址。
11.行指针
行指针是指向数组的指针,即上面几种指针类型中的 int (*a)[5];所以,当二维数组要被当做参数进行传递时,可以这样声明:
void funcByRowPtr(int (*p)[5],const int row);
或者
void funcByRowPtr(int p[][5],const int row);
1.2 本章学习体会
1.讲的比较快,难以完全理解。
2.基本不太理解。
3.代码量:
2.PTA实验作业
2.1 拆分实数的整数与小数部分
2.1.1 伪代码
```
*intpart=(int)x;//取出整数部分
小数部分=实数-整数
*fracpart = x - (int)x;//取小数部分
```
2.1.2 代码截图
2.1.3 总结本题的知识点
指针做函数参数
void splitfloat(float x, int *intpart, float *fracpart)
指针做函数参数可以返回多个值
2.1.4 PTA提交列表及说明
提交列表说明:
一开始不会做,没有思路,后来请教了一下同学,给我讲解了一下。
2.2 求出数组中最大数和次最大数
2.2.1 伪代码
```
for a+1 to a+n(遍历数组)找最大数
if(下一个数>第一个数)交换最大数
maxptr=*p;*p=*a;*a=maxptr;
end for
再次遍历数组,找次大数
```
2.2.2 代码截图
2.2.3 总结本题的知识点
1.掌握寻找最大值并交换的做法
```
for (p = a+1; p < a + n; p++)
{
if (*p > *a)
{
maxPtr = *p;
*p = *a;
*a = maxPtr;
}
}
```
2.根据寻找最大值的方法学会寻找次大值、最小值、次小值。
3.注意遍历数组时,从第二个元素开始。
2.2.4 PTA提交列表及说明
提交列表说明:
1.答案错误:求最大值和次小值,我只遍历了一遍数组
2.答案正确:请教同学后,分别遍历了一遍数组
2.3 合并两个有序数组
2.3.1 伪代码
```
定义静态数组h[1000001]
for i=0 to m
数组a存进数组h;
for j=0 to n
数组b存进数组h;
i=0;
for (k=0;i<m+n;k++)
if(h[k]>0)
for(;h[k]>0;)
k赋给a[i]
i++;h[k]--;
```
2.3.2 代码截图
2.3.3 本题知识点
1.学会使用静态数组
2.学会使用下标法
2.3.4 PTA提交列表及说明
提交列表说明:
1.段错误:h[k]没有递减
2.答案正确:询问同学改正
3.阅读代码
#include<stdio.h>//标准c,没有用c++的string,这样首先读取字符串就是个问题了
#define MAX 500000
//先处理字符串,删除多余的空格,形成新字符串
//Hello World Here I Come
int main()
{
char s;//指单独一个字符
char t[MAX];//创建一个字符数组
int i = 0, count = 0, flag = 0;
while ((s = getchar()) != '
') {//getchar每次从标准输入读入一个字符 ,标准输入会有'
'???
if (s != ' ') {
flag = 1; //标记遇到单词
t[i++] = s;
count = 0;
}
else if (count > 0) {
continue;//contiue跳过
}
else if (flag) {
t[i++] = s; //只有之前遇到单词的情况下碰到空格才把这个空格写入目标字符串
count++;//这里换成count=1也是完全一样
}
} //删除多余的空格,将目标字符串放入 t 中
//这里的count起了什么作用呢?
//如遇到 Hello,都存入t中,遇到第一个空格,此时count=0,flag=1,把空格存入t,count=1
//World后面的空格 ,第二个空格,遇到空格继续读下一个字符即,continue,起一个跳过作用
//开头就是空格咋办?啥也不操作
count = 0;
int j;
for (i -= 1; i >= 0; i--) {//i-=1.i=i-1,最后一个标号为i里面是没存东西的
if (t[i] != ' ') {
count++; // 这里的 count 统计的是一个单词里字母的个数
}
else if (t[i] == ' ' && count > 0) {
for (j = i + 1; j <= i + count; j++) {
printf("%c", t[j]);
} //遇到空格就输出单词
printf(" ");
count = 0;
}
} // 还剩最后一个单词没输出,因为最后一个单词可能前方无空格 ,只完成了count++,但是没有遇到 空格,那么逻辑是一样的
for (j = i + 1; j <= i + count; j++) {
printf("%c", t[j]);
} //i,j的变量作用范围非常的有用
//这么看来字符数组其实非常的方便,不必非要使用c++的string类 ,continue用来跳过也是极好的
return 0;
}
功能:给定一句英语,要将句中所有单词的顺序颠倒输出。
优点:有注释,代码可读性高,便于理解;
缺点:所有都写在一个函数里,没有分装函数,需要改进。