C语言提供了另外两种构造类型:结构体与公用体,用来存储若干个类型不同但彼此组成一个集合的数据总体。

(1)结构体类型与结构体变量

1.定义

其一般形式为:

struct  结构体类型名{

数据类型1 成员名1;

数据类型2 成员名2;

数据类型3 成员名3;

......

}

定义一个结构体变量只是描述结构体的组织形式,并不意味着将分配一段内存单元来存放个数据项成员。它的作用只是告诉编译系统所定义的结构体类型是有哪些类型的成员构成的,各占多少字节,按什么形式存储,并把他们当作一个整体来处理。

2.结构体变量的定义:

结构体类型的变量的定义有三种方法:

1)先定义结构体类型,再定义结构体变量;struct student{省略成员的定义};struct student stu1,stu2;

2)定义结构体类型的同时,定义结构体变量;struct student{省略成员的定义}stu1,stu2;

3)不定义结构体的类型,直接定义变量。(此时结构体是无名的)struct{省略成员的定义}stu1,stu2;

结构体成员也可以是一个结构体变量,即一个结构体的定义中可以嵌套另外一个结构体的结构体的结构体。

struct date{

  int year;

int month;

int day;

};

struct student{

long int number;

char name[20];

char sex;

struct date birthday;

char addr[30];

};

3.结构体变量的引用

在定义结构体类型变量以后,就可以引用结构体类型变量,如赋值,存取和运算等。遵循以下规则:

1)不能将结构体变量当作一个整体处理;

2)访问带有结构体变量成员的结构体时应采取逐级访问的方式;

3)结构体的成员变量和普通变量一样可以进行各种运算。

4.结构体变量的初始化

结构体类型是数组类型的扩充,只是它的成员项可以具有不同的数据类型:

struct student{

long num;

char name[20];

char sex;

char addr[20];

}s1={2006001,"MenAngel",'m',"anhui hefei"};

(2)结构体数组

结构体数组与普通的变量的数组大致相同:

初始化:

struct student{}stu1={{括号里与单个结构体初始化方式相同},{},{}......};

1)输入3名学生的信息并输出

 #include<stdio.h>
#include<string.h> struct student{
long num;
char name[];
int age;
char sex;
int score;
}; int main(){
struct student stu[];
int i;
printf("学生的数据是:长整型的学号,字符数组的名字,整型的年龄,字符型的性别,整型的分数。\n");
for(i=;i<;i++){
printf("Please input all data of student[%d]\n",i+);
scanf("%ld,%s%d,%c,%d",&stu[i].num,&stu[i].name,&stu[i].age,&stu[i].sex,&stu[i].score);
}
printf("\n num\t name\t age\t sex\t score\n");
for(i=;i<;i++){
printf("%ld\t%s\t%d\t%4c\t%5d\n",stu[i].num,stu[i].name,stu[i].age,stu[i].sex,stu[i].score);
}
return ;
}

本例用是scanf函数输入各成员时,除字符型数组外,其他变量都采用","分隔,而字符数组以回车作为输入的结束。

2)统计候选人得票数。假设有3名候选人,每次输入一个得票人的名字,要求最后输出每个人的得票总数。

 #include<stdio.h>
#include<string.h> struct person
{
char name[];
int count;
} leader[]={"Hu",,"Li",,"Ma",};//结构体数组的赋值 int main(){
int i,j;
char leader_name[];
for(i=;i<=;i++){
scanf("%s",leader_name);
for(j=;j<;j++){
if(strcmp(leader_name ,leader[j].name )==){
leader[j].count++;
}
}
}
for(i=;i<;i++){
printf("%5s:%d\n",leader[i].name,leader[i].count);
}
return ;
}

(3)结构体指针

指向结构体的指针称为结构体指针变量。该变量存放结构体变量的起始地址。结构体指针变量也可以指向结构体数组中的元素。

1.结构体指针变量的定义

struct 结构体类型 *结构体指针

例如:

struct student stu1,*p=&stu1;

在访问结构体变量的成员时:p->num等价于(*p).num;

2.结构体数组指针

一个结构体指针变量可以指向结构体数组,即将结构体数组的起始地址赋给指针变量,这种指针就是结构体指针。

struct student stu1[10],*p=stu1;

