C程序第三次作业

Posted 董雅洁

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)的代码行数和所用时间、博客字数和所用时间

以上是关于C程序第三次作业的主要内容,如果未能解决你的问题,请参考以下文章

第三次作业

第三次作业

C高级第三次作业

java程序设计作业 c.njupt.edu.cn java实现第三次作业

第三次作业

第三次作业