袁中的第三次作业
第一题:
输出月份英文名
设计思路:
1:看题目:主函数与函数声明,知道它要你干什么
2:理解与分析:在main中,给你一个月份数字n,要求你通过调用函数char *getmonth,来判断:若它小于等于12,则将它转化为英文单词输出,若它大于等于12,则输出wrong input!
3:解答:第一步:定义一个二维数组*a[12][15],并赋值给它1-12月的英文单词
第二步:定义i,i作为a[]的下标
第三步:利用一个for循环,判断i是否等于n,若相等,返回a[i-1];若出了for循环,则返回 NULL
流程图:
实验代码:
char *a[12][15]={"January","February","March","April","May","June","July","August","September","October","November","December"};
char *getmonth( int n )
{
int i;
for(i=1;i<=12;i++)
{
if(i==n)
{
return a[i-1];
}
}
return NULL;
}
错误信息:
错误1: a[12][15]中的号一直没打,找了好久,害我在其它地方一直改,没改对
解决方案1:加*号
第二题:
查找星期
设计思路:
1:看题目:主函数与函数声明,知道它要你干什么
2:理解与分析:在main中,给你星期1-7的英文单词及它们对应的序号,再给你一个字符串,通过调用函数getindex,要你判断它是否为星期1-7的英文单词,若是则输出它的序号,否则输出wrong input!
3:解答:第一步:定义一个二维数组*a[][],并赋值给它星期7-1的英文单词
第二步:定义i,i作为a[]的下标
第三步:利用一个for循环,判断strcmp(s,a[i])是否等于0,若成立,返回序号i;若不成立,跳出for循环后,返回-1
流程图:
实验代码:
char *a[][15]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
int getindex( char *s )
int i;
for(i=0;i<7;i++)
{
if(strcmp(s,a[i])==0)
return i;
}
return -1;
}
错误信息:
这题没错误,因为第一题的错误避免了,还有我知道strcmp(s,a[i])==0
第三题:
计算最长的字符串长度
设计思路:
1:看题目:主函数与函数声明,知道它要你干什么
2:理解与分析:在main中,题目给你n个字符串,要求你通过调用函数 max_len,计算n个元素的指针数组s中最长的字符串的长度
3:解答:第一步:定义i,max=0,t=0;其中i为s[]的下标,max记录s中最长的字符串的长度,t为记录s中字符串的长度
第二步:将strlen(s[0])赋值给max
第三步:利用for循环,从i=1开始,令 t=strlen(s[i]);再判断max是否小于t,若小于,将t赋值给max,跳出for循环后,返回max
流程图:
实验代码:
int max_len( char *s[], int n )
{
int i,max=0,t=0;
max=strlen(s[0]);
for(i=1;i<n;i++)
{
t=strlen(s[i]);
if(max<t)
max=t;
}
return max;
}
错误信息:
无
第四题:
指定位置输出字符串
设计思路:
1:看题目:主函数与函数声明,知道它要你干什么
2:理解与分析:要你用函数match应打印s中从ch1到ch2之间的所有字符,并且返回ch1的地址
3:解答:在match中,定义i=0,j=0,len=0;i,j作为s[]的下标,len用于记录s[]长度。还定义 *p=NULL,*p用于记录ch1的地址
第一步:计算s[]的长度——len = strlen(s)
第二步:用for循环遍历s[],先找 s[i]==ch1,若找到,则p=&s[i],再用for循环找ch2,若找到,则输出 ch1到 ch2之间的字符,并返回p;若没找到,输出ch1后面的所有字符,并返回p;若没找到ch1,则p=&s[len],并返回p;
实验代码:
char *match( char *s, char ch1, char ch2 ){
int i=0,j=0,len=0;
char *p=NULL;
len = strlen(s);
for(i=0;i<len;i++){
if(s[i]==ch1){
p=&s[i];
for(j=i;j<len;j++){
if(s[j]!=ch2){
printf("%c", s[j]);
}
if(s[j]==ch2){
printf("%c\n", s[j]);
return p;
}
}
printf("\n");
return p;
}
}
p=&s[len];
printf("\n");
return p;
}
错误信息:
原因:一开始我题目理解错了:
我以为在主函数中输出也是rog,然后我就一直在这个地方错误,后来我仔细看题才知道返回的是ch1的地址
第五题:
用筛选法求质数;
题目:
设计思路:
1:看题目:主函数与函数声明,知道它要你干什么
2:先定义一个宏——MAX_N=10000000,然后定义一个全局变量的数组prime[MAX_N],再定义一个全局变量bool型的数组is_prime[MAX_N+1];
3:在主函数中,先定义b,c,d,i;其中b为你的学号,c为你学号的前三位,d为你学号的后四位,i为prime[]的下标
第一步:输入你的学号b,然后求出你学号的前三位和学号的后四位——c=b/10000000,d=b%10000;
第二步:调用函数sieve——sieve(c*d);
第三步:输出
4:在sieve中,用n接收c*d,定义p=0,i,j;p作为质数的下标,i作为数组的下标、还为1—n之间的某个数,j为i的倍数
第一步:用一个for循环,令所以的is_prime[i]的值都为true,出for循环后,令is_prime[0]=is_prime[1]=false;
第二步:用两个for循环,外层for循环为for( i=2;i<=n;i++),进入外层for循环后,判断is_prime[i]==true是否成立,若成立,代表i为质数,令prime[p]=i,然后p++,再用一个for循环令所以i的倍数的值全为is_prime[j]=false,实现为内层for循环for(int j=2*i;j<n;j=j+i)is_prime[j]=false;
实验代码:基地学长教我的
#include <stdio.h>
#include <math.h>
int MAX_N=10000000;
int prime[MAX_N];
bool is_prime[MAX_N+1];
int sieve(int n){
int p=0,i,j;
for( i=0;i<=n;i++)is_prime[i]=true;
is_prime[0]=is_prime[1]=false;
for( i=2;i<=n;i++){
if(is_prime[i]==true){
prime[p]=i;
p++;
for(int j=2*i;j<n;j=j+i)is_prime[j]=false;
}
}
}
int main()
{
int b,c,d,i;
scanf("%d",&b);
c=b/10000000;
d=b%10000;
int sieve(c*d);
for(i=0;i<=MAX_N;i++)
{
if((i+1)%5==0)
{
printf("%d\n",prime[i]);
}else
{
printf("%d ",prime[i]);
}
}
}
}
第六题:
学生成绩链表处理
设计思路:
1:看题目:主函数与函数声明,知道它要你干什么
2:理解与分析:在main中,要求你利用两个函数,一个将输入的学生成绩组织成单向链表;另一个将成绩低于某分数线的学生结点从链表中删除。其中函数createlist利用scanf从输入中获取学生的信息,将其组织成单向链表,并返回链表头指针;而函数deletelist从以head为头指针的链表中删除成绩低于min_score的学生,并返回结果链表的头指针;
3:解答:在createlist中,定义三个struct stud_node的指针*p, *ptr, *head=NULL;其中*p用于申请动态空间,*head用于建立链表的表头,*ptr用于建立链表的其它部分
第一步:定义num,name[20],score;它们的值用于赋值给struct stud_node结构中的num,name[20],score;
第二步:读入一个num,并判断它是否等于0,若不等于,则进入while循环;若等于0,返回head;
第三步:进入whlie后,读入name[20],score;再申请一个struct stud_node结构的动态空间p,将num,name[20],score的值赋值或复制给p中的num,name[20],score;
第四步:判断head是否为NULL;是则让head=p,建立链表的表头;若不是,则令ptr->next = p;出if语句后,再将ptr=p;
第五步:重复操作第二步到第四步,直到num=0,返回head;
在deletelist中,定义二个struct stud_node的指针ptr1, ptr2;在第一个while中,ptr2用于查找从head开始第一个不满足head->score < min_score的数;在第二个while中(此时的head肯定不满足head->score < min_score):ptr1用于指向head,ptr2用于指向head的next;
第一步:判断head != NULL && head->score < min_score,若成立,则令ptr2=head,再令head = head->next,再free(ptr2);若不成立了,一定是以下两种情况之一:1:学生的分数全部低于min_score,链表全部都释放了,此时head=NULL;
2:找到了第一个学生的分数大于min_score的人,并让head指向了他;
第二步:出第一个while后,判断head == NULL;若是,则为我说的第一个情况——学生的分数全部低于min_score,链表全部都释放了,此时head=NULL,应该返回NULL;若不是,则为第二种情况——找到了第一个学生的分数大于min_score的人,并让head指向了他,我们还要找是否他后面还有不满足head->score < min_score的数;
第三步:令ptr1 = head;ptr2 = head->next;判断ptr2 != NULL,若不为空,进入第二个while中,判断ptr2->score < min_score,若满足,则说明我们要将ptr1的next释放,在释放前,应该先链接——ptr1->next = ptr2->next,再释放——free(ptr2);若不满足ptr2->score < min_score,则说明ptr2不用被释放,我们应该让ptr1指向ptr2——ptr1 = ptr2,再让ptr2指向ptr1的next——ptr2 = ptr1->next;一直重复下去,直到跳出while
第四步:返回head;
流程图:
无
实验代码:
#include<string.h>
struct stud_node *createlist()
{
struct stud_node *p, *ptr, *head=NULL;
int num;
char name[20];
int score;
scanf("%d",&num);
while (num != 0)
{
scanf("%s %d",name,&score);
p = (struct stud_node *)malloc(sizeof(struct stud_node));
p->num = num;
strcpy(p->name, name);
p->score = score;
p->next = NULL;
if (head == NULL)
{
head = p;
}
else
{
ptr->next = p;
}
ptr = p;
scanf("%d",&num);
}
return head;
}
struct stud_node *deletelist( struct stud_node *head, int min_score )
{
struct stud_node *ptr1, *ptr2;
while (head != NULL && head->score < min_score)
{
ptr2 = head;
head = head->next;
free(ptr2);
}
if (head == NULL)
return NULL;
ptr1 = head;
ptr2 = head->next;
while (ptr2 != NULL)
{
if (ptr2->score < min_score) {
ptr1->next = ptr2->next;
free(ptr2);
}
else
ptr1 = ptr2;
ptr2 = ptr1->next;
}
return head;
}
错误信息:
一开始再老师没讲之前,错误太多了,不是我们没做,而是天天在做,天天在错,删除链表好多情况没有考虑到,例如:第一个低于min_score;当全部是低于min_score;还有最后一个低于min_score;老师讲了之后好一点了,还是有上面的一些问题,最后经过仔细琢磨终于想出想出来了
小结:这题做的太辛苦了,不过嘛,也受到了好多东西,下次在遇到相似的题也不会这么费劲了
第七题:
奇数值结点链表
设计思路:
1:看题目:主函数与函数声明,知道它要你干什么
2:理解与分析:在main中,要求你用两个函数,分别将读入的数据存储为单链表、将链表中奇数值的结点重新组成一个新的链表。其中函数readlist从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。而函数getodd将单链表L中奇数值的结点分离出来,重新组成一个新的链表。返回指向新链表头结点的指针,同时将L中存储的地址改为删除了奇数值结点后的链表的头结点地址(所以要传入L的指针)。
3:解答:在readlist中,定义三个struct ListNode的指针*p, *tail, *head=NULL;其中*p用于申请动态空间,*head用于建立链表的表头,*tail用于建立链表的其它部分
第一步:定义data;data的值用于赋值给struct ListNode结构中的data;
第二步:读入一个data,并判断它是否等于-1,若不等于,则进入while循环;若等于-1,返回head
第三步:进入whlie后,申请一个struct ListNode结构的动态空间p,将data的值赋给p中的data;p->next=NULL;
第四步:判断head是否为NULL;是则让head=p,建立链表的表头;若不是,则令tail->next = p;出if语句后,再将tail=p;
第五步:重复操作第二步到第四步,直到data=-1,返回head;
在getodd中,定义七个struct stud_node的指针*p=*L,*a,*b,*head1,*head2,*p1,*p2;其中head1,head2用于申请动态空间,p用于接收*L,p1用于建立奇数链表的表头,a用于建立奇数链表的其它部分,p2用于建立偶数链表的表头,b用于建立偶数链表的其它部分
第一步:申请两个struct ListNode结构的动态空间head1,head2;令a指向head1,b指向head2;
第二步:判断p!=NULL?,若成立,则p->data%2!=0?,若是,则建立奇数链表,否则建立偶数链表,若不成立,令*L指向偶数链表的表头p2,返回奇数链表的表头p1;
流程图:
无
实验代码:
struct ListNode *readlist()
{
struct ListNode *head=NULL,*p=NULL,*tail=NULL;
int data;
scanf("%d",&data);
while(data!=-1)
{
p=(struct ListNode *)malloc(sizeof(struct ListNode));
p->data=data;
p->next=NULL;
if(head==NULL)
{
head=p;
}else
{
tail->next=p;
}
tail=p;
scanf("%d",&data);
}
return head;
}
struct ListNode *getodd( struct ListNode **L )
{
struct ListNode *p=*L,*a,*b,*head1,*head2,*p1=NULL,*p2=NULL;
head1=(struct ListNode*)malloc(sizeof(struct ListNode));
head2=(struct ListNode*)malloc(sizeof(struct ListNode));
head1->next=NULL;
head2->next=NULL;
a=head1;
b=head2;
for(;p!=NULL;p=p->next)
{
if(p->data%2!=0)
{
if(p1==NULL)
p1=p;
else
a->next=p;
a=p;
}
else
{
if(p2==NULL)
p2=p;
else
b->next=p;
b=p;
}
}
a->next=NULL;
b->next=NULL;
*L=p2;
return p1;
}
错误信息:
原因:我先是在原来链表的基础上修改,然后建一个奇数链表;然而我处理不好,一直错误,后来我建了两个链表,一个奇数,一个偶数,最后让*L=偶数表头,返回奇数表头
第八题:
链表拼接
设计思路:
1:看题目:主函数与函数声明,知道它要你干什么
2:理解与分析:在main中,要求你实现一个合并两个有序链表的简单函数
3:解答:在mergelists中,定义struct ListNode的 *p,*ptr1=list1,*ptr2=list2,*tail=NULL,*head=NULL;其中*p用于申请动态空间,*head用于建立链表的表头,*ptr用于建立链表的其它部分,ptr1指向list1,ptr2指向list2;
第一步:定义整形a[1000],i=0,n=0,j=0,t;其中a[]用于储存list1和list2中的所有数,i,j用于冒泡排序法,n用于记录a[]有多少数,t用于冒泡排序法中交换的中间量;
第二步:用两个for循环,将list1和list2中的所有数储存到a[]中,再用n=i,记录a[]有多少数;
第三步:用两个for循环,用冒泡排序法将a[]升序排列;
第四步:建立一个新的链表,将a[]的数全部赋值到链表中,最后返回链表的头部;
实验代码:
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2)
{
struct ListNode *p,*ptr1=list1,*ptr2=list2,*tail=NULL,*head=NULL;
int a[1000],i=0,n=0,j=0,t;
for(i=0;ptr1!=NULL;ptr1=ptr1->next,i++)
{
a[i]=ptr1->data;
}
for(;ptr2!=NULL;ptr2=ptr2->next,i++)
{
a[i]=ptr2->data;
}
n=i;
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(a[i]>a[j])
{
t=a[i];a[i]=a[j];a[j]=t;
}
}
}
for(i=0;i<n;i++)
{
p=(struct ListNode *)malloc(sizeof(struct ListNode));
p->data=a[i];
p->next=NULL;
if(head==NULL)
{
head=p;
}else
{
tail->next=p;
}
tail=p;
}
return head;
}
错误信息:
原因:
有一些NULL没大写;写成了NUll,一直编译错误
总结:
最近两周的学习,我们学了二级指针,我们利用它输出月份英文名,查找星期,计算最长的字符串长度,指定位置输出字符串;我们还学了链表,刚开始,感觉建链表比较简单,而删除链表比较困难,因为有些特殊情况不好处理,后来经过不断的学习,对删除链表也掌握了,这周,我们利用链表奇数值结点链表,学生成绩链表处理,链表拼接;这周我有一些特别的感觉,以前做PTA基本一下就作好了,而这周嘛,为了这几题一直在想,一直在做,也许是我掌握的不够好,不过现在对我来说这种题型都会做了,也可以理解所有代码,不会像以前那样费劲了,因为学了一周了,想的也多了,有时走路也在想,感觉这周收获比较多。我们还学了如何申请动态空间,这样可以节省更多的空间,上面做的题有体现。
我的进度:
我点评的人:
点评我的人:
左右羽
马钰娟
王文博
姜健
李伍壹