2019春第十一周作业
这个作业属于哪个课程 | C语言程序设计2 |
这个作业要求在哪里 | 2019年春季学期第十一周作业 |
我在这个课程的目标是 | 我希望能够通过学习C语言的知识,能够对相对复杂的问题,合理定义程序的多函数结构;能使用递归函数进行编程;掌握宏的基本用法;掌握编译预处理的概念。 |
这个作业在哪个具体方面帮助我实现目标 | 这个作业让我对相对复杂的问题,能够合理定义程序的多函数结构;可以使用递归函数进行编程;掌握了宏的基本用法;掌握了编译预处理的概念。 |
参考文献 | strncmp函数;指针数组;数组指针;数组指针与指针数组的区别;函数指针;指针函数;函数指针和指针函数用法和区别;多级指针(二级指针),C语言多级指针的用法详解;;;; |
基础作业
题目
汉诺塔问题
汉诺塔是一个源于印度古老传说的益智玩具。据说大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘,大梵天命令僧侣把圆盘移到另一根柱子上,并且规定:在小圆盘上不能放大圆盘,每次只能移动一个圆盘。当所有圆盘都移到另一根柱子上时,世界就会毁灭。
请编写程序,输入汉诺塔圆片的数量,输出移动汉诺塔的步骤。
输入格式
圆盘数 起始柱 目的柱 过度柱
输出格式2
移动汉诺塔的步骤
每行显示一步操作,具体格式为:
盘片号: 起始柱 -> 目的柱
其中盘片号从 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 Hanoi(int n,char s,char g,char c);
int main()
{
int n;
char start,goal,change;
scanf("%d\n",&n);
scanf("%c %c %c",&start,&goal,&change);
Hanoi(n,start,goal,change);
return 0;
}
void Hanoi(int n,char s,char g,char c)
{
if (n==1)
{
printf("%d: %c -> %c\n",n,s,g);
}
else
{
Hanoi(n-1,s,c,g);
printf("%d: %c -> %c\n",n,s,g);
Hanoi(n-1,c,g,s);
}
}
2)设计思路
3)本题调试过程中碰到的问题及其解决办法
1.if-else语句的附属语句没有缩进,答案错误;
解决办法:改正格式。
2.格式错误,输出没换行,箭头前后没空格;
解决办法:按要求改格式。
4)运行截图
题目
估值一亿的AI核心代码
以上图片来自新浪微博。
本题要求你实现一个稍微更值钱一点的 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)实验代码
这个代码我在dev-c++中可以正确运行,但是提交到pta上有第1、3、4个测试点答案错误,我也找不出到底这三个点在哪
#include<stdio.h>
#include<string.h>
void da_xiao_xie(char *s);
int chara(char c) //判断是否为字母
{
return (c >= 'A'&&c <= 'Z') || (c <= 'z'&&c >= 'a');
}
int numb(char c) //判断是否为数字
{
return (c >= '0'&&c <= '9');
}
int main()
{
int n,i,j,l,k;
scanf("%d\n",&n);
char sent[10001],sent1[10001];
while(n--)
{
gets(sent); //输入字符串
printf("%s\nAI: ",sent); //原样输出一次,且输出AI
l=strlen(sent); //算出字符串的长度
for(j=0;sent[j]==' ';j++); //从句首开始计算
for(l;sent[l]==' ';l--); //从句末开始计算
sent[l+1]='\0'; //从j到l就是即除去首尾空格的句子
strcpy(sent1,sent+j);
strcpy(sent,sent1);
for(j=0;sent[j]!='\0';j++)
{
for(int k=j;sent1[k]!='\0';k++)
{
if(sent1[k]==' '&&!chara(sent1[k+1])&&!numb(sent1[k+1])) //消去多余空格
strcpy(sent+j,sent1+k+1);
else {
strcpy(sent1,sent);
break;
}
}
}
da_xiao_xie(sent); // 大写改为小写,?改为!
strcpy(sent1,sent);
l=strlen(sent);
char str[4]="you";
for(i=0;i<l;i++) //把I和me改为you
{
if(sent[i]=='I'&&!chara(sent[i+1])&&!numb(sent[i+1])&&!chara(sent[i-1])&&!numb(sent[i-1]))
{
strcpy(sent+i,str);
strcat(sent,sent1+i+1);
strcpy(sent1,sent);
}
if(sent[i]=='m'&&sent[i+1]=='e'&&!chara(sent[i-1])&&!numb(sent[i-1])&&!chara(sent[i+2])&&!numb(sent[i+2]))
{
strcpy(sent+i,str);
strcat(sent,sent1+i+2);
strcpy(sent1,sent);
}
}
l=strlen(sent);
char canyou[8]="can you",couldyou[10]="could you";
char canyou1[6]="I can",couldyou1[8]="I could";
for(i=0;i<l;i++) //改变can you和could you
{
if(!strncmp(&sent[i],canyou,7)&&!chara(sent[i-1])&&!numb(sent[i-1])&&!chara(sent[i+7])&&!numb(sent[i+7]))
{ //改变can you
strcpy(sent+i,canyou1);
strcat(sent,sent1+i+7);
strcpy(sent1,sent);
}
if(!strncmp(&sent[i],couldyou,9)&&!chara(sent[i-1])&&!numb(sent[i-1])&&!chara(sent[i+9])&&!numb(sent[i+9]))
{ //改could you
strcpy(sent+i,couldyou1);
strcat(sent,sent1+i+9);
strcpy(sent1,sent);
}
}
printf("%s\n",sent);
}
return 0;
}
void da_xiao_xie(char *s)
{
for(int i=0;s[i]!='\0';i++)
{
if(s[i] >= 'A'&&s[i] <= 'Z'&&s[i]!='I')
s[i]=s[i]+32;
if(s[i]=='?')
s[i]='!';
}
}
2)设计思路
3)本题调试过程中碰到的问题及其解决办法
1.PTA提交答案错误;
4)运行截图
提交的是dev-c++上的运行截图
预习作业
1.数组指针
首先“数组指针”本质是指针,是指向一维数组的指针,定义方法,如:int (*p)[n]😭)的优先级更高,表示一个名为p的指针,指向一个整型的、长度为n的数组。如果要把一个二维数组赋给这样的指针,可以这样,如:int b[2][4]; int (*p)[4]; (因为要将二维数组b赋给p,而二维数组b的有2行,每一行的长度是4,所以数组指针p的长度定为4)定义完之后赋值方法为 p=b; (将数组b的首地址b[0]或者b[0][0]赋给p),此时p指向b[0][0],若执行p++; 则p指向b[1][0]。
2.指针数组
指针数组的本质是数组,这个数组的元素全都是指针。定义方式如:int *p[n]; p是数组名,int是数组的类型,n是数组长度,则p[0]、p[1]、p[2]等都表示这个数组的一个指针,p++; 表示p数组指向下一个数组元素。如果a是个一维数组,要将a首地址赋给p,则p=a是错误的方式,可以写成*p=a; 此时*p表示指针数组第一个元素的值,a的首地址的值。如果要把二维数组赋给一个指针数组,则在定义之后如int c[3][5]; int *p[3]; for(i=0;i<3;i++) p[i]=c[i]; 二维指针数组的各个元素的表示方法:*(*(p+i))和**(p+i)表示第‘i+1’行的第一个元素,*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]和p[i][j]都表示第i行的第j个元素。
3.指针函数
指针函数本质是函数,它的返回值是个指针。它的声明形式:类型名 *函数名(参数表),如,int *fact(cahr c,char op);会返回一个类型为int的指针(地址值),而在主函数中用来接收该返回值的也必须是相同类型的指针变量。
4.函数指针
函数指针本质是指针变量,它指向这个函数。函数指针指向的地址就是这个函数的入口地址。定义:类型说明符 (*函数名) (参数) 如,int (*fact)(int a,int b);赋值方式:如果有一个名为fun的函数,将fun的地址赋给fact,有fact=fun;或fact=&fun;两种方法。调用函数指针:假设c为变量,有c=(*fact)(参数1,参数2)或者c=fact(参数1,参数2)两种方式。
5.二级指针
二级指针就是指向指针的指针,例如int a; int *s; int **p; s=&a; **p=&s; 即一级指针s指向变量a,二级指针p指向一级指针s。
6.单向链接
链表是一种动态存储分布的数据结构,单向链表是链表的一种,是一种其结构类型内的next分量又是该结构类型的指针的数据结构。如:struct fun{ int a; int b; char c; struct fun*next;};
5)预习中存在的疑惑
1.单向链表中每个next分量都一样吗;
2.构造单向链表除了结构的递归定义法之外还有别的吗;
3.二级指针怎么用。
结对编程
本周题目难度太大,在写第二题的时候和搭档讨论怎么把每个细节处理好,互相解决对方产生的问题,虽然写完之后在PTA上没有完全正确,但是在我们在dev-c++上都能够正确运行。结对编程的优点是在自己找不出自己代码错在哪里时和搭档互相找错的效率更高,缺点是我们虽然思路相同但是在写代码时的习惯不同,在看搭档的代码时很费力。
学习感悟
本周学习了递归函数并用其进行编程;学习了宏的基本用法;理解编译预处理的概念。以前总是见到使用宏的情况,但是没去正式了解,这次真正知道了宏的概念,还有编译预处理也经常听到但没没去查过,这周也知道了,真正感觉到对这门课的知识越学越深了,也越来越难了。这周的题目大部分都很难,第二题虽然一开始看的时候,觉得不难,思路很明确,但是难在对每个细节的实现上,真的是绞尽脑汁的感觉,这一个题写了两天,期间不断的改,不断换方法,也有在网上查看别人怎么写的,可以别人写的都和我自己的方式不同,我还是想把自己的方法写出来,但是最后在PTA上也只是部分正确,不是很满意。
学习进度
时间进度条
日期 | 这周所花时间 | 代码行 | 学到的知识点 | 问题 |
---|---|---|---|---|
3.15-3.22 | 10个小时 | 130 | 选择排序,冒泡排序,二维数组 | 输出完一行数后会自动换行吗 |
3.22-3.29 | 13个小时 | 200 | 字符型数组的简单使用,字符数组与字符串的区别,二维字符数组的输入及简单判断,对指针的初步了解 | 指针怎样在自定义函数中返回多个值 |
3.29-4.05 | 8个小时 | 100 | 变量、内存单元和地址之间的关系;如何定义指针变量,怎样使用指针变量,怎样进行指针变量的初始化;指针变量的基本运算;理解指针作为函数参数的作用;使用指针实现函数调用返回多个值 | 在自定义函数中将数值赋给指针所指向的变量,要在主函数中输出该值,输出参数是指针,为什么不可以。 |
4.05-4.12 | 12个小时 | 150 | 数组名作为函数参数的用法,指针、数组和地址之间的关系,指针和数组可以实现相同的操作,strcpy函数的深层理解,for循环与while循环在内存层面的区别 | 对指针的运用不熟练 |
4.12-4.19 | 8个小时 | 120行 | 常用字符串函数,如何使用指针操作字符串,动态内存分配。 | 两个字符串的交换为什么不能通过赋值实现 |
4.19-4.26 | 10个小时 | 120行 | 使用结构变量与结构数组进行编程,利用结构指针进行操作,并应用于函数传递 | 有些题目不用结构也能解决,在二者都能解决的情况下,使用结构解决问题有什么优势 |
5.5-5.10 | 25个小时 | 200行 | 对相对复杂的问题,合理定义程序的多函数结构;使用递归函数进行编程;宏的基本用法;编译预处理的概念 | 对递归函数的实现步骤总是很模糊 |
时间 | 累计代码行数 | 累计博客字数 |
---|---|---|
第一周 | 80 | 0 |
第二周 | 150 | 400 |
第三周 | 250 | 1600 |
第四周 | 380 | 3200 |
第五周 | 580 | 5110 |
第六周 | 680 | 8110 |
第七周 | 830 | 10910 |
第八周 | 950 | 13510 |
第九周 | 1070 | 17210 |
第十一周 | 1270 | 20745 |