0.展示PTA总分
1.本章学习总结
1.1 学习内容总结
指针做循环变量做法
char *p;
for(p=a;p<a+n;p++)
字符指针如何表示字符串
const char *str="abcdef";
动态内存分配
int *p;
p=(int *)malloc(n*sizeof(int));
动态申请的内存在结束时要记得释放free()
指针数组
- 形式:类型名 *数组名[数组长度]
- 指针数组是由指针变量构成的数组,在操作时,既可以直接对数组元素进行复制和引用,也可以间接访问数组元素所指向的单元内容,改或引用该单元的内容
- 指针数组名也是二级指针,用数组下标能完成的操作也能用指针完成
二级指针及行指针
- 形式:类型名 **变量名 为指向指针的指针
int a=10;
int *p=&a;
int **pp=&p;
此时&&a、&p、pp等价,&a、p、* pp等价,a、* p、* * pp代表同一个单元,它们的值相同
- 二维数组名是一个二级指针
- 形式:类型名 *指针变量名
- 尽管不同类型的变量所占的空间不同,但不同类型指针变量所占的内存空间大小都是相同的。
- 能将地址作为循环变量,例如p++,从首地址到最末地址。
- 不能用数值作为指针变量的初值,但可以将一个指针变量初始化为一个空指针。
- 数组名可以使用指针形式,而指针变量也可以转换为数组形式。
- 指针的算是运算质保卡两个相同类型的指针相减以及指针加上或减去一个整数。
- 行指针形式:数据类型 (*p)[m]
- 行指针不能直接指向一维数组,p指针指向第一行,行指针特点就是比如p+1,那么p就指向下一行的首地址
函数返回值为指针
- 函数通过return只能返回一个值。如果希望函数调用能将多个计算结果带回主函数,可以将指针作为函数的参数。
- 用指针作为函数返回值时需要注意的一点是,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量、局部数组和形式参数,函数返回的指针请尽量不要指向这些数据
例如下面的例子定义了一个函数 strlong(),用来返回两个字符串中较长的一个
#include <stdio.h>
#include <string.h>
char *strlong(char *str1, char *str2){
if(strlen(str1) >= strlen(str2)){
return str1;
}else{
return str2;
}
}
int main(){
char str1[30], str2[30], *str;
gets(str1);
gets(str2);
str = strlong(str1, str2);
printf("Longer string: %s
", str);
return 0;
}
库函数
- 字符串复制函数:strcpy(s1,s2)
- 字符串连接函数:strcat(s1,s2)
- 字符串比较函数:strcmp(s1,s2)
- 字符串长度函数:strlen(s1,s2)
- 动态内存分配函数:malloc()功能:在内存的动态存储区中分配一连续空间,其长度为size
- 计数动态存储分配函数:calloc()功能:在内存的动态存储区中分配n个连续空间,每一存储空间的长度为size,并且分配后还把存储块里全部初始化为0
- 动态存储释放函数:free()功能:释放由动态存储分配函数申请到的整块内存空间。
- 分配调整函数:realloc()功能:更改以前的存储分配。
字符串处理函数(假设s为字符型数组)
- getchar() 读入一个字符
- putchar() 输出一个字符
- scanf("%s",s)输入字符串,与空格结束
- fgets(s,len,stdin)输入字符串,以‘ ’结束
- printf("%s",s)输出字符串,遇到‘ ’结束
- printf("%c",s[i])输出字符,一般用来循环输出
- puts()输出字符串,' '转换为' '输出
1.2 本章学习体会
- 指针的学习使得编程的难度又上了一层,指针的理解比较困难,个人感觉使用指针做题没有用数组顺畅,但我知道指针在c语言中的地位举足轻重,对于日后的学习也能打下坚实的基础,而对于指针的练习也相对较少,目前对于指针的掌握还不熟练,希望之后可以把指针牢固掌握。
- 代码量700行左右
2.PTA实验作业
2.1合并两个有序数组
2.1.1 伪代码
int i = 0;定义a数组自增变量
int j = 0;定义b数组自增变量
int k = 0;定义c数组自增变量
int *c = (int*)malloc((m + n) * sizeof(int));定义数组c,申请内存,用以存放排序后的两数组元素
for (;i < m&&j < n;)
{
if (a[i] < b[j])判断a,b数组对应元素的大小
{
将a中对应元素元素放入c数组
}
else
{
将b中对应元素元素放入c数组
}
}
while (i < m) c[k++] = a[i++];若a中有剩余元素,将a中剩余元素放入c数组
end while
while (j < n) c[k++] = b[j++];若b中有剩余元素,将b中剩余元素放入c数组
end while
for (i = 0;i < m + n;i++)
将c数组的元素放入a数组
end for
释放c的空间
2.1.2 代码截图
2.1.3 总结本题的知识点
1.动态内存分配开辟新数组,并在结束时释放空间
2.使用循环解决数组元素排序问题
3.将数组元素转移到另一个数组
2.1.4 PTA提交列表及说明
1.多种错误:最开始再用将b数组元素合并到a数组里面,但有运行超时和答案错误
2.部分正确:发现数组在排序时符号错误,改了之后,仍然有运行超时
3.部分正确:换为a数组与b数组比较排序的做法之后,仍然超时,发现是自增变量给搞混了
4.全部正确:全部正确
2.2说反话-加强版
2.2.1 伪代码
char ch;定义字符变量,用于输入字符
char a[MAX];定义字符数组,用于存入字符串
int i = 0, j;定义循环变量
int count = 0, flag = 0;
while ((ch = getchar()) != '
') 输入一串字符
{
if (ch != ' ')
{如果字符不为空格
flag = 1; 转变条件
a[i++] = ch;将非空格字符放入数组a
count = 0;
}
else if (count > 0)
{若有多个空格的情况,跳过此次循环
continue;
}
else if (flag)
{如果是空格,放入第一个空格
a[i++] = ch;
count=1;更改条件,是后续如果有空格,则跳过此次循环
}
}
count = 0;
for (i -= 1; i >= 0; i--)
{逆序遍历数组
if (a[i] != ' ')
{当字符不为空格时,count自增
count++;
}
else if (a[i] == ' ' && count > 0)
{当字符时空格时
for (j = i + 1; j <= i + count; j++)
{
循环输出相应的单词
}
printf(" ");在每个单词后加一个空格
count = 0;重置count的值
}
}
for (j = i + 1; j <= i + count; j++)
{
对于输入的第一个单词,末尾没必要加空格,直接作为最后的单词循环输出
}
2.2.2 代码截图
2.2.3 总结本题的知识点
1.利用while ((ch = getchar()) != '
')循环输入一串字符
2.利用flag等变量控制条件,以按照题目要求执行程序
3.将数组元素逆序遍历,达到相应目的
2.2.4 PTA提交列表及说明
1.部分正确:对于控制空格数量的count的初始值赋值错误
2.部分正确:输出最后一个单词时,j的初始值错误,之前的i=-1,需要再加1
3.全部正确:全部正确
2.3删除字符串中的子串
2.3.1 伪代码
char mom[81], son[81];定义两个数组,别输入主串和子串
char *p;指针用于记录子串查找结果
gets(mom);输入主串
gets(son);输入子串
while ((p = strstr(mom, son)) != NULL)查找主串是否含有子串,若strstr函数返回值不为NULL,证明有查找到子串,反之,则没有
{
*p = ' ';标记查找到子串的位置为结束符‘ ’
strcat(mom, p + strlen(son));将主串中子串之后的部分连接到结束符的位置,将子串位置覆盖掉
}
puts(mom);输出新的字符串
2.3.2 代码截图
2.3.3 总结本题的知识点
1.字符串查找函数strstr() 用于查找str1里的str2,返回值:若str2是str1的子串,则返回str2在str1的首次出现的地址;如果str2不是str1的子串,则返回NULL
2.字符串长度函数strlen() 计算给定字符串的长度,不包括' '在内,返回s的长度
3.字符串连接函数strcat() 连接两个字符串
2.3.4 PTA提交列表及说明
1.编译错误:代码复制过来时出错
2.部分正确:没有审清题意,理解成了删除字符,而不是字符串,导致只过了一个测试点
3.部分正确:改成了删除字符串,然而没有
4.全部正确:全部正确
3.阅读代码
1.功能:在1 / 2,1 / 3... 1 / n 的循环小数表示中总共有多少个数字 k。 输入由几个测试用例组成。 每个测试用例是包含两个整数 n (2≤ n ≤100)和 k (0≤ k ≤9)的一行。 输出数字的总出现次数
2.memset函数:作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。表达式memset(void *s,int ch,size_t n);头文件<memory.h>或<string.h>
3.while(scanf("%d%d",&n,&k)!=EOF) EOF的值其实就是-1,当scanf读取内容发生错误或者读到文件结尾的时候就会返回EOF,那个while的意思就是说当当前输入缓存还有东西时就一直读取,直到输入缓存中的内容为空时停止
4.定义了全局数组,并有宏定义,使代码更为精简