1.本章学习总结
1.1 思维导图
1.2 本章学习体会及代码量学习体会
1.2.1 学习体会
- 学习体会:这两周的学习进度“咻”一下加快,总的来说还是比较吃力的,从数组过渡到指针再过渡到文件,整体的学习节奏都比之前快上很多。新的概念与新的函数(文件里概念性的东西有点多)等需要静下来消化的东西变得更加多了。发现一个问题,从最基本的概念上还是不够熟练与清晰。具体表现在——课堂派的复习作业做起来有点像预习作业……处于一个会与不会,可能会大概会的一个模糊的区间范围内,这也导致了一种上课时的一种“我是谁,我在哪,我在干什么”的状态。对于新内容的接收和学习速度不够,课后也没有及时的巩固,进而导致了一种恶性死循环。趁着博客作业对于指针的内容进行了一个梳理。指针的pta题目还是相对少一些嘛……对于返回多个值的函数,指针能够起到的作用就比较大,在字符串的一些程序编写上,用指针也更加便捷,要学会习惯指针的用法,普及化酱,多学多练吧。qaq
- 该做的事:指针的运用还是比较广泛,不仅在字符串还有后面要学到的链表知识,所以还是要一些代码量,对于一些比较经典的运算方法进行一个分析,方便深入掌握指针的使用。
- 对于老师的建议:qaq 虽然文件对于课设有比较大的帮助,但是直接跳跃讲文件,其中再参杂一些还没有巩固牢靠的指针知识会使本来不那么复杂的文件显得有些遥远和难以接纳(emmmm不知道是不是我自己的感觉……就是:令人头大鸭酱)课堂派里常出现一些需要devc进行调试的题目也常常是“老师已经开启禁止黏贴功能”,建工程因为对指针概念的不够熟悉也变成了老师博客代码的搬运工。希望老师可以救救孩子,平常可以挑一些课堂派上的经典代码进行分析,合理化课堂派的功能,巩固一下指针知识……oxo辛苦老师……
1.2.2 代码累计
2.PTA总分
2.1
2.2 我的总分:
- 总分:110
3.PTA实验作业
3.1 PTA题目1
7-2 说反话-加强版
给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。
3.1.1 算法分析
定义数组 a[500001];
定义 flag=0,len 字符串长度i,j,ret,count=0 单词长度
gets(a);
len=strlen(a);
for i=len-1 To 0 //倒序判断
if a[i]!=' '
ret=1;count++;
end if
if a[i]=' '&&ret=1 //一个单词结束
if flag=1 已输出过单词 先空格
end if
for j=i+1 To i+count
逐个输出字符
flag=1;
end for
全部初始化
end if
if i=0&&ret=1 //第一个单词单独判断
同理输出
end if
end for
3.1.2 代码截图
3.1.4 PTA提交列表及说明
#include<stdio.h>
#include<string.h>
int main()
{
char a[100][100];
int i,j;
int flag=0;
char sentense[10000];
gets(sentense);
int m=0,n=0;
for(i=0;sentense[i];i++)
{
if(sentense[i]!=' ')
{
a[m][n]=sentense[i];
m++; //单词长度累加
}
if(m!=0&&sentense[i]==' ')
{
a[m][n]='\0';
n++;m=0; //有单词累计,遇到空格
}
}
for(i=n;i>0;i--)
{
for(j=0;a[j][i];j++)
{
printf("%c",a[j][i]);flag=1;
}
if(flag==1) printf(" ");
}
for(j=0;a[j][0];j++)
printf("%c",a[j][i]);
return 0;
}
- Q:运行时间超长,导致最后一个测试点过不去
- A:以上是之前第一次写这道题目时的代码,利用二维数组对于出现的单词进行标号统计,最后倒序输出。(我jio得这样比较直观 小声bb)这种情况会出现最后一个测试点过不去,运行时间超长。先进行总统计,再输出。所以就采用倒序判断,边判断边输出,节省了运行时间。第二种方法比较通用,但是个人是觉得第一种方法灵活度更高,顺便还可以指定输出指定位置的单词。但这道题对于运行时间的要求比较高,因此还是要采用便判断边输出的方式。
4.大作业
4.1.改造函数介绍
函数1 computerExp 随机生成表达式
int computerExp(char grade,int *gradeNum)
定义i,j=0,step,n //控制生成的随即位数&计算步数
定义exp[30], op[5]={'+','-','*','/'}; //枚举
switch(grade)
A:一位两步
B:两位一步
C:三位一步
for j=0 To step-1
for j To (i+1)*n-1
exp[j]=rand()%10+'0'; //生成随机数转字符录入
end for
exp[j]=op[rand()%*gradeNum]; //对应加减/加减乘除
end for;
exp[i]='\0';
输出表达式
函数2 Calculation 运算
定义 former latter i,j,pos;
for j=0 To j<n-1
former=10*former+exp[pos]-'0'; //转数字
pos++;
end for;
for i=0 To i<step-1
for j=0;j<n-1
latter=10*latter+exp[pos]-'0'; //转数字
pos++;
end for
end for
switch op //运算
case +:
case -:
case *:
case /: if latter=0,跳过此题
return latter;
4.3 与原有函数代码比较
等级选择
former
void Calculation(char x)
{
switch(x)
{
case 'A':
while(correctNum<10)//如果想一直答下去,就把它修改成while(1),然后输入6666照样可以退出循环w
{
printf("当前挑战等级:青铜\n");
printf("当前答对题数:%d\n",correctNum);
printf("tips:输入6666提前结束游戏\n\n\n");
x = rand() % 10; /* generate 1-digit random number */
y = rand() % 10; /* generate another 1-digit random number */
kind=rand()%4;
randomOperation(kind,x,y);
}
break;
case 'B':
while(correctNum<10)
{
printf("当前挑战等级:钻石\n");
printf("当前答对题数:%d\n",correctNum);
printf("tips:输入6666提前结束游戏\n\n\n");
x = rand() % 90+10; /* generate 1-digit random number */
y = rand() % 90+10; /* generate another 1-digit random number */
kind=rand()%2;
randomOperation(kind,x,y);
}
break;
case 'C':
while(correctNum<10)
{
printf("当前挑战等级:王者\n");
printf("当前答对题数:%d\n",correctNum);
printf("tips:输入6666提前结束游戏\n\n\n");
x = rand() % 900+100; /* generate 1-digit random number */
y = rand() % 900+100; /* generate another 1-digit random number */
kind=rand()%2;//decide to minus or plus
randomOperation(kind,x,y);
}
break;
}
}
latter
void Choice(char x,int *correctNum,int *incorrectNum,int *gradeNum)//选择
{
int answer,end;
while(*correctNum<10)//如果想一直答下去,就把它修改成while(1),然后添加一个跳出循环条件就好啦w
{
again:
switch(x)
{
case 'A':printf("当前挑战等级:青铜\n");*gradeNum=4;break;
case 'B':printf("当前挑战等级:钻石\n");*gradeNum=2;break;
case 'C':printf("当前挑战等级:王者\n");*gradeNum=2;break;
}
printf("当前答对题数:%d\n",*correctNum);
printf("tips:输入任意大于6666可直接结束游戏\n\n\n");
answer=computerExp(x,gradeNum);
if(answer==5555)//除数为0
{
fflush(stdin);//清空输入缓冲区
system("cls");//empty
goto again;
}
end=Judgement(answer,correctNum,incorrectNum);
if(end)break;
Pause();
}
- former:函数重复的内容比较多,函数的内容比较单一。
- latter:因为表达式是另外输出,所以简化了这一块的代码,其他的部分放在computerExp中完成,直接生成一串字符。
计算
former
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int kind;//choose to minus or plus etc.
int flag=0;//控制是否输出正确提示语
int END=0;//控制跳出循环
int Num=0;//sum
char grade;//choose one to play
int wrongTimes=0;//the number of wrong times
int correctNum=0;//the number of correct times
int incorrectNum=0;//the number of incorrect times
int x,y;
void Calculation(char x);
void Menu(void) ;
void plus(int x,int y);
void divide(int x,int y);
void minus(int x,int y);
void multiply(int x,int y);
void correctMessage( void );
void incorrectMessage( void );
int randomOperation(int kind,int x,int y);
void Ending(void);//ending message
latter
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void Pause(void);
char Menu(void) ;
int Calculation(char exp[],int step,int n);
int Judgement(int answer,int *correctNum,int *incorrectNum);
int computerExp(char grade,int *gradeNum);
void Ending(int *correctNum,int *incorrectNum);//ending message
void correctMessage( int *correctNum );
void incorrectMessage(int *wrongTimes,int *incorrectNum,int answer);
void Choice(char x,int *correctNum,int *incorrectNum,int *gradeNum);
int Calculation(char exp[],int step,int n)
{
int former=0,latter=0;
int i,j,pos=0;
for(j=0;j<n-1;j++)
{
former=10*former+exp[pos]-'0';
pos++;
}
pos++; //jump the op position
for(i=0;i<step-1;i++)
{
for(j=0;j<n-1;j++)
{
latter=10*latter+exp[pos]-'0';//change into number
pos++;
}
switch(exp[i*n+n-1])
{
case '+':former+=latter;latter=0,pos++;break;
case '-':former-=latter;latter=0;pos++;break;
case '*':former*=latter;latter=0;pos++;break;
case '/':if(latter==0) return former=5555;
former/=latter;latter=0;pos++;break;
}
}
return former;
}
- former:简单抛个头文件。先前的代码只是生成两个随机数,分+-*/模块分别去计算,导致代码的赘余,功能的重复。之前还是用了比较多的void类型函数
- latter:对计算上进行了一个优化,利用switch将整个计算封装在一起,使代码简化很多。
4.4 改进大作业总结
- qaq!!!总算写到这里了。这次的大作业还是进行了比较大规模的改动。先后看错好几次要求……刚开始还是基于上一次的代码,进行修改,只是简单地把全局变量修改成指针。后来发现题目要求是将表达式储存到字符数组中,再整串输出。因此这边还是进行了一个比较大的改动。刚开始的代码大概长这样。
switch (grade)//等级
{
case 'A':n=1;break;
case 'B':n=2;break;
case 'C':n=3;break;
}
for(i=0; i<3*n; i++)num[i]=rand()%10; //生成随机数
for(i=0; i<n; i++)x=10*x+num[i]; //生成第一个随机数
for(i=n; i<2*n; i++)y=10*y+num[i]; //生成第二个随机数
for(i=2*n; i<3*n; i++)z=10*z+num[i]; //生成第三个随机数
for(i=0;i<3*n+3;i++) //录入字符数组
{
if (i==n)
{
exp[i]=randomOp();
if(exp[i]=='/'&&y==0)
{
do
{
for(i=n;i<2*n;i++)
{
num[i]=rand()%10;
y=10*y+num[i];
}
}while(y);
}
else if(exp[i]=='*'||exp[i]=='/')
{
mark1=1;
}
}
else if(i==2*n+1)
{
exp[i]=randomOp();
if(exp[i]=='/'&&z==0)
{
do
{
for(i=2*n;i<3*n;i++)
{
num[i]=rand()%10;
z=10*z+num[i];
}
}while(!z);
}
else if(exp[i]=='*'||exp[i]=='/')
{
mark2=1;
}
}
else if (i==3*n+2)exp[i]='=';
else
{
exp[i]=num[j]+'0';
j++;
}
}
exp[i]='\0';//加上终止符
- 还是在迎合题目要求,进行固定步数的计算,但是这种比较固定的模式,就比较好考虑运算优先级,这串代码改动上意义不大。不过在刚写完的时候还是比较满意的。固定位置的固定符号,整个程序都比较固化,没什么弹性。
- 后来是老师评论了我的博客的时候,我才开始考虑,计算与表达式分离的好处,在这边请教了老师。然后就从表达式的随机生成开始进行修改,在这方面就相对灵活些。写函数我会倾向于先写一个最简单的程序,验证程序是否能正常得出结果,便于调试——因为大作业里面的函数已经涉及到的东西还是比较多。然后就写出了一个可以自定义生成随即表达式的程序。大概长这样
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
if (grade=='A')gradeNum=4;else gradeNum=2;
int i,step,j=0,n;
printf("你想挑战的位数:");scanf("%d",&n);n++;
printf("你想挑战的步数:");scanf("%d",&step);step++;
char exp[30];
char op[5]={'+','-','*','/'};
for(i=0;i<step;i++)
{
for(j;j<(i+1)*n-1;j++)
exp[j]=rand()%10+'0';
if(i!=step-1)exp[j]=op[rand()%gradeNum];
else exp[j]='=';j++;
}
exp[j]='\0';
printf("%s",exp);
}
- 这样的写法比之前的写法要灵活些,以后要是想修改条件也比较便利。因为之前判断优先级的时候,是对固定位置的符号进行判断,如果符合条件进行优先运算酱。但是经过这样的改动之后,暂时就没有一个比较可行的方法来进行优先级的比较。如果最近能够找到一个比较合适的方法,我会在博客下面进行补充。
- 所以现在的程序还是比较笨一点。
- 这次的大作业在参数的传递上,还是时常出现问题的。时常出现一级指针二级指针并行的情况。老师推荐去看范华同学的代码qaq!!!但还是比较不容易吸收一些,所以就先按照自己熟悉的字符数组来写,后期会再尝试模仿范华同学的代码,对于指针的运用再加强练习一下。
- 写这次大作业比较大的收获,是已经可以相对熟悉地运用字符数组,然后能够尝试着用一些指针,return语句的灵活运用在处理除数为0的情况时也起到了比较大的作用。嘛。希望在文件版大作业的修改上面可以效率高一点,思考问题考虑通式,思维不定时酱。
- 这次还简化了一些函数,代码量上大概简略了100行酱。