(4)结构体类型数据在函数间的传递

函数间不仅可以传递简单变量、数组、指针这些类型的数据,还可以传递结构体类型的数据。函数间结构体类型数据的传递和普通变量一样,可以“按值传递”,也可以“按地址传递”。

1.结构体变量作为函数参数

用结构体变量作为函数实参传递数据:

 #include<stdio.h>

 struct Teacher{
char name[];
float salary;
float reword;
float income;
};
void display(struct Teacher p)
{
printf("\n%s %7.2f %7.2f %7.2f",p.name,p.salary,p.reword,p.income);
p.salary=;
p.reword=;
p.income=p.salary+p.reword;
printf("\n%s %7.2f %7.2f %7.2f",p.name,p.salary,p.reword,p.income);
}
int main(){
struct Teacher teacher;
printf("\nInput name:");
scanf("%s",teacher.name);
teacher.salary=;
teacher.reword=;
teacher.income=teacher.salary+teacher.reword;
display(teacher);
printf("\n%s %7.2f %7.2f %7.2f",teacher.name,teacher.salary,teacher.reword,teacher.income);

调用函数的实参与被调用函数的形参都是结构体变量名。

形参和实参的结构体类型相同,但运行时分配在不同的存储空间,因此,被调用函数不能修改调用函数的值。

2.结构体指针变量作为函数参数

 #include<stdio.h>

 struct student{
long num;
char name[];
float score[];
}stb1={,"LiYing",67.9,78.5,91.2},stb2={,"YangLi",87.9,97.6,90.0}; void output(struct student *p){
printf("%ld\n%s\n%f\n%f\n%f\n",p->num,p->name,p->score[],p->score[],p->score[]);
printf("\n");
}; int main(){
output(&stb1);
output(&stb2);
return ;
}

3.结构体数组作为函数参数

用结构体数组写一个联系人管理的c程序,包括增删改查,打印所有联系人信息五个功能!

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct contacter{
int num;
char name[];
unsigned long linknumber;
};
struct contacter linkers[];
int count=;
//程序开始时的提醒:
void FirstWarn(){
printf("This is a c program used to manange your address book:\n");
printf("Chose different choice,then you will get disfferent function:\n");
printf("1.Establish and save a new contacter:\n");
printf("2.Delete a contacter:\n");
printf("3.Modify a contacter:\n");
printf("4.Search information of a contacter:\n");
printf("5.Print all of your contacters:\n");
}
//第1个功能,用来新建一个联系人
void newContacters(){
getchar();
if(count==){
printf("There is no storage space any more!\n");
}else if(count>=&&count<){
printf("Please input name:\n");
gets(linkers[count].name);
printf("please input his or her telephone number:\n");
scanf("%ld",&linkers[count].linknumber);
linkers[count].num=+count;
count++;
}
}
//用来验证输入的命令数字
void validate(int* p){
if(*p<|*p>){
printf("Warning: No Such order!\n");
printf("Please input a new order again:\n");
scanf("%d",p);
validate(p);
}
}
//第2个功能,实现删除一个联系人
//(1)用号码来删除
void deleteByNumber(int num){
int n;
n=num-;
for(int i=n;i<count;i++){
strcpy(linkers[i].name,linkers[i+].name);
linkers[i].linknumber=linkers[i+].linknumber;
}
count--;
}
//(2)用名字来删除
void deleteByName(char name[]){
for(int i=;i<count;i++)
if(!strcmp(name,linkers[i].name))
deleteByNumber(+i);
}
//第3个功能,实现输入名称修改联系人的信息
void modifyByName(char *name){
for(int i=;i<count;i++){
if(!strcmp(name,linkers[i].name)){
printf("Please input this linker's telephone:\n");
scanf("%d",&linkers[i].linknumber);
}
printf("After modifing:num=%d name=%s telephone=%ld\n",
linkers[i].num,linkers[i].name,linkers[i].linknumber);
}
}
void modifyByNumber(int num){
printf("Please input this linker's name\n");
gets(linkers[num-].name);
printf("Please input this linkers' telephone\n");
scanf("%ld",&linkers[num-].linknumber);
printf("After modifing:num=%d name=%s telephone=%ld\n",
linkers[num-].num,linkers[num-].name,linkers[num-].linknumber);
}
//第4个功能,实现查询功能
int searchByName(char *name,struct contacter *p,int count){
for(int i=;i<count;i++){
if(!strcmp(name,p[i].name)){
printf("The information of this person:\n");
printf("num=%d,name=%15s,telephone=%ld\n",p[i].num,p[i].name,p[i].linknumber);
return ;
}
}
return ;
}
int searchByNumber(int num,struct contacter *p, int count){
if(<=num-&&num-<=count){
printf("num=%d,name=%15s,telephone=%ld\n",
p[num-].num,p[num-].name,p[num-].linknumber);
}
}
//第5个功能,实现打印信息
void printAll(){
for(int i=;i<count;i++){
printf("第%d位联系人:num=%d; name=%15s; telephone=%ld \n",i+,linkers[i].num,linkers[i].name,linkers[i].linknumber);
}
}
int main(){
//在启动程序时自动创建一个包含100个变量的结构体数组
//记录用户的选择
int choice;
FirstWarn();
while(){
printf("Please input a order:\n");
scanf("%d",&choice);
validate(&choice);
switch(choice){
case :{
newContacters();
break;
}
case :{
printf("Chose the way of deleting linkers:\n");
printf("0.By name\n");
printf("1.By Number:\n");
int temp;
scanf("%d",&temp);
if(temp){
int number;
printf("Input the number:\n");
scanf("%d",&number);
deleteByNumber(number);
}else{
char name[];
printf("Print the name of linker who you want to delete:\n");
scanf("%s",name);
deleteByName(name);
}
break;
}
case :{
int list=;
printf("Chose a way to modyfy the contacter:\n");
printf("1.Modify the telephone only(By name)!\n");
printf("0.Modify both name and telephone(By number)!\n");
scanf("%d",&list);
if(list){
char name[];
printf("Please input the name:\n");
getchar();
gets(name);
modifyByName(name);
}else{
int num;
printf("Please input the number:\n");
scanf("%d",&num);
getchar();
modifyByNumber(num);
}
break;
}
case : {
int list=;
printf("Chose a way to search the contacter:\n");
printf("1.search by name!\n");
printf("0.search by number!\n");
scanf("%d",&list);
if(list){
char name[];
printf("Please input the name:\n");
scanf("%s",name);
if(!searchByName(name,linkers,count)){
printf("no such man!");
}
}else{
int num;
printf("Please input the person's number you want to search:\n");
scanf("%d",&num);
searchByNumber(num,linkers,count);
}
break;
}
case : {printAll();
break;}
default:printf("Errors!");break;
}
}
}

由于屏幕小,测试功能的截屏就是以上那么多!

总结遇到的问题:

1.在从键盘输入数据用scanf("%d",n),忘了加&,然而也不报错,检查半天,痛心!应为scanf("%d",&n);

2.本例用记录数组大小的数count,和结构体数组作为全局变量,事实上这样在每个函数中都可以自由更改它们的值。如果使用值传递的方式是不能更改count的值的,也不能更改结构体数组的值,操作起来非常不方便。

3.在用gets()函数,或者scanf()函数接收字符串时一定要确定前面是否有scanf()函数,如果有,确定用getchar();接收上面输入过程产生的回车符。

4.本例用long型数据存储电话号码,但貌似只能有8位整数,unsigned long貌似只能输入9位,无法达到11位的要求。这里就不在详细追究。事实上可以用字符数组来接收电话号码。

c的详细学习(9)结构体与共用体的学习(一)的更多相关文章

  1. 不可或缺 Windows Native (8) - C 语言: 结构体,共用体,枚举,类型定义符

    [源码下载] 不可或缺 Windows Native (8) - C 语言: 结构体,共用体,枚举,类型定义符 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 结构体 ...

  2. C++程序设计之结构体,共用体,枚举和typedef

    [1]结构体的基本功 注意结构体里面可以有很多东西,可以结构体里面包含结构体 #include<iostream> using namespace std; struct Date { i ...

  3. 全国计算机等级考试二级教程-C语言程序设计_第14章_结构体、共用体和用户定义类型

    函数的返回值是结构体类型 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> struct ...

  4. __c语言__结构体、共用体、枚举__笔记

    2017-09-16 21:14:09 结构体,共用体,枚举 1.结构体 把不同的类型整合成一个有机的整体,以便于引用,这个类型就叫做结构体 1)结构体变量的定义方式(3种)和引用成员变量: 定义一个 ...

  5. C++面试常见问题——13结构体与共用体的sizeof

    结构体与共用体的sizeof 结构体的sizeof 结构体变量占用的内存空间大小通常是其基本类型的大小,但是由例外(字节对齐机制) struct S1{ char c[5]; int a; doubl ...

  6. C语言程序设计(十二) 结构体和共用体

    第十二章 结构体和共用体 当需要表示复杂对象时,仅使用几个基本数据类型显然是不够的 根本的解决方法是允许用户自定义数据类型 构造数据类型(复合数据类型)允许用户根据实际需要利用已有的基本数据类型来构造 ...

  7. C语言------结构体和共用体

    仅供借鉴.仅供借鉴.仅供借鉴(整理了一下大一C语言每个章节的练习题.没得题目.只有程序了) 文章目录 1 .实训名称 2 .实训目的及要求 3.源代码及运行截图 4 .小结 1 .实训名称 实训8:结 ...

  8. c的详细学习(10)结构体与共用体的学习(二)

    在c语言中,结构体数据类型与共用体数据类型都属于构造类型.共用体与结构体数据类型在定义上十分相似,但它们在存储空间的占用分配上有本质的区别.结构体变量是各种类型数据的集合,各成员占据不同的存储空间,而 ...

  9. ndk学习之C语言基础复习----结构体、共用体与C++开端

    自己实现sprintf功能: 关于C中的系统函数sprintf在上次[https://www.cnblogs.com/webor2006/p/7545627.html]学习中已经用到过了,这里再来回顾 ...

随机推荐

  1. 未能从程序集“Oracle.ManagedDataAccess”加载 “OracleInternal.Common.ConfigBaseClass”

    使用VS2015做项目的过程中一直使用的服务器上的oracle数据库,后来想学习一下oracle,就在本机安装了oracle.可没想到本来运行好好的项目,现在不能运行了.项目是使用的Abp框架,当运行 ...

  2. [译] 回调地狱——JavaScript异步编程指南

    原文:Callback Hell 什么是 “回调地狱”? 在 JavaScript 中,我们经常通过回调来实现异步逻辑,一旦嵌套层级多了,代码结构就容易变得很不直观,最后看起来像这样: fs.read ...

  3. Application provided invalid, non monotonically increasing dts to muxer in stream

    很多同学在使用Ffmpeg过程中都遇到Application provided invalid, non monotonically increasing dts to muxer in stream ...

  4. 遍历list,字典

    private void Form1_Load(object sender, EventArgs e) { List<int> ids = new List<int>(); i ...

  5. 从两张Excel表所想到的

    从两张Excel表所想到的 前几日,客服妹子发过来几张表,让我给她做下匹配,然后做了,想了,便有了这篇博文,不由感慨,看似简简单单的两张Excel表其实藏着好多东西,记叙如下,与君共勉. 最初的需求: ...

  6. docker 报错 Error response from daemon: driver failed programming external connectivity on endpoint mynginx

    Error response from daemon: driver failed programming external connectivity on endpoint mynginx (7d1 ...

  7. hdu 1159(Common Subsequence)简单dp,求出最大的公共的字符数

    Common Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  8. android open source

    https://github.com/Cleveroad https://github.com/ddwhan0123/Useful-Open-Source-Android https://github ...

  9. 【JMeter4.0学习(十)】之JMeter函数简单运用以及结合正则表达式提取器

    下面来简单的举个栗子: 首先,把函数和正则表达式提取器放在一块来介绍,如下所示: 1.结构完整展示,下面再一步一步创建添加: 2.添加线程组: 3.首先添加HTTP请求1 4.添加结果树后,运行后查看 ...

  10. 从头认识java-17.5 堵塞队列(以生产者消费者模式为例)

    这一章节我们来讨论一下堵塞队列.我们以下将通过生产者消费者模式来介绍堵塞队列. 1.什么是堵塞队列?(摘自于并发编程网对http://tutorials.jenkov.com/java-concurr ...