C程序第三次作业
6-1 输出月份英文名
PTA提交列表:
1.设计思路
(1)主要描述题目算法
第一步:将十二个月的名称分别赋值给一维数组指针,定义用于返回的数据类型。
第二步:遍历数组,满足若n在1-12范围则将month第n-1行的首元素的地址赋给一开始定义的数据。
第三步:返回变量的地址值。
2.实验代码
char *getmonth( int n ) {
char *month[12] = {"January","February","March","April","May","June","July","August","September","October","November","December"};
char *pc = '\0';
if(n>0 && n<=12){
pc = *(month+n-1);
}
return pc;
}
3.本题调试过程碰到问题及解决办法
错误点1:* pc未等于' \0 ',导致当输入的月份不为1-12范围内时,则停止工作。
解决方法:在注意到题目中“返回空指针NULL”后,将返回的指针型pc赋初值为'\0'。
错误点2:pc写成等于month+n-1
解决方法:在单步调试时,查看了(month+n-1)的值,加上 * (month+n-1)后结果为正确,然而上课时并没有很注意老师说的这个知识点,所以有一点疑惑,在询问了二班的李伍壹同学后,并观看了老师的ppt并自己手动调试后,最终解决了问题: * (month+n-1)是第n-1行首元素的地址,** (month+n-1) 是第n-1行首元素的值。 李伍壹同学认真的程度真的很值得我去学习,同时自己也需要自我批评,课上一定要高度集中注意力。
6-2 查找星期
PTA提交列表:
1.设计思路
(1)主要描述题目算法
第一步:将一个星期每天的英文分别赋值给一维数组指针,定义一个整型变量,赋初值为-1。
第二步:遍历一维数组,用strmcp函数比较数组中每行元素与输入的字符串是否相同,若相同,则令此时的行数等于一开始定义的整型变量,且跳出循环。
第三步:返回整型变量值。
2.实验代码
int getindex( char *s ) {
int k=-1,i=0;
int *day[7] = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
for(i=0;i<7;i++) {
if(strcmp(*(day+i),s)==0) {
k = i;
break;
}
}
return k;
}
3.本题调试过程碰到问题及解决办法
错误点1:将strcmp((day+i),s)==0直接写成 *(day+i) == *s。
解决方法:在第一题了解了之后,明白 * (day+i) 指的是第i行元素的首元素的地址,而 * s则表示的是首字母的值;且想起数组比较是否相等的话,必须要一个一个字母进行比较,只能用for循环或者是比较strcmp((day+i),s)的值,若为0则相等。
strcmp函数:对两个字符串进行自左至右逐个字符相比,按ASCII值的大小比较,全部相等值则为0,出现不相等的字符,则以第一个不相同的字符比较为准,若前者大于后者,函数值为正整数,反之为负整数。
6-3 计算最长的字符串长度
PTA提交列表:
1.设计思路
(1)主要描述题目算法
第一步:遍历s数组,运用strlen函计算出每行元素的长度。
第二步:在for循环中进行比较,定义int型max,赋初值为0,当行元素的长度大于max,则将长度的值赋给max。
第三步:返回max的值。
(2)流程图
2.实验代码
int max_len( char *s[], int n ) {
int max = 0,i=0,len;
for(i=0;i<n;i++) {
len = strlen(*(s+i));
if(len > max) {
max = len;
}
}
return max;
}
3.本题调试过程碰到问题及解决办法
无
6-4 指定位置输出字符串
PTA提交列表:
1.设计思路
(1)主要描述题目算法
第一步:先遍历s字符数组,找到与ch1相同时s的下标,并将下标值赋给一个整型变量,定义为j。
第二步:在确定下标后,定义一个指针字符temp,将&s[i]赋给temp,后跳出循环。
第三步:从上面的j开始,循环字符数组s,在循环中分情况,若s[i] != ch2,则输出s[i],反之则输出s[i]加换行,且返回temp。
第四步:循环结束后,输出换行及返回temp。
(2)流程图
2.实验代码
/*
char *match( char *s, char ch1, char ch2 ) {
int i,j=strlen(s),k = 0,m=0;
char temp1[j+1];
char temp2[j+1];
for(i=0;s[i] != '\0';i++) {
if(s[i] == ch1) {
j = i;
break;
}
}
for(i=0;s[i] != '\0';i++) {
if(s[i] == ch2) {
k = i;
break;
}
}
if(k==0) {
k = strlen(s);
}
for(i=j;i<=k;i++) {
temp1[m] = s[i];
m++;
}
printf("%s\n",temp1);
m=0;
for(i=j;s[i] != '\0';i++) {
temp2[m] = s[i];
m++;
}
return temp2;
}
*/
char *match( char *s, char ch1, char ch2 ) {
int i,j=strlen(s),k = 0,m=0;
char *temp;
for(i=0;s[i] != '\0';i++) {
if(s[i] == ch1) {
temp = &s[i];
j = i;
break;
}
}
for(i=j;s[i] != '\0';i++) {
if(s[i] != ch2) {
printf("%c",s[i]);
} else {
printf("%c\n",s[i]);
return temp;
}
}
printf("\n");
return temp;
}
3.本题调试过程碰到问题及解决办法
错误点1:在dev中运行正确,却在pta全部答案错误。
解决方法:将temp2字符数组改成指针变量后,则为部分正确,猜测为pta中此题不支持字符数组的形式,最后将temp1舍去,按照满足条件则输出对应单个字符的思路重新构思代码,最后正确。
一道编程题:
#include <stdio.h>
int main ()
{
int m=20,n=970;
//int型变量范围为-32768-32767,int n[10000]是不行的,因为这样定义的数组用的是栈
//内存,系统默认值为最大1Mb,一个int型占4字节这样最大可以申请1024*1024/4=264144
//个,如果考虑到系统自身的占用最大值为25000个。
int *p = (int *)malloc((m*n) *sizeof(int));
int *q = (int *)malloc((m*n) *sizeof(int));//用的是堆内存,只要内存中有那么多的连续空间就可以。
int i=0,j;
for(i=0;i<(m*n);i++) {
p[i] = i+1;
}
for(i=0;i<(m*n);i++) {
for(j = i+1;j<=(m*n);j++) {
if(p[i] !=1&&p[j] != 1) {
if(p[j]%p[i] ==0) {
p[j] = 1;
}
}
}
}
j=0;
for(i=0;i<(m*n);i++) {
if(p[i] != 1) {
printf(" %d",p[i]);
j++;
}
if(j == 5) {
printf("\n");
j=0;
}
}
}
然而上面的代码是存在bug的,当数字过大时,最终系统会一直加载不出来,例:当输入的数字是20970时,最后答案是可以的,然而变成201970时则不可以。而在老师讲授完此课程的时候,自己又将自己的代码进行了一次修改,最后答案可以输出。
#include <stdio.h>
#define N 201
#define M 970
int a[N][M];
int del(int s[N][M],int x) {
int n,m;
for(n=0;n<N;n++) {
for(m=1;m<M;m++) {
if(s[n][m]==0) continue;
if(s[n][m]!=x && (s[n][m]%x)==0) {
s[n][m]=0;
}
}
}
return 0;
}
int main()
{
int n=0,m=0,number=1,i=0;
for(n=0;n<N;n++) {
for(m=0;m<M;m++) {
a[n][m]=number++;
}
}
for(n=0;n<N;n++) {
for(m=1;m<M;m++) {
if(a[n][m]!=0) {
del(a,a[n][m]);
}
}
}
for(n=0;n<N;n++) {
for(m=1;m<M;m++) {
if(a[n][m]!=0) {
printf(" %d",a[n][m]);
i++;
}
if(i==5) {
printf("\n");
i=0;
}
}
}
return 0;
}
6-1 奇数值结点链表
PTA提交列表:
1.设计思路
(1)主要描述题目算法
第一步:在readlist函数中,将输入的值存储在链表里,且用while循环时条件为输入的值不为-1,在while循环内对p进行动态分配内存,切记在完全输入以后,末尾结点的next为空,最后返回链表的头结点。
第二步:在getodd函数中,根据题目要求的条件对链表结点中date的值进行分类判断,将数值为偶数的date存储在一个新的链表中,另将为奇数的存储在一个新的列表中。
第三步:需考虑若最后新建链表有可能为空的情况。
第四步:最后按照要求返回要求链表的头结点。
(2)流程图
2.实验代码
struct ListNode *readlist() {
int number;
struct ListNode *p = NULL,*head = NULL,*tail = NULL;
scanf("%d",&number);
while(number!=-1&&number>0 ) {
p = (struct ListNode*)malloc(sizeof(struct ListNode));
p->data = number;
if(head == NULL) {
head = p;
} else {
tail->next = p;
}
tail = p;
scanf("%d",&number);
}
if(head == NULL) {
return NULL;
}
tail->next = NULL;
return head;
}
struct ListNode *getodd( struct ListNode **L ) {
struct ListNode *p = *L,*head1 = NULL,*r = NULL,*L1 = NULL,*r1 = NULL;
while(p!=NULL&&p->data>0) {
if(p->data%2!=0) {
if(head1 == NULL) {
head1 = p;
} else {
r->next = p;
}
r = p;
} else {
if(L1 ==NULL) {
L1 = p;
} else {
r1->next = p;
}
r1 = p;
}
p = p->next;
}
if(head1==NULL){
return NULL;
} else {
r->next = NULL;
}
if(L1==NULL) {
*L = NULL;
} else {
r1->next = NULL;
*L = L1;
}
return head1;
}
3.本题调试过程碰到问题及解决办法
错误点1:未在readList子函数中加上tail->next = p.
解决方法:在dev中运行没有结果且调试会出错,在多次单步运行后发现若最后不加tail->next = p,最后的p->next不会为空,传下去则会造成getodd函数中的p值在最后仍不为空,最后造成系统的报错。
错误点2:在getodd函数中while的条件写成p->next!=NULL。
解决方法:在单步调试后发现,若写成p->next!=NULL,最后一个结点会不满足while的条件,直接跳过循环,进入下一步,最终导致答案错误。
6-2 学生成绩链表处理
PTA提交列表:
1.设计思路
(1)主要描述题目算法
第一步:在createlist函数中将输入的学号,姓名和分数存储到链表中,while循环的条件为学号不为0,因当学号为0时不需要输入姓名及分数,即结束,因此需明确必须在判断学号不为0的情况下才可以输入姓名和成绩,返回链表的头结点。
第二步:在deletelist函数中遍历链表的结点,若结点中的分数小于规定的值则释放此结点的内存,需注意若最终结点全被释放完内存,即返回的头结点为空的情况。
第三步:将判断后链表的头结点返回主函数。
(2)流程图
2.实验代码
struct stud_node *createlist() {
int num,score;
char name[20];
struct stud_node *p,*head=NULL,*tail=NULL;
p = (struct stud_node*)malloc(sizeof(struct stud_node));
scanf("%d",&num);
while (num != 0)
{
p = (struct stud_node *)malloc (sizeof (struct stud_node));
scanf ("%s %d", p->name, &p->score);
p->num = num;
if (head == NULL)
head = p;
else
tail->next = p;
tail = p;
scanf ("%d", &num);
}
return head;
}
struct stud_node *deletelist( struct stud_node *head, int min_score ) {
struct stud_node *L=head,*head1=NULL,*tail1=NULL;
while(L!=NULL) {
if(L->score>=min_score)
{
if(head1==NULL) {
head1 = L;
} else {
tail1->next = L;
}
tail1 = L;
} else {
free(L);
}
L=L->next;
}
if(head1==NULL) {
return NULL;
} else {
tail1->next =NULL;
}
return head1;
}
3.本题调试过程碰到问题及解决办法
错误点1:在判断输入的成绩小于规定值后,并没有将此时的结点内存释放。
解决方法:在看了PTA调试错误的类型后,重新仔细思考了自己的代码结合老师上课所讲的用free可以释放内存的知识点,最终解决问题。
错误点2:在函数deletelist中while循环的结束后,忘记加tail1->next =NULL,导致第一个测试点答案错误。
解决方法:在调试及各种值的带入都找不出错误原因后,仔细思考了此测试点没错的同学的代码,最终发现问题。
6-3 链表拼接
PTA提交列表:
1.设计思路
(1)主要描述题目算法
(2)流程图
2.实验代码
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2) {
struct ListNode *p1=list1;
int length=0;
int array[100];
for(p1=list1;p1!=NULL;p1=p1->next) {
array[length] = p1->data;
length++;
}
p1=list2;
for(;p1!=NULL;p1=p1->next) {
array[length] = p1->data;
length++;
}
int i,j,t;
for(i=0;i<length-1;i++) {
for(j=i+1;j<length;j++) {
if(array[j]<array[i]) {
t =array[j];
array[j]=array[i];
array[i] = t;
}
}
}
struct ListNode *q,*head1 = NULL,*tail1=NULL;
i=0;
while(i<length) {
q = (struct ListNode *)malloc(sizeof(struct ListNode));
q->data = array[i];
if(head1 == NULL) {
head1 = q;
} else {
tail1->next = q;
}
tail1 = q;
tail1->next = NULL;
i++;
}
return head1;
}
3.本题调试过程碰到问题及解决办法
遇到的问题1:将函数最后的tail1->next=q与tail1=q位置放反,导致系统崩坏。
解决方法:单步调试后发现顺序的问题,最后改正。
遇到的问题:一开始自己的思路为,新建一个链表,将之前两个链表的值统合到此一个列表中,在定义一个一维数组,最后将新建链表中date的值赋给此一维数组,然后用选择法进行数组元素的排序,最终将排好序的数组赋值给一个新的链表,最终返回新的链表头结点
,但在pta中会导致最后结果全为段错误,即超出内存。
最后在网上搜寻答案后,简化代码,即直接将合并的两个链表的值直接赋给一维数组,然后进行选择法排序,将排好的值赋给新建链表即可,最后返回新建列表的头结点。
struct ListNode *p1=list1,*head1=NULL,*tail1=NULL;
for(;p1!=NULL;p1=p1->next) {
if(head1==NULL) {
head1 = p1;
} else {
tail1->next=p1;
}
tail1 = p1;
}
p1 = list2;
for(;p1!=NULL;p1=p1->next) {
tail1->next = p1;
tail1 = p1;
}
tail1->next=NULL;
int length=0;
int array[100];
for(p1=head1;p1!=NULL;p1=p1->next) {
array[length] = p1->data;
length++;
}
学习总结和进度
1、总结两周里所学的知识点,回答下列问题?
1)如何理解指针数组,它与指针、数组有何关系?为何可以用二级指针对指针数组进行操作?
答:指针数组是存放指针的数组,即是数组的形式,但数组中的元素为指针,而指针又叫指针变量是存放指针的变量,即存放地址的变量;用二级指针指向指针数组的第一个元素,此时二级指针中存放指针数组第一个元素的地址,若定义二级指针为int ** p,指针数组为 int * num[]里面存储着int a[]的地址,则p表示num[0]的值,指向a[0],值为a[0]的地址, p+i指向数组元素a[i],且 * (*p+i)表示数组元素a[i]。
2)将C高级第三次PTA作业(1)任何一个题目改为使用二级指针对指针数组进行操作。
6-1 输出月份英文名改为使用二级指针对指针数组进行操作,代码如下:
char *getmonth( int n ) {
char *month[12] = {"January","February","March","April","May","June","July","August","September","October","November","December"};
char **p = &month[0];
char *pc = '\0';//*pc未等于'\0'
if(n>0 && n<=12){//n写成>=0
pc = *(p+n-1);//pc写成等于month+n-1
}
return pc;
}
3)用指针数组处理多个字符串有何优势?可以直接输入多个字符串给未初始化的指针数组吗?为什么?
答:如果用二维数组保存多个字符串比较浪费内存空间,每个字符串必须要占用同样的字节数,从而浪费了一定的空间,而指针数组的话,可以通过初始化字符串由编译器自动决定数组的长度,从而节约内存;不可以,因为若未将指针初始化的话,指针会指向一个不确定的地址,而此地址中有可能存储着有用的数据,会破坏系统的正常工作情况。
2、将PTA作业的源代码使用git提交到托管平台上,要求给出上传成功截图和你的git地址。
git地址:(https://git.coding.net/exo07/disizhouzuoye.git)
3、点评3个同学的本周作业(在作业中给出被点评同学博客的链接),并邀请3名同学点评你的作业
史泽文:(http://www.cnblogs.com/shilcz/p/8906128.html)
高立彬:(http://www.cnblogs.com/gao628526/p/8781936.html)
董欣:(http://www.cnblogs.com/dx2017/p/8781858.html)
4、请用表格和折线图呈现你本周(4/9 8:00~4/23 8:00)的代码行数和所用时间、博客字数和所用时间