2019春第十一周作业
第十一周作业
|
-|-
这个作业属于那个课程 | C语言程序设计II
这个作业要求在哪里 | https://edu.cnblogs.com/campus/zswxy/computer-scienceclass4-2018/homework/3203
我在这个课程的目标是 | 学会归递函数和宏的用法
这个作业在那个具体方面帮助我实现目标 | 归递函数的实际使用
参考文献 | C语言程序设计II
一、本周完成的作业
基础作业
编译题
7-1 汉诺塔问题* (10 分)
汉诺塔是一个源于印度古老传说的益智玩具。据说大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘,大梵天命令僧侣把圆盘移到另一根柱子上,并且规定:在小圆盘上不能放大圆盘,每次只能移动一个圆盘。当所有圆盘都移到另一根柱子上时,世界就会毁灭。
请编写程序,输入汉诺塔圆片的数量,输出移动汉诺塔的步骤。
输入格式
圆盘数 起始柱 目的柱 过度柱
输出格式
移动汉诺塔的步骤
每行显示一步操作,具体格式为:
盘片号: 起始柱 -> 目的柱
其中盘片号从 1 开始由小到大顺序编号。
输入样例
3
a c b
输出样例
1: a -> c
2: a -> b
1: c -> b
3: a -> c
1: b -> a
2: b -> c
1: a -> c
1).实验代码
#include<stdio.h>
void hanio(int n,char a,char b,char c);
int main()
{
int n;
char a,b,c;
scanf("%d\n",&n);
scanf("%c %c %c",&a,&b,&c);
hanio(n,a,b,c);
return 0;
}
void hanio(int n,char a,char b,char c){
if(n==1)
printf("%d: %c -> %c\n",n,a,b);
else{
hanio(n-1,a,c,b);
printf("%d: %c -> %c\n",n,a,b);
hanio(n-1,c,b,a);
}
}
2) 设计思路
3).本题调试过程碰到问题及解决办法
a.错误问题截图:
b.问题及其解决办法:
问题:放在pta上显示答案错误,自己在编译器上运行结果也很奇怪
解决办法:调试之后发现起始柱变成了'\n',应该在输入n的时候在后面提前加'\n',改完之后就正确了
4).运行结果截图:
7-2 估值一亿的AI核心代码 (20 分)
以上图片来自新浪微博。
本题要求你实现一个稍微更值钱一点的 AI 英文问答程序,规则是:
无论用户说什么,首先把对方说的话在一行中原样打印出来;
消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
把原文中所有大写英文字母变成小写,除了 I;
把原文中所有独立的 can you、could you 对应地换成 I can、I could—— 这里“独立”是指被空格或标点符号分隔开的单词;
把原文中所有独立的 I 和 me 换成 you;
把原文中所有的问号 ? 换成惊叹号 !;
在一行中输出替换后的句子作为 AI 的回答。
输入格式:
输入首先在第一行给出不超过 10 的正整数 N,随后 N 行,每行给出一句不超过 1000 个字符的、以回车结尾的用户的对话,对话为非空字符串,仅包括字母、数字、空格、可见的半角标点符号。
输出格式:
按题面要求输出,每个 AI 的回答前要加上 AI: 和一个空格。
输入样例:
6
Hello ?
Good to chat with you
can you speak Chinese?
Really?
Could you show me 5
What Is this prime? I,don 't know
输出样例:
Hello ?
AI: hello!
Good to chat with you
AI: good to chat with you
can you speak Chinese?
AI: I can speak chinese!
Really?
AI: really!
Could you show me 5
AI: I could show you 5
What Is this prime? I,don 't know
AI: what Is this prime! you,don't know
1).实验代码
#include<stdio.h>
#include<string.h>
void AI1(char *p);
void AI2(char *p);
void AI3(char *str1);
void deblank(char *p);
int main()
{
int n,i;
scanf("%d\n",&n);
for(i=0;i<n;i++){
char a[1001];
gets(a);
puts(a);
AI1(a);
deblank(a);
AI2(a);
printf("AI: ");
AI3(a);
}
return 0;
}
void AI1(char *p){ //初步的转换,大写改小写,?改!
int n,i;
char c;
n=strlen(p);
for(i=0;i<n;i++){
if(p[i]>='A'&&p[i]<='Z'&&p[i]!='I'){
p[i]=p[i]+32;
}
if(p[i]=='?'){
p[i]='!';
}
}
}
void deblank(char *p){ //大于1个空格变成1个空格
int n,i,j=0;
n=strlen(p);
for(i=0;i<n;i++){
if(p[i]==' '){
p[j++]=p[i];
while(p[++i]==' ');
}
p[j++]=p[i];
}
p[j]='\0';
}
void AI2(char *p){ //进一步删除多余空格
int n,i,j=0;
n=strlen(p);
for(i=0;i<n;i++){
if(p[i]==' '&&i==0){
continue;
}
if(p[i]==' '&&p[i+1]>122){
continue;
}
if(p[i]==' '&&p[i+1]<97&&p[i+1]!='I'&&p[i+1]!='0'&&p[i+1]!='1'&&p[i+1]!='2'&&p[i+1]!='3'&&p[i+1]!='4'&&p[i+1]!='5'&&p[i+1]!='6'&&p[i+1]!='7'&&p[i+1]!='8'&&p[i+1]!='9'){
continue;
}
p[j++]=p[i];
}
p[j]='\0';
}
void AI3(char *str1){
int i=0,b,y;
while(str1[i]!='\0'){
/*判断是否为can you*/
if(str1[i]=='c'&&str1[i+1]=='a'&&str1[i+2]=='n'&&str1[i+3]==' '&&str1[i+4]=='y'&&str1[i+5]=='o'&&str1[i+6]=='u'){
if(((str1[i-1]<'a'||str1[i-1]>'z')&&(str1[i-1]<'A'||str1[i-1]>'Z'))&&((str1[i+7]<'a'||str1[i+7]>'z')&&(str1[i+7]<'A'||str1[i+7]>'Z'))){
str1[i]='I'; /*判断can you是否独立(“独立”是指被空格或标点符号分隔开的单词)*/
str1[i+1]=' ';
str1[i+2]='c';
str1[i+3]='a';
str1[i+4]='n';
str1[i+5]='8';
str1[i+6]='8';
i+=7; /*减少判断量,从can you后的字符继续判断*/
continue;
}
}
/*判断是否为could you*/
if(str1[i]=='c'&&str1[i+1]=='o'&&str1[i+2]=='u'&&str1[i+3]=='l'&&str1[i+4]=='d'&&str1[i+5]==' '&&str1[i+6]=='y'&&str1[i+7]=='o'&&str1[i+8]=='u'){
if(((str1[i-1]<'a'||str1[i-1]>'z')&&(str1[i-1]<'A'||str1[i-1]>'Z'))&&((str1[i+9]<'a'||str1[i+9]>'z')&&(str1[i+9]<'A'||str1[i+9]>'Z'))){
str1[i]='I'; /*判断could you是否独立(“独立”是指被空格或标点符号分隔开的单词)*/
str1[i+1]=' ';
str1[i+2]='c';
str1[i+3]='o';
str1[i+4]='u';
str1[i+5]='l';
str1[i+6]='d';
str1[i+7]='8';
str1[i+8]='8';
i+=7; /*减少判断量,从could you后的字符继续判断*/
continue;
}
}
/*判断I是否独立(“独立”是指被空格或标点符号分隔开的单词)*/
if(str1[i]=='I'&&((str1[i-1]<'a'||str1[i-1]>'z')&&(str1[i-1]<'A'||str1[i-1]>'Z'))&&((str1[i+1]<'a'||str1[i+1]>'z')&&(str1[i+1]<'A'||str1[i+1]>'Z'))){
str1[i]='7';
}
/*判断me是否独立(“独立”是指被空格或标点符号分隔开的单词)*/
if((str1[i]=='m'&&str1[i+1]=='e')&&((str1[i-1]<'a'||str1[i-1]>'z')&&(str1[i-1]<'A'||str1[i-1]>'Z'))&&((str1[i+2]<'a'||str1[i+2]>'z')&&(str1[i+2]<'A'||str1[i+2]>'Z'))){
str1[i]='5';
str1[i+1]='6';
i++;
}
i++;
}
/*输出改变后的字符串,'8'转义为空,('5''6')转义为you,'7'转义为you*/
y=strlen(str1);
for(i=0;i<y;i++){
if(str1[i]=='8')
continue;
else if(str1[i]=='5'&&str1[i+1]=='6'){
printf("you");
i++;
continue;
}
else if(str1[i]=='7'){
printf("you");
}
else
printf("%c",str1[i]);
}
printf("\n");
}
2) 设计思路
3).本题调试过程碰到问题及解决办法
a.错误问题截图:
b.问题及其解决办法:
问题:出现了各种奇怪的错误
解决办法:我的思路是用几个自定义函数来处理字符串,各种错误都出现过,总算是把大小写转换和?转换!,还有多个空格变成一个空格,之后是首末位空格消除,以及标点符号前的空格消除(标点符号指非字母和数字以及空格的字符),但是在最后的字符串的部分替换卡了一天,从5/8的晚上10点卡到5/9的晚上10点
最后群里发了一份参考作业,我从他的代码找到了我所需要的那一部分直接改成了我最后需要的函数(所以改成AI3函数的时候没有大改他的代码),感谢这位博主,这作业难度对我来说还是有点大的,
4).运行结果截图:
挑战作业
7-3 ***八皇后问题 (20 分)
在国际象棋中,皇后是最厉害的棋子,可以横走、直走,还可以斜走。棋手马克斯·贝瑟尔 1848 年提出著名的八皇后问题:即在 8 × 8 的棋盘上摆放八个皇后,使其不能互相攻击 —— 即任意两个皇后都不能处于同一行、同一列或同一条斜线上。
现在我们把棋盘扩展到 n × n 的棋盘上摆放 n 个皇后,请问该怎么摆?请编写程序,输入正整数 n,输出全部摆法(棋盘格子空白处显示句点“.”,皇后处显示字母“Q”,每两格之间空一格)。
输入格式
正整数 n (0 < n ≤ 12)
输出格式
若问题有解,则输出全部摆法(两种摆法之间空一行),否则输出 None。
要求:试探的顺序逐行从左往右的顺序进行,请参看输出样例2。
输入样例1
3
输出样例1
None
输入样例2
6
输出样例2
. Q . . . .
. . . Q . .
. . . . . Q
Q . . . . .
. . Q . . .
. . . . Q .
. . Q . . .
. . . . . Q
. Q . . . .
. . . . Q .
Q . . . . .
. . . Q . .
. . . Q . .
Q . . . . .
. . . . Q .
. Q . . . .
. . . . . Q
. . Q . . .
. . . . Q .
. . Q . . .
Q . . . . .
. . . . . Q
. . . Q . .
. Q . . . .
1).实验代码
#include<stdio.h>
#include<string.h>
void queen(int i,int j); //归递函数
int check(int i,int j); //判断能否摆放的函数
int queennumber=8;
int chess[12][12];
int cas=0;
int n;
int main()
{
scanf("%d",&n);
queen(0,0);
if(cas==0){
printf("None");
}
return 0;
}
void queen(int i,int j){
int x,y;
if(j>=n){
return ;
}
if(check(i,j)==1){//如果能放
chess[i][j]=1;//放皇后
if(i==n-1){//如果是最后一行,记录情况
for(y=0;y<n;y++){
for(x=0;x<n;x++){
if(x==n-1&&chess[y][x]==1){
printf("Q");
}
if(x==n-1&&chess[y][x]==0){
printf(".");
}
if(x!=n-1&&chess[y][x]==1){
printf("Q ");
}
if(x!=n-1&&chess[y][x]==0){
printf(". ");
}
}
printf("\n");
}
cas++;
printf("\n");
}
else{
queen(i+1,0);//不是最后一行就分析下一行
}
}
chess[i][j]=0;//如果此位置不能放,就置空(0),判断旁边的格子。
//如果此位置能放,走到这里就意味着上面的代码全部执行了,把皇后拿走(置零),再讨论其他情况,拿旁边位置试探。
queen(i,j+1);
}
int check(int i,int j){
int k;
for(k=0;k<n;k++){
if(chess[i][k]==1) return 0;//0=不能放
}
for(k=0;k<n;k++){
if(chess[k][j]==1) return 0;
}
for(k=-n;k<=n;k++){//两对角线
if(i+k>=0&&i+k<n&&j+k>=0&&j+k<n)//从左上到右下对角线
if(chess[i+k][j+k]==1) return 0;
if(i-k>=0&&i-k<n&&j+k>=0&&j+k<n)//从左下到右上对角线
if(chess[i-k][j+k]==1) return 0;
}
return 1;
}
2) 设计思路
实话说我没有明确的思路,在八皇后问题 递归实现 C语言 超详细 思路 基础的代码的基础上进行修改才能做出来,但是pta上是错误的,我很困惑,本来就对这道题目感到迷茫,这下子更加懵逼了,理论上不会出现错误的反而出现了错误,调试我也看不出错误.
3).本题调试过程碰到问题及解决办法
a.错误问题截图:
b.问题及其解决办法:
问题:很奇怪的结果
解决办法:未解决,我借鉴了八皇后问题 递归实现 C语言 超详细 思路 基础的代码,在此基础上进行做题,
我运行结果是
应该是没有错的,但是pta却不是这样,对于这种很复杂的题目,我觉得pta应该把测试点告诉我们,只能看到个别答案正确很难进行调试,自己完全不知道哪里出现错误,什么情况下又是对的,两眼一抹黑.
4).运行结果截图:
无正确截图
预习作业
第十二周的教学内容是:第十一章 指针进阶
请大家查阅资料,思考如下问题:
请举实例解释以下几个概念:数组指针,指针数组,指针函数,函数指针,二级指针,单向链表。(无实例不给分)
请用自己的理解回答。如果有引用他人的文字,请一定要标出出处(使用Markdown的链接方式)。
答:
数组指针,指针数组:
int *p[5];
int (*p)[5];
数组指针的意思即为通过指针引用数组,p先和结合,说明了p是一个指针变量,指向一个大小为5的数组。所以,int (p)[5]即为一个数组指针
指针数组的意思是一个数组的元素均为指针类型数据,称为指针数组。所以, int *p[5]即为一个指针数组
参考出处详解C语言中的数组指针与指针数组
指针函数,函数指针:
函数指针是指向函数的指针变量,即函数指针本身首先应是指针变量.定义格式例如int (*pfun)(int, int);
指针函数是指返回值是指针的函数,即本质是一个函数.定义格式例如int *pfun(int, int);
参考出处C语言基础知识:函数指针&指针函数(定义格式、作用及用法说明)
二级指针:
多级指针就是指针的指针的指针,即指向指针的指针,定义格式例如int **p;就是一个二级指针
参考出处多级指针(二级指针),C语言多级指针的用法详解
单向链表:
链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用。
初学链表,一般从单向链表开始
--->NULL
head
参考出处c语言链表详解(超详细)
二、学习进度条
周/日期 | 这周所花的时间 | 代码行 | 学到的知识点简介 | 目前比较迷惑的问题 |
---|---|---|---|---|
3/15-3/22 | 15小时 | 350左右 | 学会处理数组的数据 | 对于指针还有很多不理解 |
3/22-3/29 | 12小时 | 300左右 | 学会使用字符串 | 对于指针还是有很多不理解 |
3/29-4/5 | 12小时 | 300左右 | 学会使用指针 | 对于指针的用法还有不少不清楚的地方 |
4/5-4/12 | 15小时 | 450左右 | 学会指针搭配数组使用 | 编译器开始出现莫名其妙的问题,以及新的函数使用不熟练 |
4/12-4/19 | 15小时 | 550左右 | 学会动态内存分配和一些新的函数 | 还是新的函数的使用问题 |
4/19-4/26 | 12小时 | 450左右 | 学会结构的使用方法 | 利用结构体能更好的处理一些问题 |
4/26-5/3 | 4小时 | 200左右 | 对结构的进一步学习 | 对结构指针还有许多的不理解 |
5/3-5/10 | 15小时 | 900左右 | 归递函数和宏 | 归递函数的运行还是有很多不明白的地方 |
三、学习感悟
这周学习了归递函数和宏,归递函数的运行方式还有些不是很清楚的地方,题目难度有点大,光基础题第二题就卡了我好久,对于替换字符串找了很多方法,自己也想了很多,但是都无法很好的完成题目要求,不过pta又开始没有告诉你测试点了,看着一会一部分正确,过一会用改过的代码又是另外几个正确,原来正确的反而错了,很懵逼,调试都不是很明白应该对哪一部分动手,从头找又很难找得到,实际自己的答案也没错,但是pta上面显示错的,更不知所措了可能是我自己找bug的能力太弱,要继续学习,累计经验,可能才能够不像现在一样懵逼.