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这个数组溢出来了,于是把最后等号所在的位置改了,就对了
posted @ 2018-12-17 22:16  Hyjjing  阅读(249)  评论(2编辑  收藏  举报