这个作业属于那个课程 | C语言程序设计II |
这个作业要求在哪里 | https://edu.cnblogs.com/campus/zswxy/computer-scienceclass1-2018/homework/3079 |
我在这个课程的目标是 | 学会使用二维字符串数组和动态内存分配和预习结构的相关知识 |
这个作业在那个具体方面帮助我实现目标 | 1,二维字符串数组的使用 2,动态内存分配 |
参考文献 | 《c语言程序设计(第3版)》 |
基础作业
函数题
函数实现字符串逆序 (15 分)
本题要求实现一个字符串逆序的简单函数。
函数接口定义:
void f( char *p );
函数f对p指向的字符串进行逆序操作。要求函数f中不能定义任何数组,不能调用任何字符串处理函数。
裁判测试程序样例:
include <stdio.h>
define MAXS 20
void f( char *p );
void ReadString( char s ); / 由裁判实现,略去不表 */
int main()
{
char s[MAXS];
ReadString(s);
f(s);
printf("%s
", s);
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
Hello World!
输出样例:
!dlroW olleH
一,实验代码
void f(char *p)
{
int i,n;
char *q,t;
for(i=0;;i++)
{
if(*(p+i)==' ')
{
q=p+i-1;
n=i;
break;
}
}
for(i=0;i<n/2;i++)
{
t=*(p+i);
*(p+i)=*(q-i);
*(q-i)=t;
}
}
二,设计思路
首先建立for循环让p指针所指向的地址逐渐后移,当p==‘ ’时令q=p+i-1,这样可以使q指针所指向的地址为字符串的最后一位字符,同时将循环次数i的值赋予n,用于下一循环找字符串的中间位置。然后,再建立一个for循环让(p+i)与*(q-i)交换,直到循环次数i>=n/2结束循环。以下为流程图:
三,调试时遇到的问题及解决方法
以下为错误代码段:
for(i=0;i<n/2;i++)
{
t=(p+i);
(p+i)=*(q-i);
(q-i)=t;
}
这样会导致系统报错。
解决方案:在指针前加上*号即可。
四,运行结果截图
字符串的连接 (15 分)
本题要求实现一个函数,将两个字符串连接起来。
函数接口定义:
char *str_cat( char *s, char *t );
函数str_cat应将字符串t复制到字符串s的末端,并且返回字符串s的首地址。
裁判测试程序样例:
include <stdio.h>
include <string.h>
define MAXS 10
char *str_cat( char *s, char *t );
int main()
{
char *p;
char str1[MAXS+MAXS] = {' '}, str2[MAXS] = {' '};
scanf("%s%s", str1, str2);
p = str_cat(str1, str2);
printf("%s
%s
", p, str1);
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
abc
def
输出样例:
abcdef
abcdef
一,实验代码
char *str_cat(char *s,char *t)
{
int i,I=0;
for(i=0;;i++)
{
if(*(s+i)==' ')
{
*(s+i)=*(t+I);
I++;
}
if(*(t+I)==' ')
break;
}
return s;
}
二,设计思路
首先建立for循环让s+i指向的位置逐渐靠后,当(s+i)=‘ ’时,令其等于(t+I),同时使I自加1。重复以上步骤,然后当*(t+I)=‘ ’时代表字符串连接结束了,所以跳出循环并返回s的地址。以下为流程图:
三,调试时遇到的问题及解决方法
在结尾的时候没有返回指针s的地址,导致答案错误。在结尾处补上return s 即可。
四,运行结果截图
编程题
输出学生成绩 (20 分)
本题要求编写程序,根据输入学生的成绩,统计并输出学生的平均成绩、最高成绩和最低成绩。建议使用动态内存分配来实现。
输入格式:
输入第一行首先给出一个正整数N,表示学生的个数。接下来一行给出N个学生的成绩,数字间以空格分隔。
输出格式:
按照以下格式输出:
average = 平均成绩
max = 最高成绩
min = 最低成绩
结果均保留两位小数。
输入样例:
3
85 90 95
输出样例:
average = 90.00
max = 95.00
min = 85.00
一,实验代码
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *p,i,n,k=0,t=0;
float max,min,average,sum=0;
scanf("%d",&n);
if((p=(int*)calloc(n,sizeof(int)))==NULL) //动态分配p的空间
{
exit(1);
}
for(i=0;i<n;i++) //输入成绩
{
scanf("%d",p+i);
sum=sum+*(p+i);
}
max=p[k]; //初始化最大值和最小值
min=p[t];
for(i=0;i<n;i++)
{
if(p[k]<p[i]) //替换最大值和最大值下标
{
k=i;
max=p[i];
}
if(p[t]>p[i]) //替换最小值和最小值下标
{
t=i;
min=p[i];
}
}
average=sum/n;
printf("average = %.2f
",average);
printf("max = %.2f
",max);
printf("min = %.2f",min);
free(p); //释放p的空间
return 0;
}
二,设计思路
题目要求使用动态内存分配,因此首先用calloc对指针p进行内存分配。然后建立循环输入成绩同时将成绩累加到sum上。然后,用max=p[k] 和min=p[t]使最大值与最小值初始化。再建立循环,寻找最大值与最小值,并存入对应的变量中。循环结束后算出平均值并输出,在输出最大值和最小值。以下为流程图:
三,调试时遇到的问题及解决方法
如图:
判定点0和1错误,这是由于我定义的average,sum都为整型,这就导致不会显示小数点以后的数字,而且,即使是输出格式为%.2d也是无效的,因为整形是不会显示小数点以后的数的。
解决方案:
将average,sum的数据类型改为float,并把输出格式改为%.2f。注意:两个参数缺一不可,不然输出的平均值必然错误。
四,运行结果截图
字符串排序 (20 分)
本题要求编写程序,读入5个字符串,按由小到大的顺序输出。
输入格式:
输入为由空格分隔的5个非空字符串,每个字符串不包括空格、制表符、换行符等空白字符,长度小于80。
输出格式:
按照以下格式输出排序后的结果:
After sorted:
每行一个字符串
输入样例:
red yellow blue green white
输出样例:
After sorted:
blue
green
red
white
yellow
一,实验代码
#include<stdio.h>
#include<string.h>
int main()
{
int i,I,k=0,n=0;
char str[5][80],ch[80]; //定义二维字符串数组
for(i=0;i<5;i++)
{
scanf("%s",str[i]); //输入字符串至str
}
for(i=0;i<=4;i++) // 运用选择排序法的思路调整str内元素的顺序
{
for(I=n;I<5;I++)
{
if(strcmp(str[k],str[I])>0)
{
strcpy(ch,str[k]);
strcpy(str[k],str[I]);
strcpy(str[I],ch);
}
}
k++;
n++;
}
printf("After sorted:
");
for(i=0;i<5;i++) //按顺序输出str内的字符串
{
printf("%s
",str[i]);
}
return 0;
}
二,设计思路
这题可以运用二维字符串数组,用来保存输入的多个字符串。然后建立循环输入字符串至二维字符串数组str中。然后,再建立双层循环,运用选择排序法的思路对str中的字符串进行排序。最后,再按顺序输出str中的字符串。以下为流程图:
三,调试时遇到的问题及解决方法
如下代码段:
if(strcmp(str[k],str[I])>0)
{
ch=str[k];
str[k]=str[I];
str[I]=ch;
}
这是一个很蠢的错误,我定义的ch和str都属于字符串一类,在确定了里面的值时就只能改变里面的元素,但如果str和ch是字符指针的话也许这样是对的。所以解决方案就是用strcpy语句将对应的参数放进去即可。
四,运行结果截图
预习作业
计算平均成绩 (15 分)
给定N个学生的基本信息,包括学号(由5个数字组成的字符串)、姓名(长度小于10的不包含空白字符的非空字符串)和成绩([0,100]区间内的整数),要求计算他们的平均成绩,并顺序输出平均线以下的学生名单。
输入格式:
输入在一行中给出正整数N(≤10)。随后N行,每行给出一位学生的信息,格式为“学号 姓名 成绩”,中间以空格分隔。
输出格式:
首先在一行中输出平均成绩,保留2位小数。然后按照输入顺序,每行输出一位平均线以下的学生的姓名和学号,间隔一个空格。
输入样例:
5
00001 zhang 70
00002 wang 80
00003 qian 90
10001 li 100
21987 chen 60
输出样例:
80.00
zhang 00001
chen 21987
一,实验代码
#include<stdio.h>
int main(void)
{
int n,i;
scanf("%d",&n);
int grade[n],number[n];
float average,sum=0;
char name[n][10]; //定义二维字符串数组保存学生名字
for(i=0;i<n;i++) //输入学生数据
{
scanf("%d",&number[i]);
scanf("%s",name[i]);
scanf("%d",&grade[i]);
sum=sum+grade[i];
}
average=sum/n;
printf("%.2f
",average);
for(i=0;i<n;i++)
{
if(grade[i]<average) //输出不及格学生的名字和学号
{
printf("%s ",name[i]);
printf("%0.5d
",number[i]);
}
}
return 0;
}
二,设计思路
很明显,这题的用意是要我们预习结构的相关知识并使用。但是我拒绝!因为我觉得太麻烦了(就是懒),而且用学过的知识做这题我感觉更简单。
首先,输入学生数至n变量。然后,定义二维字符串数组name用来储存学生的名字,定义两个一维数组grade和number分别用来储存成绩和学号,它们开辟的空间数都有n变量决定。建立循环,输入学号,名字和成绩,同时计算总分至sum。再然后,用sum和n算出平均值并输出,建立循环来寻找不及格学生同时输出他的名字和学号。以下为流程图:
三,调试时遇到的问题及解决方法
如上图,但是我定义的number是为二维字符串数组,如下:
char number[n][5];
原因貌似是因为二维字符串数组的输出方式与字符指针的输出方式类似,是根据地址逐个向后输出,导致出现如上图的将number数组从i开始之后所有的字符串都输了出来的错误。
具体错误原因暂且未知。
解决方案:
将number定义方式更换,如下:
int number[n];
四,运行结果截图
挑战作业
不会写,题目也没看懂...
学习进度统计与学习感悟
这周主要学习了字符串使用的相关函数strcpy,strcat,strcmp和动态内存分配的相关函数malloc,calloc,free,和realloc。内容相较上周的更多也更复杂,需要多加练习。
结对编程的过程和优缺点
主要还是是以互相分享思路为主,遇到调试错误和难点时也会互相讨论。
优点:1,思路更多了,有时搭档也会提出一些优化代码的意见
2,当出现自己疏忽了的错误时搭档会提醒,节省了很多回头找错误的时间
缺点: 双方都变懒了,有时会互相拖拉进度