C博客作业05--指针
1. 本章学习总结
1.1 思维导图
1.2 本章学习体会及代码量学习体会
1.2.1 学习体会
这几周学习了指针,指针是C语言的一个重要的概念,也是特色之一。它可以通过对地址的访问来改变值,所以它的用处也很多,例如交换数就可以通过指针来完成。可是运用指针,大多时候都要通过运行看能不能通过编译来判断是否要加*或者不加* 。做指针题集时,函数题还有些用到指针,但是编程题就没有用到了,还是用之前的老方法做(不大会用指针)。知道指针是很重要的一部分,等到掌握得更熟练再回来重新做一遍吧。还学习了字符串处理的一些函数,之前赋值都是直接用等号,判断用大于小于,但是字符串的判断就要调用函数了,刚开始用还真是很容易出错。PTA的题目,将之前对数据的处理变成了对字符串的处理,可以对这些函数多些运用吧
1.2.2 代码累计
2. PTA总分
2.1 截图PTA中指针题目集的排名得分
2.2 我的总分:110
3. PTA实验作业
3.1 PTA题目1
求子串在母串中最后一次出现的地址
给定程序中函数fun的功能是:求出在字符串中最后一次出现的子字符串的地址,通过函数值返回,在主函数中输出从此地址开始的字符串;若未找到,则函数值为NULL。
函数接口定义:
char *fun (char *s, char *t );
其中 s和t 是用户传入的参数。函数求 t指针所指的字符串在s指针所指的字符串中最后一次出现的地址,并返回,若未找到,则函数值为NULL。
3.1.1 算法分析
定义整型变量i,j,k,n,用来判断是否出现子串的flag=0
定义字符指针变量p
for 从i=0到t数组为空字符 do
i++
将i的值赋给n
end for
for 从i=0到s数组为空字符 do
for 从i=j,k=0开始到s数组结束,并且s数组和t数组中的字符一样时 do
if t数组最后一个字符不为空字符 do
指针p指向s数组中第j-n个字符即最后一次出现t串时的位置减去t串的长度
flag=1
end if
end for
end for
if flag==0
返回 p 为空指针
否则返回 p
3.1.2 代码截图
3.1.3 PTA提交列表及说明表及说明
Q1:一开始没有定义指针让它来指向要输出的数组,直接把s数组return回去了,调试过程中发现它并没有按我所想的情况发展
A1:加了个字符指针,让它指向要输出的首地址,最后把这个指针返回回去就可以了
4.大作业
4.1改造函数介绍
4.1.1函数1
- 伪代码
定义存放随机数num1,num2,num3,随机运算符operation_1,operation_2
operation_1=rand()%4
operation_2=rand()%2//产生范围内的随机数,用于switch
switch(level)//level是主函数传参进来的数
case 1:
num1=rand()%10
num2=rand()%10
itoa(num1,exp,10)//将整型数据转化为字符数据并存在数组中char *itoa( int value, char *string,int radix); 原型说明:value:欲转换的数据。string:目标字符串的地址。radix:转换后的进制数,可以是
10进制、16进制等。
switch(operation_1)
case 0:strcat(exp,"+");break;//将符号接到数组里
......
end switch
strcat(exp,itoa(num2,exp+3,10))//将第二个数也接到数组里,因为前一个数和运算符占了2个字节,所以exp从第3个开始存放进去
break;
case 2:
.......
case 3:
.......
//等级二,等级三均同理可得到一个式子
end switch
strcat(exp,"=")//接上等于号
输出exp
- 截图函数代码
void CreateExp(char *exp,int level)
{
int num1,num2,num3;
int operation_1,operation_2;
srand(time(NULL));
operation_1=rand()%4;
operation_2=rand()%2;
switch(level)
{
case 1:
srand(time(NULL));
num1=rand()%10;
num2=rand()%10;
itoa(num1,exp,10);
switch(operation_1)
{
case 0:strcat(exp,"+");break;
case 1:strcat(exp,"-");break;
case 2:strcat(exp,"*");break;
case 3:strcat(exp,"/");break;
}
strcat(exp,itoa(num2,exp+3,10));
break;
case 2:
num1=rand()%100;
num2=rand()%100;
num3=rand()%100;
itoa(num1,exp,10);
switch(operation_2)
{
case 0:strcat(exp,"+");break;
case 1:strcat(exp,"-");break;
}
strcat(exp,itoa(num2,exp+4,10));
switch(operation_2)
{
case 0:strcat(exp,"+");break;
case 1:strcat(exp,"-");break;
}
strcat(exp,itoa(num3,exp+7,10));
break;
case 3:
num1=rand()%1000;
num2=rand()%1000;
num3=rand()%1000;
itoa(num1,exp,10);
switch(operation_2)
{
case 0:strcat(exp,"+");break;
case 1:strcat(exp,"-");break;
}
strcat(exp,itoa(num2,exp+5,10));
switch(operation_2)
{
case 0:strcat(exp,"+");break;
case 1:strcat(exp,"-");break;
}
strcat(exp,itoa(num3,exp+9,10));
break;
}strcat(exp,"=");
puts(exp);
}
4.1.2函数2
- 伪代码
将exp和level传入该函数里面
if 等级为1并且是除号
while 除数为0
清屏//将非法式子清除
调用函数CreateExp
if 不是除号或者除数不为0
跳出while
end if
end while
while num1取余num2不为0//即不能整除属于非法式子
清屏
调用函数CreateExp
if num1取余num2为0
跳出while
end if
end while
end if
- 截图函数代码
int IsExp(char *exp,int level)
{
srand(time(NULL));
if(level==1&&exp[1]=='/')
{
while(exp[2]=='0')
{
system("cls");//调用清屏函数将非法函数去掉
CreateExp(exp,level);
if(exp[1]!='/'||exp[2]!='0')
break;
}
while((exp[0]-'0')%(exp[2]-'0')!=0)
{
system("cls");
CreateExp(exp,level);
if((exp[0]-'0')%(exp[2]-'0')==0)
break;
}
}
}
4.1.3函数3
- 伪代码
定义整型变量m来存放数据,sum做整个式子的结果,i
定义字符型变量oldc为+
do
if exp数组的第i个数据是大于0并且小于9
m=10*m+exp[i]-'0'//将字符数据转化为数字数据
else
if oldc为加号
sum+=m
else if oldc为减号
sum-=m
else if oldc为乘号
sum*=m
else
sum/=m
end if
i++//字符数组exp往后移
while 最后一个数据时不为=
return sum//将sum的值返回到主函数
- 截图函数代码
int ComputeExp(char *exp)
{
int m=0, sum=0,i=0;
char oldc='+';
do
{
if(exp[i]<='9'&&exp[i]>='0' )
m=10*m+exp[i]-'0';
else
{
if(oldc=='+' )
sum += m;
else if(oldc=='-')
sum -= m;
else if(oldc=='*')
sum*=m;
else
sum/=m;
m = 0;
oldc =exp[i];
}
i++;
}while(exp[i-1]!='=');
return sum;
}
4.2与原有函数代码进行比较
- 改造前函数1和改造后的函数1
改造前
void Number()
{
switch(level)
{
case 1:
srand(time(NULL));
num1=rand()%9+1;
num2=rand()%9+1;
break;
case 2:
srand(time(NULL));
num1=rand()%90+10;
num2=rand()%90+10;
num3=rand()%90+10;
break;
case 3:
srand(time(NULL));
num1=rand()%900+100;
num2=rand()%900+100;
num3=rand()%900+100;
break;
}
}
void Operation()
{
int operation_1,operation_2;
srand(time(NULL));
operation_1=rand()%4;
operation_2=rand()%2;
if(level==1)
{
switch(operation_1)
{
case 0:ch1='+';break;
case 1:ch1='-';break;
case 2:ch1='*';break;
case 3:ch1='/';break;
}
}
else
{
switch(operation_2)
{
case 0:ch2='+';ch3='+';break;
case 1:ch2='-';ch3='-';break;
}
}
}
void GameBegin()
{
int response;
if(level==1)
{
printf("你的题目是%.0f %c %.0f =\n",num1,ch1,num2);
}
else if(level==2)
{
printf("你的题目是%.0f %c %.0f %c %.0f =\n",num1,ch2,num2,ch3,num3);
}
else
{
printf("你的题目是%.0f %c %.0f %c %.0f =\n",num1,ch2,num2,ch3,num3);
}
}
改造前用了三个函数来完成得出随机的式子,一个函数用来产生随机数,一个函数用来产生随机运算符,另一个用来将它们连接并且输出
改造后的代码将这三个函数共同完成的内容并到同一个里面来完成,就不用定义那么多全局变量,让不同函数共用一个变量。而且代码量也少了,看起来比较简洁
- 改造前函数2和改造后的函数2
改造前得到随机数时直接使用rand()%9+1,这样就不会得到0,所以就没有判断除数为0的情况。但是之前的除法都认为不能整除也是正常的式子,所以还要考虑用户输入的答案和计算机给出的答案会不一致,考虑的就比较多
改造后将式子都控制在可以整除的情况下,所以在下一个计算结果的函数就可以比较轻松了
- 改造前函数3和改造后的函数3
改造前
double Gameresult()
{
double result;
switch(ch1)//一级难度的一步运算i
{
case '+':
result=num1+num2;break;
case '-':
result=num1-num2;break;
case '*':
result=num1*num2;break;
case '/':
result=num1/num2+0.005;
result=1.0*((int)(result*100))/100;
break;
}
switch(ch2)//二,三级难度的两步运算
{
case '+':result=num1+num2;break;
case '-':result=num1-num2;break;
}
switch(ch3)
{
case '+':result=result+num3;break;
case '-':result=result-num3;break;
}
return result;
}
改造前一级难度和二三级难度在计算结果时分开讨论,因为一级是一步运算,而二三级是两步运算
改造后不用判断是一级难度还是二三级难度了,可以共有一个代码来完成,提高了代码的效率
4.3改进大作业总结
- 这次的改进大作业,因为一直拖着,到了最后一天才在匆匆忙忙的赶,匆匆忙忙的交了上去,在交之前bug超多的,都还没来得及改完。再也不这么匆忙了,真的是作业不能一直拖着
- 这次在测试数据时,用了字符进去测试就崩了,所以我把等级等之类的数据改为了字符型,这样输入字符型的数据时就不会崩掉了
- 在构造式子时,愣了一下,然后根据老师的推荐去看了曾俊伟同学的博客,就有了些思路,也调用了itoa这个函数然后用strcat把它们连接起来
- 第二个函数,判断是否合法,如果不合法就重构一个,然后就调用了stdilb.h里的清屏函数让不合法的式子被清掉
- 第三个函数里,一开始测试第一级难度数据时答案是错的,最后一个数据总是进不去,后来发现是exp这个数组溢出来了,于是把最后等号所在的位置改了,就对了