结构体
- 结构体基本格式:
struct Name{
//一些基本的数据结构或者自定义的数据类型
};
Eg.
struct studentInfo {
int id;
char gender;
char name[20];
char major[20];
}Alice, Bob, sru[1000];
- 结构体不能定义自己本身,但是可以定义自身类型的指针变量
Eg
struct node {
node n;//错误!!! 不能定义node型变量
node* next;//可以定义node*型指针变量
};
- 访问结构体有两种方法,"." 操作和 "->"操作
Eg
struct studentInfo {
int id;
char name[20];
studentInfo* next;
}stu, *p;
访问stu中变量的写法如:stu.id / stu.name / stu.next;
访问指针变量p中元素的写法如:
(*p).id / (*p).name / (*p).next / p->id / p->name / p->next
- 构造函数初始化结构体
构造函数:不需要写返回类型,且函数名和结构体名相同
struct studentInfo {
int id;
char gender;
//下面的参数用以对结构体内部变量进行赋值
studentInfo(int _id, char _gender) {
//赋值
id = _id;
gender = _gender;
}
或者写成一行
struct studentInfo {
int id;
char gender;
//下面的参数用以对结构体内部变量进行赋值
studentInfo(int _id, char _gender):id(_id),gender(_gender){}
};
这样在需要的时候就可以直接对结构体变量进行赋值了:
studentInfo stu = studentInfo(10086, 'm');
但是,如果自己重新定义了构造函数,就不能不经过初始化就定义结构体变量,即默认生成的构造函数 studentInfo{}
此时被覆盖了,为了既能不初始化就定义结构体变量,又能享受初始化带来的便捷,可以手动加上“studentInfo"。这意味着,只要参数个数和类型不完全相同,就可以定义任意多个构造函数,以适应不同的初始化场合
Eg
struct studentInfo {
int id;
char gender;
//用以不初始化就定义结构体变量
studentInfo(){} //没有分号!
//只初始化gender
studentInfo(char _gender) {
gender = _gender;
}
//同时初始化id和gender
studentInfo(int _id, char _gender):id(_id),gender(_gender){}
}stu,*p;
Eg
struct Point {
int x, y;
Point() {}
Point(int _x, int _y) :x(_x), y(_y) {}
}pt[10];
int main()
{
int num = 0;
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
pt[num++] = Point(i, j);
}
}
for (int i = 0; i < num; i++) {
printf("%d,%d\n", pt[i].x, pt[i].y);
}
return 0;
}
共用体
-
共用体(也称联合)也是一种构造的数据类型,它是将不同类型的数据组织在一起共同占用同一段内存的一种构造数据类型。
-
共用体与结构体的类型声明方法类似
-
共用体的关键字为union
-
一般形式:
union 共用体名称 {
成员列表;
}; -
结构体与共用体都可匿名,匿名后在之后的程序中不可再声明。
-
结构体与共用体的区别:
结构体变量所占内存长度是各成员占的内存长度之和,每个成员分别占有自己的内存单元
共用体变量所占内存长度是最长的成员的长度。即共用体变量的地址和它的各成员的地址是同一地址。 -
共用体变量的引用:
对共用体变量的使用,包括赋值、使用只能是对变量的成员进行。
表示方法: 共用体变量名.成员名 -
不允许对共用体变量作初始化赋值,赋值只能在程序中进行
-
https://wenku.baidu.com/view/e2c46dfd83d049649a665848.html
练习
C语言11.1
题目描述
完成一个对候选人得票的统计程序。假设有3个候选人,名字分别为Li,Zhang和Fun。使用结构体存储每一个候选人的名字和得票数。记录每一张选票的得票人名,输出每个候选人最终的得票数。结构体可以定义成如下的格式:
struct person {
char name[20];
int count; }leader[3] = {“Li”, 0, “Zhang”, 0, “Fun”, 0};输入 第一行有一个整数n,表示以下有n张选票信息将会输入。保证n不大于100。
以后的n行中,每一行包含一个人名,为选票的得票人。保证每一个人名都是Li,Zhang和Fun中的某一个。输出 有三行,分别为Li,Zhang和Fun每人的得票数。格式为首先输出人名,其后输出一个冒号,最后输出候选人的得票数。
请注意行尾输出换行。
- 遇到问题
如果if语句写成if(namei==leader[j].name),程序无法正常运行。用strcmp函数解决了这个问题,猜测其中的原因是字符串不能直接比较大小
#include <cstdio>
#include <cstring>
int main()
{
struct person {
char name[20];
int count;
}leader[3] = { "Li",0,"Zhang",0,"Fun",0 };
int n;
char namei[20] = {};
scanf("%d\n", &n);
if (n > 100)
return 0;
for (int i = 0; i < n; i++)
{
scanf("%s", namei);
for (int j = 0; j <= 2; j++)
{
//如果下面这个if语句写成if(namei==leader[j].name),程序无法正常运行。
if (!strcmp(namei, leader[j].name))
{
leader[j].count ++;
}
}
}
for (int i = 0; i < 3; i++)
{
printf("%s:%d\n", leader[i].name, leader[i].count);
}
return 0;
}
C语言11.2
题目描述
定义一个结构体student,存储学生的学号、名字、性别和年龄,读入每个学生的所有信息,保存在结构体中,并输出。结构体student的定义如下:
struct student {
int num;
char name[20];
char sex;
int age; }; 本题要求使用指向结构体数组的指针进行输入和输出。输入 第一行有一个整数n,表示以下有n个学生的信息将会输入。保证n不大于20。
以后的n行中,每一行包含对应学生的学号、名字、性别和年龄,用空格隔开。保证每一个人名都不包含空格且长度不超过15,性别用M和F两个字符来表示。输出 有n行,每行输出一个学生的学号、名字、性别和年龄,用空格隔开。 请注意行尾输出换行。
#include <cstdio>
#include <cstring>
int main()
{
struct student {
int num;
char name[20];
char sex;
int age;
student(){};
}*p,stu[20];//不可以没有stu[20]
p = stu;//!!!看这里
int n;
scanf("%d\n", &n);
for (int i = 0; i < n; i++)
{
//scanf("%d %s %c %d", &((p+i)->num), ((p + i)->name), &((p + i)->sex),&((p + i)->age));
//这里要取址符!!
scanf("%d %s %c %d", &((*(p + i)).num), (*(p + i)).name, &((*(p + i)).sex), &(( *(p + i)).age));
}
for (int i =0 ; i < n; i++)
{
printf("%d %s %c %d\n", (p + i)->num, (p + i)->name, (p + i)->sex, (p + i)->age);
//printf("%d", ((*p).num));
}
return 0;
}
上面的指针这段代码还有一种写法:
for (int i = 0; i < n; i++)
{
scanf("%d %s %c %d", &((*p).num), (*p ).name, &((*p).sex), &(( *(p)).age));
p++;
}
C语言11.4
题目描述
设有若干个人员的数据,其中包含学生和教师。学生的数据中包括:号码、姓名、性别、职业、班级。教师的数据包括:号码、姓名、性别、职业、职务。可以看出,学生和教师所包含的数据是不同的。现在要求把这些数据放在同一个表格中储存,使用结构体中的共用体实现。结构体定义如下:
struct {
int num;
char name[10];
char sex;
char job;
union {
int class;
char position[10];
}category; }; 在以上的结构体中,如果job项为s(学生),则第5项为class(班级);如果job项是t(教师),则第5项为position(职务)。
输入几个人员的数据,将其保存在以上包含共用体的结构体数组中,并输出。输入 第一行有一个整数n,表示以下n行分别表示n个人员的数据。保证n不超过100。
之后的n行,每行有5项用空格隔开的内容。前4项分别为人员的号码(整数)、姓名(长度不超过9的无空格字符串)、性别(字符,m或f)和职业(字符,s或t)。如果第4项是s,则第5项为一个整数,表示班级;如果第4项是t,则第5项为一个长度不超过9的无空格字符串,表示职务。输出 共有n行,与输入格式相同,输出读入的所有内容。 请注意行尾输出换行。
#include <cstdio>
#include <cstring>
int main()
{
struct {
int num;
char name[10];
char sex;
char job;
union {
int classnum;
char position[10];
}category;
}sta[100],*p;
int n;
scanf("%d", &n);
p = sta;
for (int i = 0; i < n; i++)
{
scanf("%d %s %c %c", &((*p).num), (*p).name, &((*p).sex), &((*p).job));
if (((*p).job) == 's') scanf("%d", &((*p).category.classnum));
else if (((*p).job) == 't') scanf("%s", ((*p).category.position));
p++;
}
p = sta;
for (int i = 0; i < n; i++)
{
printf("%d %s %c %c ",((*p).num), (*p).name, ((*p).sex),((*p).job));
if (((*p).job) == 's') printf("%d\n", ((*p).category.classnum));
else if (((*p).job) == 't') printf("%s\n", ((*p).category.position));
p++;
}
return 0;
}
C语言11.7
题目描述
编写两个函数input和print,分别用来输入5个学生的数据记录和打印这5个学生的记录。对于每一个学生,其记录包含了学号、名字、3门课程的成绩共5项。用主函数分别调用input和print函数进行输入和输出。
要求使用结构体数组实现,结构体中包括了每个学生的5项记录。输入 共有5行,每行包含了一个学生的学号(整数)、名字(长度不超过19的无空格字符串)和3门课程的成绩(0至100之间的整数),用空格隔开。
输出 与输入格式相同,每行输出一个学生的所有记录。 请注意行尾输出换行。
#include <cstdio>
#include <cstring>
struct student {
char name[10];
int num;
int score[3];
}stu[5], *p;
void input(student* stu)
{
p = stu;
for (int i = 0; i < 5; i++)
{
scanf("%d %s", &((*p).num),(*p).name);
for (int j = 0; j < 3; j++)
scanf("%d", &((*p).score[j]));
p++;
}
}
void output(student * stu)
{
p = stu;
for (int i = 0; i < 5; i++)
{
printf("%d %s ", (*p).num, (*p).name);
for (int j = 0; j < 3; j++)
{
printf("%d ", (*p).score[j]);
if (j == 2) printf("\n");
}
p++;
}
}
int main()
{
p = stu;
input(p);
p = stu;
output(p);
return 0;
}
C语言11.8
题目描述
有10个学生,每个学生的数据包括学号、姓名、3门课程的成绩。读入这10个学生的数据,要求输出3门课程的总平均成绩,以及个人平均分最高的学生的数据(包括学号、姓名、3门课程成绩、平均分数)。输入
共有10行,每行包含了一个学生的学号(整数)、名字(长度不超过19的无空格字符串)和3门课程的成绩(0至100之间的整数),用空格隔开。输出 第一行包含了3个实数,分别表示3门课程的总平均成绩,保留2位小数,每个数之后输出一个空格。
第二行输出个人平均分最高的学生的数据,与输入数据格式相同。如果有多位个人平均分最高的学生,输出按照输入顺序第一个最高分的学生数据。
请注意行尾输出换行。
#include <cstdio>
#include <cstring>
struct student {
char name[10];
int num;
int score[3];
}stu[10], *p;
void input(student* stu)
{
p = stu;
for (int i = 0; i < 10; i++)
{
scanf("%d %s", &((*p).num),(*p).name);
for (int j = 0; j < 3; j++)
scanf("%d", &((*p).score[j]));
p++;
}
}
void output1(student * stu)
{
for (int i = 0; i < 3; i++)
{
double sum = 0;
p = stu;
for (int j = 0; j < 10; j++)
{
sum += p->score[i];
p++;
}
printf("%.2lf ", (double)(sum/10));
}
printf("\n");
}
void output2(student* stu)
{
p = stu;
double sco[10] = {0},maxsco=0;
int maxnum;
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 3; j++)
{
sco[i] += p->score[j];
}
sco[i] = (double)(sco[i] / 10);
if (sco[i] > maxsco)
{
maxsco = sco[i];
maxnum = i;
}
p++;
}
p = stu + maxnum;
printf("%d %s ", (*p).num, (*p).name);
for (int j = 0; j < 3; j++)
{
printf("%d ", (*p).score[j]);
}
}
int main()
{
p = stu;
input(p);
p = stu;
output1(p);
p = stu;
output2(p);
return 0;
}