C语言博客作业--结构体
一、PTA实验作业
题目1:结构体数组按总分排序
1. 本题PTA提交列表
2. 设计思路(伪代码或流程图)
calc函数
传入结构体的地址和长度
定义结构体指针,指向传入的结构体
for p=stu to stu+n
for i=0 to 2
初始化sum为0
end
end
指针返回初始位置
for p=stu to stu+n
for i=0 to 2
累加sum
end
end
sort函数
定义结构体指针stu,和p2作为内循环指针,max指针存放最大sum的变量地址
定义结构体变量作为交换两变量
for p=stu to stu+n-1
max存p
for p2=p+1 to stu+n-1
如果p2指的变量里的sum大于max指的变量里的sum
交换两变量的数据
end
end
3.代码截图
4.本题调试过程碰到问题及PTA提交列表情况说明。
前几次提交时少复制了后面的几个花括号,导致了几次编译错误
calc函数sum没有初始化,导致devc++上答案错误
解决方法:遍历结构体的sum,初始化为0
题目2:计算职工工资
1. 本题PTA提交列表
2. 设计思路(伪代码或流程图)
struct staff{
char name[100];
double base,flow,put,actual;
};//name为名字,base为基本工资,flow为浮动工资,put为支出,actual为实际工资
定义n为人数,i为循环变量
输入n
定义结构数组,长度为n
for i=0 to n-1
输入单个结构的内容
end
for i=0 to n-1
计算实际工资
end
for i=0 to n-1
输出
end
3.代码截图
4.本题调试过程碰到问题及PTA提交列表情况说明。
定义结构体时基本工资,浮动工资,支出定义成了int,计算的结果却放到了浮点型的变量里,输出结果用的是%f,用函数写是编译错误,去掉函数就变成答案错误。
解决方法:改变定义的类型
题目3:通讯录的录入与显示
1. 本题PTA提交列表
2. 设计思路(伪代码或流程图)
struct list{
char name[100];
char birthday[100];
char sex;
char tel[100];
char mobil[100];
};//name表示名字,birthday生日,sex性别,tel电话,mobil手机
定义为存入信息数,i为循环变量,num为查找信息编号,n2查找个数
输入n
定义结构体数组lis【n】
for i=0 to n-1
输入信息
end
输入查找信息个数
for i=0 to n2-1
输入查找信息的编号
如果编号在可用范围内,输出信息
否则输出没找到
end
3.代码截图
4.本题调试过程碰到问题及PTA提交列表情况说明。
答案错误:输出时信息的位置放错了
解决方法:调整了信息的位置输出
部分正确:定义电话的时后给的长度不够
解决方法:加大了电话的数组长度
二、截图本周题目集的PTA最后排名
三、阅读代码
- 编一程序,用指针数组在主函数中输入十个等长的字符串。用另一函数对它们排序,然后在主函数中输出10个已排好序的字符串
#include<stdio.h>
#include<string.h>
void sort(char *[]);
int main()
{
int i;
char str[10][6], *p[10];
printf("please input 10 string:/n");
for(i=0;i<10;i++)//首先将10个str的首地址赋值给10个p[i];
p[i]=str[i];//将第i个字符串的首地址赋予指针数组p的第i个元素;
for(i=0;i<10;i++)
scanf("%s",p[i]);//scanf输入到&p[i]
sort(p);
printf("the output 10 string:/n");
for(i=0;i<10;i++)
printf("%s/n",p[i]);//输出到p[i];
}
void sort(char *s[])
{
char *temp; int i,j;
for(i=0;i<9;i++)
for(j=0;j<9-i;j++)
if(strcmp(*(s+j),*(s+j+1))>0) {
temp=*(s+j);//*(s+j)指向数组指针,我想应该是字符串的首地址;所以可以直接赋值给temp指针;
*(s+j)=*(s+j+1);
*(s+j+1)=temp;
}
}
这道题指针的做法很有借鉴价值,将第i个字符串的首地址赋予指针数组p的第i个元素,后续就不用再拿二维数组的地址来用,简化程序,提高可读性。
- 有n个结构体变量,内含学生学号、姓名和3门课程的成绩。要求输出平均成绩最高的学生的信息(包括学号、姓名、3门课程成绩和平均成绩)。
#include<stdio.h>
#define N 3 //学生数为3
struct student
{
long num;
char name[20];
int score[3];
float aver;
}stu[N];
int main()
{
void input(struct student stu[]);
struct student max(struct student stu[]);
void print(struct student stu);
struct student *p=stu;
input(p);
print(max(p));
return 0;
}
void input(struct student stu[])
{
int i;
printf("请输入%d个学生的信息(学号、姓名、三门课成绩):\n",N);
for(i=0;i<N;i++)
{
scanf("%ld %s %d %d %d",&stu[i].num,stu[i].name,&stu[i].score[0],&stu[i].score[1],&stu[i].score[2]);
stu[i].aver=(stu[i].score[0]+stu[i].score[1]+stu[i].score[2])/3.0;
}
}
struct student max(struct student stu[])
{
int i,m=0;
for(i=1;i<N;i++)
if(stu[i].aver>stu[m].aver) m=i;
return stu[m];
}
void print(struct student stu)
{
printf("\n成绩最高的学生是:\n");
printf("学号:%ld\n姓名:%s\n三门课成绩:%d %d %d\n平均成绩:%5.2f\n\n",
stu.num,stu.name,stu.score[0],stu.score[1],stu.score[2],stu.aver);
}
这道题使用了结构体,但是我觉得更好的地方是用函数来分装代码,整个结构很好,值得借鉴。
四、本周学习总结
1.总结本周学习内容。
结构体、共用体、枚举这种构造数据类型特点。
结构体
struct 结构体名
{
成员表列
} 变量表列;
例:
struct data{
int a;
char b;
double c;
} s1;
结构体变量就像数组一样,但是不同于数组的是,他内部的元素可以不同,而且结构体内部还可以嵌套,这对于数据的分类管理就起到很大作用。
共用体
union 共用体名
{
成员表列
} 变量表列;
列:
union data
{
int i;
char ch;
float f;
} a, b, c;
1.同一个内存段可以用来存放几种不同类型的成员,但是在每一瞬间只能存放其中的一种,而不是同时存放几种。
2.共用体变量中起作用的成员是最后一次存放的成员,在存入一个新成员后,原有成员就失去作用。
3.共用体变量的地址和它的各成员的地址都是同一地址。
4.不能对共用体变量名赋值,也不能企图引用变量名来得到一个值。
5.共用体类型可以出现在结构体类型的定义中,也可以定义共用体数组。反之,结构体也可以出现在共用体类型的定义中,数组也可以作为共用体的成员。
6.共用体变量的初始化。
(1)union data a=b; //把共用体变量初始化为另一个共用体
(2)union data a={123}; //初始化共用体为第一个成员
(3)union data a={.ch='a'}; //指定初始化项目,按照C99标准
7.共用体变量也可以作为函数的参数和返回值。
共用体的使用大大降低编程时内存的占用,但是使用时也要格外小心,不同于结构体数据所占内存不同,共同体占的内存相同,取值只取最后存放的数,所以使用时要注意。
此外结构体与共用体的定义方式差不多,可以结合起来记忆。
枚举
enum 枚举名{
标识符[=整型常数],
标识符[=整型常数],
...
标识符[=整型常数]
} 枚举变量;
例:
enum weekday{sun,mon,tue,wed,thu,fri,sat};
如果枚举没有初始化,即省掉"=整型常数"时, 则从第一个标识符开始,顺次赋给标识符0, 1, 2, ...。但当枚举中的某个成员赋值后,其后的成员按依次加1的规则确定其值。
例如下列枚举说明后,x1, x2, x3, x4的值分别为0, 1, 2, 3。enum Num{x1, x2, x3, x4}x;
当定义改变成
enum Num
{
x1,
x2=0,
x3=50,
x4
}x;
则x1=0, x2=0, x3=50, x4=51
-
枚举中每个成员(标识符)结束符是"," 不是";", 最后一个成员可省略","。
-
初始化时可以赋负数, 以后的标识符仍依次加1。
-
枚举变量只能取枚举说明结构中的某个标识符常量。
-
枚举值是常量,不是变量。不能在程序中用赋值语句再对它赋值。例如对枚举weekday的元素再作以下赋值: sun=5;mon=2;sun=mon; 都是错误的。
-
枚举元素本身由系统定义了一个表示序号的数值,从0 开始顺序定义为0,1,2…。如在weekday中,sun值为0,mon值为1, …,sat值为6。
-
只能把枚举值赋予枚举变量,不能把元素的数值直接赋予枚举变量。如: a=sun;b=mon; 是正确的。而: a=0;b=1; 是错误的。如一定要把数值赋予枚举变量,则必须用强制类型转换,如: a=(enum weekday)2;其意义是将顺序号为2的枚举元素赋予枚举变量a,相当于: a=tue; 还应该说明的是枚举元素不是字符常量也不是字符串常量, 使用时不要加单、双引号。
相比于结构体或共同体,枚举的定义方法有点类似,但有很大区别,如2所提到,以及系统定义数值要非常注意;枚举的使用方便了常量的使用,使代码可读性大大提高。
递归函数原理:
递归(recursion)就是子程序(或函数)直接调用自己或通过一系列调用语句间接调用自己,是一种描述问题和解决问题的基本方法。
递归通常用来解决结构自相似的问题。所谓结构自相似,是指构成原问题的子问题与原问题在结构上相似,可以用类似的方法解决。具体地,整个问题的解决,可以分为两部分:第一部分是一些特殊情况,有>直接的解法;第二部分与原问题相似,但比原问题的规模小。实际上,递归是把一个不能或不好解决的大问题转化为一个或几个小问题,再把这些小问题进一步分解成更小的问题,直至每个小问题都可以直接
解决。因此,递归有两个基本要素:
(1)边界条件:确定递归到何时终止,也称为递归出口。
(2)递归模式:大问题是如何分解为小问题的,也称为递归体。递归函数只有具备了这两个要素,才能在有限次计算后得出结果
在递归函数中,调用函数和被调用函数是同一个函数,需要注意的是递归函数的调用层次,如果把调用递归函数的主函数称为第0层,进入函数后,首次递归调用自身称为第1层调用;从第i层递归调用自身称>为第i+1层。反之,退出第i+1层调用应该返回第i层。
递归函数的内部执行过程:
一个递归函数的调用过程类似于多个函数的嵌套的调用,只不过调用函数和被调用函数是同一个函数。为了保证递归函数的正确执行,系统需设立一个工作栈。具体地说,递归调用的内部执行过程如下:
(1)运动开始时,首先为递归调用建立一个工作栈,其结构包括值参、局部变量和返回地址;
(2)每次执行递归调用之前,把递归函数的值参和局部变量的当前值以及调用后的返回地址压栈;
(3)每次递归调用结束后,将栈顶元素出栈,使相应的值参和局部变量恢复为调用前的值,然后转向返回地址指定的位置继续执行。
总之,递归函数就是将一个复杂的问题分解成几个相似的小问题,调用函数来解决问题。只需考虑问题的分解,及分解到边界时如何解决即可,其他部分交给计算机来解决。
2.罗列本周一些错题。
对于以下结构定义,(*p)->str++中的++加在()。 (2分)
struct { int len; char\ *str; } *p;
A、
指针str上
B、
指针p上
C、
str指向的内容上
D、
语法错误
答案:d 错选:c
分析:*p已经是内容,不能->,如果是p->str++,则++加在指针str上
线性表用顺序实现。请填空写一个求线性表L 中所有奇数之和的算法。
例如:
L=(1,2,3,4,5) 其和为 9(本题结构体定义很不错。)
#include <stdio.h>
#define N 10
typedef struct sqlist
{
int data[N];
int last;
}LIST;
int Total(List list)
{
return sum;
}
void Show(LIST list)
{
int i;
for(i=0;i<=list.last;i++)
printf("%3d", list.data[i]);
printf("\n");
}
int main()
{
LIST list;
int i,sum;
for(i=0;i<=5;i++)
list.data[i]=i;
list.last=5;
Show(list);
sum=Total(list);
printf("sum=%3d\n",sum);
return 0;
}
参考答案
int sum=0;
for(int i=0;i<=list.last;i++)
if(list.data[i]%2)
sum+=list.data[i];
我的作答
int sum=0,i;
for(i=0;i<list.last;i+=2){
sum+=list.data[i];
}
分析,没看清楚题目,题目要的是奇数的和,不是下标