第二次作业
要求一
要求二
6-7 删除字符串中数字字符
删除一个字符串中的所有数字字符。
函数接口定义:
void delnum(char *s);
其中 s
是用户传入的参数。 函数的功能是删除指针s
所指的字符串中的所有数字字符。
裁判测试程序样例:
#include "stdio.h"
void delnum(char *s);
int main ()
{ char item[80];
gets(item);
delnum(item);
printf("%s\n",item);
return 0;
}
/* 请在这里填写答案 */
输入样例:
a0bc+d496df
输出样例:
abc+ddf
1 设计思路
1> 遍历数组,当找到数字时,进行2>
2> 将该位置及以后的值依次前移,重复1>直到字符串结尾
流程图
实验代码
void delnum(char *s)
{
int i,j;
for(i=0;*(s+i)!='\0';i++)
{
if(*(s+i)>='0'&&*(s+i)<='9')
{
for(j=i;*(s+j)!='\0';j++)
{
*(s+j)=*(s+j+1);
}
i--;
}
}
}
错误信息1:程序直接崩溃
错误解决:重新编写程序,但该错误暂无解决方法
错误信息2:通过调试发现指针s的值会自动变化
错误解决:同上
错误信息3:重新编程后发现会多出非数字字符
错误解决:循环变量i未归位,即未重新遍历数组,前移后将i的值归位
6-8 统计子串在母串出现的次数
编写一个函数,该函数可以统计一个长度为3的字符串在另一个字符串中出现的次数。例如,假定输入的字符串为:asdasasdfgasdaszx67asdmklo
,字符串为:asd
,则应输出n=4
。
函数接口定义:
int fun(char *str,char *substr);
其中str
和 substr
是用户传入的参数。函数统计substr
指针所指的字符串在str指针所指的字符串中出现的次数,并返回次数。
裁判测试程序样例:
#include<stdio.h>
int fun(char *str,char *substr);
int main()
{ char str[81]="asdasasdfgasdaszx67asdmklo",substr[4]="asd";
int n;
n=fun(str,substr);
printf("n=%d\n",n);
return 0;
}
/* 请在这里填写答案 */
输出样例:
n=4
1 设计思路
1> 定义循环变量i,j,统计次数变量count,判断变量k
2> 遍历字符串数组str,若找到与字符串数组substr开头相同的字符,进行3>
3> 同时对str和substr进行长度为strlen(substr)的遍历,若有不相同字符,则改变k的值,并退出该遍历
4> 若3>执行完成后k的值未改变,则 令count的值加1;并从该位置返回2>继续遍历
5> 完成2>中遍历后,将count的值返回主函数
流程图
实验代码
int fun(char *str,char *substr)
{
int i,j;
int count=0;
int k;
for(i=0;*(str+i)!='\0';i++)
{
k=1;
if(*(str+i)==*substr)
{
for(j=0;*(substr+j)!='\0';j++)
{
if(*(str+i+j)!=*(substr+j))
{
k=0;
break;
}
}
if(k==1)
count++;
}
}
return count;
}
错误信息1:返回值count出错
错误原因:遍历数组时将两字符串比较后的循环变量i错误改变,以及判断变量k的位置放错
错误解决:逐个遍历数组而非跳跃式遍历数组;判断变量k应该在两字符串比较完成后就进行判断而非在遍历数组str时判断
6-9 字符串中除首尾字符外的其余字符按降序排列
请编写函数fun
,对字符串中除首、尾字符外的其余字符按降序排列。例如,原来的字符串为CEAedca
,排序后输出为CedcEAa
。
函数接口定义:
int fun(char *s,int num);
其中s
和 num
都是用户传入的参数。函数对字符指针 s
所指的字符串中除首、尾字符外的其余字符按降序排列。
裁判测试程序样例:
#include <stdio.h>
int fun(char *s,int num);
int main()
{
char s[10];
gets(s);
fun(s,7);
printf("%s",s);
return 0;
}
/* 请在这里填写答案 */
输入样例:
CEAedca
输出样例:
CedcEAa
1 设计思路
1> 找到字符串的首尾字符的位置
2> 将除首尾外的字符降序排序
流程
图
实验代码
int fun(char *s,int num)
{
int i,j,k;
for(i=1;i<num-1;i++)
{
for(j=num-2;j>i;j--)
{
if(*(s+j)>*(s+j-1))
{
char t;
t=*(s+j),*(s+j)=*(s+j-1),*(s+j-1)=t;
}
}
}
}
错误信息1:排序结果错误
错误解决1:变量过多导致范围确定错误,将程序简化确定范围
错误解决2:冒泡排序过程出错,重新复习冒泡排序并改正
7-1 输出学生成绩
本题要求编写程序,根据输入学生的成绩,统计并输出学生的平均成绩、最高成绩和最低成绩。建议使用动态内存分配来实现。
输入格式:
输入第一行首先给出一个正整数N
,表示学生的个数。接下来一行给出N
个学生的成绩,数字间以空格分隔。
输出格式:
按照以下格式输出:
average = 平均成绩
max = 最高成绩
min = 最低成绩
结果均保留两位小数。
输入样例:
3
85 90 95
输出样例:
average = 90.00
max = 95.00
min = 85.00
设计思路
1> 定义个数变量N,双精度各功能变量sum,max,min,avg,指针变量p
2> 输入N,申请N个双精度长度的空间并将首地址赋值给p
3> 通过循环输入N个数,并将其相加得到sum
4> 将首地址的值赋给max,min,通过循环遍历该动态内存空间来找到最大最小值
5> 计算avg,按题意输出avg,max,min
6> 释放该动态内存
流程图
实验代码
#include<stdio.h>
#include<stdlib.h>
int main()
{
int N;
double sum=0,max,min,avg,*p;
int i;
scanf("%d",&N);
if((p=(double *)calloc(N,sizeof(double)))==NULL)
{
printf("Not able to allocate memory.\n");
exit(1);
}
for(i=0;i<N;i++)
{
scanf("%lf",p+i);
sum=sum+*(p+i);
}
max=*p,min=*p;
for(i=0;i<N;i++)
{
if(*(p+i)>max)
max=*(p+i);
if(*(p+i)<min)
min=*(p+i);
}
avg=sum*1.0/N;
printf("average = %.2lf\nmax = %.2lf\nmin = %.2lf\n",avg,max,min);
free(p);
}
错误信息1:编译错误
错误改正:未引用stdlib.h库,引用即可
错误信息2:答案错误
错误改正:输入N个数为整形而非双精度型,改为双精度型即可
7-1 计算职工工资
给定N
个职员的信息,包括姓名、基本工资、浮动工资和支出,要求编写程序顺序输出每位职员的姓名和实发工资(实发工资=基本工资+浮动工资-支出)。
输入格式:
输入在一行中给出正整数N
。随后N
行,每行给出一位职员的信息,格式为“姓名 基本工资 浮动工资 支出”,中间以空格分隔。其中“姓名”为长度小于10的不包含空白字符的非空字符串,其他输入、输出保证在单精度范围内。
输出格式:
按照输入顺序,每行输出一位职员的姓名和实发工资,间隔一个空格,工资保留2位小数。
输入样例:
3
zhao 240 400 75
qian 360 120 50
zhou 560 150 80
输出样例:
zhao 565.00
qian 430.00
zhou 630.00
1 实验思路
1> 定义结构体worker,元素分别为字符串数组name(用来存放姓名)、双精度实数jb(基本工资)、fd(浮动工资)、zc(支出)、fee(实发工资)
2> 定义结构体变量w,整型N,i;N赋值
3> 按结构体要求输入数据,计算实发工资fee,输出姓名name与实发工资fee
流程图
实验代码
#include<stdio.h>
struct worker
{
char name[10];
float jb,fd,zc;
float fee;
};
int main()
{
struct worker w;
int N,i;
scanf("%d",&N);
for(i=0;i<N;i++)
{
scanf("%s %f %f %f",w.name,&w.jb,&w.fd,&w.zc);
w.fee=w.jb+w.fd-w.zc;
printf("%s %.2f\n",w.name,w.fee);
}
}
错误信息1:PTA上提示段错误
错误改正:先前是用结构体数组来实现题目要求,后改为输入结束一次就输出一次,PTA通过
7-2 计算平均成绩
给定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
设计思路
1> 定义结构体student,元素分别为字符串数组No(学号)、name(姓名),整型sore(成绩)
2> 定义整型变量N(学生个数),i(循环变量),sum(成绩总和),双精度实数变量avg(平均成绩),结构体数组s
3> sum赋初值0,N赋值
4> 通过循环给结构体数组赋值,并累加sum
5> 计算avg,输出
6> 遍历结构体数组找到低于平均值的成绩,将其对应的姓名与学号输出
流程图
实验代码
#include<stdio.h>
struct student
{
char No[6];
char name[10];
int sore;
};
int main()
{
int N,i,sum=0;
double avg;
struct student s[10];
scanf("%d",&N);
for(i=0;i<N;i++)
{
scanf("%s %s %d",s[i].No ,s[i].name ,&s[i].sore );
sum=sum+s[i].sore ;
}
avg=sum*1.0/N;
printf("%.2lf\n",avg);
for(i=0;i<N;i++)
{
if(s[i].sore<avg)
printf("%s %s\n",s[i].name,s[i].No);
}
}
错误信息1:输出学号时会带上对应姓名
错误分析:通过对数组的空间分配的分析发现,字符串数组No长度为5,最后结尾不为\0;其对应的字符串数组name所分配的空间是紧挨着No所分配的空间的,在输出字符串(即%s)时,判断字符串结尾的\0在name中,导致输出No时将name的\0当作字符串结尾,因此输出No后会再带上对应的姓名
错误改正:将字符串数组No的长度改为6,即给\0申请个空间
6-1 按等级统计学生成绩
本题要求实现一个根据学生成绩设置其等级,并统计不及格人数的简单函数。
函数接口定义:
int set_grade( struct student *p, int n );
其中p是指向学生信息的结构体数组的指针,该结构体的定义为:
struct student{
int num;
char name[20];
int score;
char grade;
};
n
是数组元素个数。学号num
、姓名name
和成绩score
均是已经存储好的。set_grade
函数需要根据学生的成绩score
设置其等级grade
。等级设置:85-100为A,70-84为B,60-69为C,0-59为D
。同时,set_grade
还需要返回不及格的人数。
裁判测试程序样例:
#include <stdio.h>
#define MAXN 10
struct student{
int num;
char name[20];
int score;
char grade;
};
int set_grade( struct student *p, int n );
int main()
{ struct student stu[MAXN], *ptr;
int n, i, count;
ptr = stu;
scanf("%d\n", &n);
for(i = 0; i < n; i++){
scanf("%d%s%d", &stu[i].num, stu[i].name, &stu[i].score);
}
count = set_grade(ptr, n);
printf("The count for failed (<60): %d\n", count);
printf("The grades:\n");
for(i = 0; i < n; i++)
printf("%d %s %c\n", stu[i].num, stu[i].name, stu[i].grade);
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
10
31001 annie 85
31002 bonny 75
31003 carol 70
31004 dan 84
31005 susan 90
31006 paul 69
31007 pam 60
31008 apple 50
31009 nancy 100
31010 bob 78
输出样例:
The count for failed (<60): 1
The grades:
31001 annie A
31002 bonny B
31003 carol B
31004 dan B
31005 susan A
31006 paul C
31007 pam C
31008 apple D
31009 nancy A
31010 bob B
设计思路
子函数:
1> 定义整型变量count用来统计不及格成绩出现次数,整型变量i作为循环变量
2> 通过指针遍历该结构体数组 ,将成绩对应的等级赋值给对应的grade中
3> 函数返回count
流程图
实验代码
int set_grade( struct student *p, int n )
{
int count=0,i;
for(i=0;i<n;i++)
{
if((p+i)->score>=85&&(p+i)->score<=100)
(p+i)->grade = 'A';
else if((p+i)->score>=70&&(p+i)->score<=84)
(p+i)->grade = 'B';
else if((p+i)->score>=60&&(p+i)->score<=69)
(p+i)->grade = 'C';
else if((p+i)->score>=0&&(p+i)->score<=59)
{
(p+i)->grade = 'D';
count++;
}
}
return count;
}
错误信息1:程序运行后,出现错误格式答案,且部分答案显示错误
错误分析:在最初编程时,指针的使用未加括号导致编译错误;在判断时未循环判断结构体数组中的各个元素导致其答案的格式错误
错误改正:判断等级放在循环内完成
6-2 结构体数组按总分排序
有一组学生数据,每个数据中含有三门课成绩,请按成绩总和从高到低对这组数据进行排序。 编写函数calc
求出每名学生的总分。 编写函数sort
按每名学生的总分从高到低对这组数据进行排序
函数接口定义:
void calc(struct student *p,int n);
void sort(struct student *p,int n);
其中 p
和 n
都是用户传入的参数。 函数calc
求出p
指针所指的结构体数组中 n
名学生各自的总分。 函数sort
对p
指针所指的结构体数组的学生数据按总分降序排序。
裁判测试程序样例:
#include <stdio.h>
struct student
{
int num;
char name[15];
float score[3];
float sum;
};
void calc(struct student *p,int n);
void sort(struct student *p,int n);
int main()
{
struct student stu[5];
int i,j;
float f;
for(i=0;i<5;i++)
{
scanf("%d%s",&stu[i].num,stu[i].name);
for(j=0;j<3;j++)
{
scanf("%f",&f);
stu[i].score[j]=f;
}
}
calc(stu,5);
sort(stu,5);
for(i=0;i<5;i++)
{
printf("%5d%15s",stu[i].num,stu[i].name);
printf(" %.1f %.1f %.1f %.1f\n",stu[i].score[0],stu[i].score[1],stu[i].score[2], stu[i].sum);
}
return 0;
/* 请在这里填写答案 */
输入样例:
1 zhang 89 87 85
2 liu 92 98 96
3 li 74 71 72
4 xion 95 98 99
5 liu 99 100 100
输出样例:
5 liu 99.0 100.0 100.0 299.0
4 xion 95.0 98.0 99.0 292.0
2 liu 92.0 98.0 96.0 286.0
1 zhang 89.0 87.0 85.0 261.0
3 li 74.0 71.0 72.0 217.0
设计思路
子函数calc
1> 定义整型变量i作为循环变量
2> 将结构体数组中sum成员的值用指针p进行求和
子函数sort
1> 定义循环变量i,j;下标变量k
2> 通过选择排序对结构体进行排序
流程图
实验代码
#include<string.h>
void calc(struct student *p,int n)
{
int i;
for(i=0;i<n;i++)
{
(p+i)->sum=(p+i)->score[0]+(p+i)->score[1]+(p+i)->score[2];
}
}
void sort(struct student *p,int n)
{
int i,j,k,m;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
{
if((p+j)->sum>(p+k)->sum)
{
k=j;
}
}
if(k!=i)
{
/*注释
float t;
t=(p+i)->num,(p+i)->num=(p+k)->num,(p+k)->num=t;
t=(p+i)->sum,(p+i)->sum=(p+k)->sum,(p+k)->sum=t;
for(m=0;m<2;m++)
t=(p+i)->score[m],(p+i)->score[m]=(p+k)->score[m],(p+k)->score[m]=t;
t=(p+i)->score[1],(p+i)->score[1]=(p+k)->score[1],(p+k)->score[1]=t;
t=(p+i)->score[2],(p+i)->score[2]=(p+k)->score[2],(p+k)->score[2]=t;
char T[15];
strcpy(T,(p+i)->name),strcpy((p+i)->name,(p+k)->name),strcpy((p+k)->name,T);
*/
struct student t;
t=*(p+i),*(p+i)=*(p+k),*(p+k)=t;
}
}
}
错误信息1:排序错误
错误分析:选择排序内循环中,j=i+1错写成j=i+i
错误改正:j=i+i改为j=i+1
错误信息2:答案错误
错误分析:原始程序中的交换使用的是单个数据类型的相互交换(即实验代码中被注释的部分),该过程中可能会有遗漏或其他问题
错误改正:直接定义结构体数据类型变量t,再用t实现两个元素的交换