0.展示PTA总分
1.本章学习总结
1.1 学习内容总结
- 指针变量的定义
如果在程序中声明一个变量并使用地址作为该变量的值,那么这个变量就是指针变量。定义指针变量的一般形式为:类型名 *指针变量名,例如:int *p
。指针变量名时指针变量的名称,必须是一个合法的标识符。 - 指针的基本运算
取地址运算符&用于取地址,间接访问运算符*用于取内容,例如:p=&a
,p=*a
.
赋值运算符=可以在指针之间互相赋值,例如:p1=&a,p2=p1
。 - 字符串处理函数
函数名 | 函数功能 |
---|---|
getchar | 从标准输入文件读入一个字符 |
putchar | 输出一个字符 |
puts | 把字符串s输出到标准输出文件,' '转换为' '输出 |
fgets | 从fp所指文件中最多读n-1个字符(遇到' '.^z终止)到字符串s中 |
strcat | 把字符串t连接到s,是s成为包含s和t的结果串 |
strcmp | 逐个比较字符串s和t中的对应字符,直到对应字符不等或比较到串尾 |
strcpy | 把字符串t复制到s中 |
strlen | 计算字符串s的长度(不包括' ') |
strstr | 在字符串s中查找字符串t首次出现的地址 |
- 内存动态分配相关函数
函数名 | 函数功能 |
---|---|
malloc | 申请空间并返回首地址 |
calloc | 申请空间并返回首地址,而且将存储块初始化为0 |
realloc | 更改以前的存储分配 |
free | 释放申请得来的空间 |
- 指针做循环变量做法
假设原来的指针为ptr,我们往往需要定义一个新的指针指向ptr,来作为循环变量使用。例如
char* pStr = str;
for (;*pStr;pStr++)
{
if (*pStr == ch) index =pStr;
}
- 字符指针如何表示字符串
1.可以在定义指针的同时就对其进行初始化加以表示,例如char *sp="point"
2.定义指针后为其开辟空间,再使用scanf语句输入字符串,例如
for (i = 0; i < 4; i++)
{
poem[i] = (char*)malloc(20 * sizeof(char));
scanf("%s", poem[i]);
}
- 动态内存分配
一般就是使用malloc函数和calloc函数申请动态内存,使用完之后要使用free函数释放掉申请得来的空间,例如
char* str = NULL;
str = (char*)malloc(N * sizeof(char));
free(str);
- 指针数组及其应用
如果数组的各个元素都是指针类型,用于存放内存地址,那么这个数组就是指针数组。指针数组定义的一般格式为:类型名 *数组名[数组长度]
举例以说明其应用
char* str[100]; //开辟指针数组
for (i = 0; i < n; i++)
{
str[i] = (char*)malloc(10 * sizeof(char)); //申请空间
scanf("%s", str[i]); //输入字符串
}
使用了指针数组之后一个数组内就可以存放多个字符串,并且在输出字符串时只需要提供一个数组元素即可(因为每个数组元素都是对应字符串的首地址)
- 二级指针、行指针
指向指针的指针称为二级指针,一般定义形式为:类型名 **变量名,例如int **pp=NULL
行指针是指向数组的指针,例如int (*a)[5]
写法 | 解释 | 指针类型 |
---|---|---|
a+0或&a[0] | 指向第1个一维数组的地址(指向第1行) | 行指针 |
a+1或&a[1] | 指向第2个一维数组的地址(指向第2行) | 行指针 |
a+2或&a[2] | 指向第3个一维数组的地址(指向第3行) | 行指针 |
- 函数返回值为指针
函数的返回值类型自然也可以是指针类型,即函数可以返回一个地址。但需要注意的是不能返回在函数内部定义的局部数据对象的地址,这些地址在函数结束时会被自动回收,从而导致返回的地址无效,因此返回指针的函数一般都返回全局数据对象的或者主调函数中数据对象的地址,例如
char* Search(char str[], char ch)
{
int i;
char* index = 0;
char* pStr = str;
for (;*pStr;pStr++)
{
if (*pStr == ch) index =pStr;
}
return index;
}
1.2 本章学习体会
学习感受
- 这学期的学习已经过了大半了,我也是从刚开始的似懂非懂进一步到现在稍微懂一些了,但是随着接触的知识越来越多,才明白自己的知识空白是永远填补不完的,只能一直保持学习,希望能够多学会一些东西。现在已经能够使用指针解决一些简单的问题,去体会直接在地址上操作数据的乐趣。对更深一步的指针用法仍然还是存在困惑。
- 计算这两周代码量
题集 | 2019-c10-指针 |
---|---|
代码量 | 356 |
2.PTA实验作业
2.1 6-9 合并两个有序数组(2)
2.1.1 伪代码
- 数据处理
类型 | 变量名 | 由来 |
---|---|---|
int* | temp | 开辟临时数组存放排序后的数组 |
int | i | 循环变量 |
int | j | 数组a下标 |
int | k | 数组b下标 |
- 伪代码
定义void类型的merge函数(形参为int型指针a,int型m,int型指针b,int型n)
定义int型变量i作为循环变量
定义int型变量j作为数组a下标
定义int型变量k作为数组b下标
开辟临时数组temp存放排序后的数组
i,j,k初始化为0
for 循环条件为j < m && k < n do
if a中元素小 then
将a中元素放入temp数组
a移动到下一个元素
else
将b中元素放入temp数组
b移动到下一个元素
end if
end for
while j < m do
将a中剩余元素放入temp数组
end while
while k < n do
将b中剩余元素放入temp数组
end while
for i=0 to m+n do
将temp数组的元素放入a数组
end for
释放temp的空间
2.1.2 代码截图
2.1.3 总结本题的知识点
1.使用malloc函数申请空间,使用free函数释放空间
2.使用for循环和while循环处理数组内的元素
3.运用数组法使用指针
4.分段处理数据的思维
2.1.4 PTA提交列表及说明
-
PTA提交列表
-
PTA提交列表说明
结果 | 原因 |
---|---|
部分正确 | 初步思路是将数据都放入同一个数组再排序,耗时过长 |
部分正确 | 引入变量flag判断是否已经排序好,稍做优化,仍然运行超时 |
部分正确 | b数组可能越界访问数组外的元素 |
部分正确 | 简化代码,仍然存在上述问题 |
答案正确 | 采取分阶段放入数据的方法,正确 |
2.2 7-4 说反话-加强版
2.2.1 伪代码
- 数据处理
类型 | 变量名 | 由来 |
---|---|---|
char* | str | 存放字符串 |
int | len | 记录字符串长度 |
int | i,j | 循环变量 |
int | mark | 控制输出格式 |
int | begin | 记录单词头 |
int | end | 记录单词尾 |
- 伪代码
main函数
定义char*型变量str存放字符串
定义int型变量len记录字符串长度
为str开辟数组空间
输入并处理字符串
计算字符串长度
调用invert函数
释放str的空间
定义void型invert函数(形参为char*型str,int型len)
定义i,j作为循环变量
定义mark控制输出格式
定义begin记录单词头
定义end记录单词尾
for i=len-1 to 0 do
if 找到单词 then
记录单词尾
for j=i-1 to 遇到空格或者字符串到首部 do
寻找单词头
end for
记录下次开始寻找单词的位置以及单词头
输出该单词(注意格式)
mark自增
else
i自减
end if
end for
2.2.2 代码截图
2.2.3 总结本题的知识点
1.使用malloc函数申请空间,使用free函数释放空间
2.字符串的处理
3.单词头尾的判断,从哪儿寻找单词的判断
4.使用strlen函数计算字符串长度
2.2.4 PTA提交列表及说明
-
PTA提交列表
-
PTA提交列表说明
结果 | 原因 |
---|---|
部分正确 | 使用指针数组存储配合scanf输入字符串,但无法判断单词数,单词长度 |
部分正确 | 给每个数组元素分配最大字符数的空间,内存超限 |
答案正确 | 用一个字符数组存放字符串,逆序寻找每个单词后输出,正确 |
2.3 7-6 A-B
2.3.1 伪代码
- 数据处理
类型 | 变量名 | 由来 |
---|---|---|
char | strA[N] | 存放字符串A |
char | strB[n] | 存放字符串B |
static int | ascii | ASCII码数组 |
int | k | 重构造数组下标 |
int | i | 循环变量 |
- 伪代码
main函数
定义数组strA存放字符串A
定义数组strB存放字符串B
输入字符串A,B
调用函数Delete
定义void类型Delete函数(形参为char*型strA,char*型strB)
定义静态int型数组ascii
定义k作为重构造数组下标
定义i作为循环变量
for i=0 to strB结束 do
strB元素为ascii数组下标,ascii数组对应元素自增
end for
for i=0 to strA结束 do
if ascii中的对应位置为0 then
记录到重构数组中
end if
end for
为strA添加结束符
输出strA
2.3.2 代码截图
2.3.3 总结本题的知识点
1.使用fgets函数输入字符串
2.使用hash数组简化问题
3.注意重构数组后要在末尾添加结束符
2.3.4 PTA提交列表及说明
-
PTA提交列表
-
PTA提交列表说明
结果 | 原因 |
---|---|
部分正确 | 这么多部分正确,总结起来就是三个问题 |
部分正确 | 1.数组空间不够大,无法输入所有的数据 |
部分正确 | 2.认为ascii数组太小,但显然想多了 |
部分正确 | 3.数组空间够大,但是使用fgets时却限制了输入的字符个数 |
答案正确 | 解决以上三个问题后,正确 |
3.阅读代码
-
题目
-
题解
-
所选代码优点及可以学习地方
1.使用自定义函数判断罗马数字的值,可以避免过多的判断
2.读取两个罗马数字之前判断下一个字符是否为结束符,确保读取的两个字符均有效
3.读取罗马数字的过程中仅仅使用if语句,而不是if-else语句,大大提高了读取的效率
4.read函数其他情况返回0很巧妙地解决了连续读取可能读取到结束符的弊端