袁中的第三次作业

第一题:

            输出月份英文名

设计思路:

                  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基本一下就作好了,而这周嘛,为了这几题一直在想,一直在做,也许是我掌握的不够好,不过现在对我来说这种题型都会做了,也可以理解所有代码,不会像以前那样费劲了,因为学了一周了,想的也多了,有时走路也在想,感觉这周收获比较多。我们还学了如何申请动态空间,这样可以节省更多的空间,上面做的题有体现。

我的进度:


我点评的人:

李伍壹
辛静瑶
姜健
王文博

点评我的人:

                       左右羽
                       马钰娟
                       王文博
                       姜健
                       李伍壹

git地址

posted @ 2018-04-09 18:53  袁中  阅读(555)  评论(18编辑  收藏  举报