“结构”是一种构造类型,它是由若干“成员”组成的。每一个成员可以是一个基本数据类型或者又是一个构造类型。结构既是一种“构造”而成的数据类型,那么在说明和使用之前必须先定义它,也就是构造它。如同在说明和调用函数之前要先定义函数一样。

一、定义结构数组

定义一个结构的一般形式为:
    struct 结构名{
        成员表列
    };
成员表列由若干个成员组成,每个成员都是该结构的一个组成部分。对每个成员也必须作类型说明,其形式为:
    类型说明符 成员名;

成员名的命名应符合标识符的书写规定。例如:

struct stu{
int num;
char name[20];
char sex;
float score;
};

  在这个结构定义中,结构名为stu,该结构由4个成员组成。第一个成员为num,整型变量;第二个成员为name,字符数组;第三个成员为sex,字符变量;第四个成员为score,实型变量。应注意在括号后的分号是不可少的。结构定义之后,即可进行变量说明。凡说明为结构stu的变量都由上述4个成员组成。由此可见, 结构是一种复杂的数据类型,是数目固定,类型不同的若干有序变量的集合。

二、说明结构变量

1)、先定义结构,再说明结构变量

如:

 struct stu{
int num;
char name[];
char sex;
float score;
};
struct stu boy1,boy2;

说明了两个变量boy1和boy2为stu结构类型。

也可以用宏定义使一个符号常量来表示一个结构类型。例如:

#define STU struct stu
STU{
int num;
char name[];
char sex;
float score;
};
STU boy1,boy2;

2)在定义结构类型的同时说明结构变量

例如:

 struct stu{
int num;
char name[];
char sex;
float score;
}boy1,boy2;

这种形式的说明的一般形式为:
    struct 结构名{
        成员表列
    }变量名表列;

3) 直接说明结构变量。
例如:

 struct{
int num;
char name[];
char sex;
float score;
}boy1,boy2;

这种形式的说明的一般形式为:
    struct{
        成员表列
    }变量名表列;

第三种方法与第二种方法的区别在于第三种方法中省去了结构名,而直接给出结构变量。三种方法中说明的boy1、boy2变量都具有下图所示的结构。

说明了boy1、boy2变量为stu类型后,即可向这两个变量中的各个成员赋值。在上述stu结构定义中,所有的成员都是基本数据类型或数组类型。成员也可以又是一个结构,即构成了嵌套的结构。例如,下图给出了另一个数据结构。

按图可给出以下结构定义:

structdate{
int month;
int day;
int year;
};
struct{
int num;
char name[];
char sex;
structdate birthday;
float score;
}boy1,boy2;

首先定义一个结构date,由month(月)、day(日)、year(年) 三个成员组成。在定义并说明变量 boy1 和 boy2 时,其中的成员birthday被说明为data结构类型。成员名可与程序中其它变量同名,互不干扰。

三、结构变量的赋值

在程序中使用程序变量时,往往不把它作为一个整体来使用。在ANSIC中除了允许具有相同类型的结构变量相互赋值意外,一般对结构变量的使用,包括赋值、输入、输出、运算等都是用过结构变量的成员来实现的。

表示结构变量成员的一般形式是:

结构变量名.成员名

例如:boy1.num    即第一个人的学号

boy2.sex          即第二个人的性别

如果成员本身又是一个结构则必须逐级找到最低级的成员才能使用。例如:

boy1.birthday.month

即第一个人出生的月份成员可以在程序中单独使用,与普通变量完全不同。

结构变量的赋值就是给各成员赋值。可用输入语句或赋值语句来完成。

【例11-1】给结构变量赋值并输出其值。

 main(){
struct stu{
int num;
char *name;
char sex;
float score;
} boy1,boy2;
boy1.num=;
boy1.name="Zhang ping";
printf("input sex and score\n");
scanf("%c %f",&boy1.sex,&boy1.score);
boy2=boy1;
printf("Number=%d\nName=%s\n",boy2.num,boy2.name);
printf("Sex=%c\nScore=%f\n",boy2.sex,boy2.score);
}

本程序中用赋值语句给num和name两个成员赋值,name是一个字符串指针变量。用scanf函数动态地输入sex和score成员值,然后把boy1的所有成员的值整体赋予boy2。最后分别输出boy2的各个成员值。本例表示了结构变量的赋值、输入和输出的方法

和其他类型变量一样,对结构变量可以在定义时进行初始化赋值。

 main(){
struct stu{ /*定义结构*/
int num;
char *name;
char sex;
float score;
}boy2,boy1={,"Zhang ping",'M',78.5};
boy2=boy1;
printf("Number=%d\nName=%s\n",boy2.num,boy2.name);
printf("Sex=%c\nScore=%f\n",boy2.sex,boy2.score);
}

本例中,boy2、boy1均被定义为外部结构变量,并对boy1作了初始化赋值。在main函数中,把boy1的值整体赋予boy2,然后用两个printf语句输出boy2各成员的值。

 四、C语言结构体数组的定义

数组的元素也可以是结构类型的。因此可以构成结构型数组。结构数组的每一个元素都是具有相同结构类型的下标结构变量。在实际应用中,经常用结构数组来表示具有相同数据结构的一个群体。如一个班的学生档案,一个车间职工的工资表等。

方法和结构变量类似,只需说明它维数组类型即可。例如:

 struct stu{
int num;
char *name;
char sex;
float score;
}boy[];

定义了一个结构数组boy,共有5个元素,boy[0]~boy[4]。每个数组元素都具有struct stu的结构形式。对结构数组可以作初始化赋值。例如:

 struct stu{
int num;
char *name;
char sex;
float score;
}boy[]={
{,"Li ping","M",},
{,"Zhang ping","M",62.5},
{,"He fang","F",92.5},
{,"Cheng ling","F",},
{,"Wang ming","M",};
}

当对全部元素做初始化赋值时,也可不给出数组长度。

【例11-3】计算学生的平均成绩和不及格的人数。

 struct stu{
int num;
char *name;
char sex;
float score;
}boy[]={
{,"Li ping",'M',},
{,"Zhang ping",'M',62.5},
{,"He fang",'F',92.5},
{,"Cheng ling",'F',},
{,"Wang ming",'M',}
};
main(){
int i,c=;
float ave,s=;
for(i=;i<;i++){
s+=boy[i].score;
if(boy[i].score<) c+=;
}
printf("s=%f\n",s);
ave=s/;
printf("average=%f\ncount=%d\n",ave,c);
}

本例程序中定义了一个外部结构数组boy,共5个元素,并作了初始化赋值。在main函数中用for语句逐个累加各元素的score 成员值存于s之中,如score的值小于60(不及格)即计数器C加1,循环完毕后计算平均成绩,并输出全班总分,平均分及不及格人数。

【例11-4】建立同学通讯录

 #include"stdio.h"
#define NUM 3
struct mem{
char name[];
char phone[];
};
main(){
struct mem man[NUM];
int i;
for(i=;i<NUM;i++){
printf("input name:\n");
gets(man[i].name);
printf("input phone:\n");
gets(man[i].phone);
}
printf("name\t\t\tphone\n\n");
for(i=;i<NUM;i++)
printf("%s\t\t\t%s\n",man[i].name,man[i].phone);
}

本程序中定义了一个结构mem,它有两个成员name和phone用来表示姓名和电话号码。在主函数中定义man为具有mem 类型的结构数组。在for语句中,用gets函数分别输入各个元素中两个成员的值。然后又在for语句中用printf语句输出各元素中两个成员值。

 五、C语言中指向结构体变量的指针

一个指针变量当用来指向一个结构变量时,称之为结构指针变量。结构指针变量中的值是所指向的结构变量的首地址。通过结构指针即可访问该结构变量,这与数组指针和函数指针的情况是相同的。

结构指针变量说明的一般形式为:

struct 结构名 *结构指针变量名

例如,在前面的例题中定义了stu这个结构,如要说明一个指向stu的指针变量pstu,可写为:
    struct stu *pstu;
当然也可在定义stu结构时同时说明pstu。与前面讨论的各类指针变量相同,结构指针变量也必须要先赋值后才能使用。

赋值时把结构变量的首地址赋予该指针变量,不能把结构名赋予该指针变量。如果boy是被说明为stu类型的结构变量,则:

pstu=&boy;

是正确的,而:

pstu=&stu
是错误的。

结构名和结构变量时两个不同的概念,不能混淆。结构名只能表示一个结构形式,编译系统并不对它分配内存空间。只有当某变量被说明为这种类型的结构时,才对该变量分配存储空间。因此上面&stu这种写法是错误的,不可能去取一个结构名的首地址。有了结构指针变量,就能更方便地访问结构变量的各个成员。

其访问的一般形式为:

(*结构指针变量).成员名

或为:

结构指针变量->成员名

例如:

(*pstu).num
或者:
    pstu->num

应该注意(*pstu)两侧的括号不可少,因为成员符“.”的优先级高于“*”。如去掉括号写作*pstu.num则等效于*(pstu.num),这样,意义就完全不对了。下面通过例子来说明结构指针变量的具体说明和使用方法。

例11-5

struct stu{
int num;
char *name;
char sex;
float score;
} boy1={,"Zhang ping",'M',78.5},*pstu;
main(){
pstu=&boy1;
printf("Number=%d\nName=%s\n",boy1.num,boy1.name);
printf("Sex=%c\nScore=%f\n\n",boy1.sex,boy1.score);
printf("Number=%d\nName=%s\n",(*pstu).num,(*pstu).name);
printf("Sex=%c\nScore=%f\n\n",(*pstu).sex,(*pstu).score);
printf("Number=%d\nName=%s\n",pstu->num,pstu->name);
printf("Sex=%c\nScore=%f\n\n",pstu->sex,pstu->score);
}

本例程序定义了一个结构stu,定义了stu类型结构变量boy1并作了初始化赋值,还定义了一个指向stu类型结构的指针变量pstu。在main函数中,pstu被赋予boy1的地址,因此pstu指向boy1.然后再printf语句内用三种形式输出boy1的各个成员值。从运行结构可以看出:

结构变量.成员名
    (*结构指针变量).成员名
    结构指针变量->成员名
这三种用于表示结构成员的形式是完全等效的。

六:C语言指向结构体数组的指针

指针变量可以指向一个结构数组,这是结构指针变量的值是整个结构数组的首地址。结构指针变量也可指向结构数组的一个元素,这时结构指针变量的值是该结构数组元素的首地址。

设ps为指向结构数组的指针变量,则ps也指向该结构数组的0号元素,ps+1指向1号元素,ps+i则指向i号元素。这与普通数组的情况是一致的。

【例11-6】用指针变量输出结构数组。

 struct stu{
int num;
char *name;
char sex;
float score;
}boy[]={
{,"Zhou ping",'M',},
{,"Zhang ping",'M',62.5},
{,"Liou fang",'F',92.5},
{,"Cheng ling",'F',},
{,"Wang ming",'M',}
};
main(){
struct stu *ps;
printf("No\tName\t\t\tSex\tScore\t\n");
for(ps=boy;ps<boy+;ps++)
printf("%d\t%s\t\t%c\t%f\t\n",ps->num,ps->name,ps->sex,ps->score);
}

在程序中,定义了stu结构类型的外部数组boy并作了初始化赋值。在main函数内定义ps为指向stu类型的指针。在循环语句for的表达式1中,ps被赋予boy的首地址,然后循环5次,输出boy数组中各成员值。

应该注意的是,一个结构指针变量虽然可以用来访问结构变量或结构数组元素的成员,但是,不能使它指向一个成员。也就是说不允许取一个成员的地址来赋予它。因此,下面的赋值是错误的。

ps=&boy[1].sex;
而只能是:
    ps=boy;(赋予数组首地址)

或者是:
    ps=&boy[0];(赋予0号元素首地址)

七、C语言结构体指针变量作函数参数

在ANSI C标准中允许用结构变量作函数参数进行整体传送。但是这种传送要将全部成员逐个传送,特别是成员为数组时将会使传送的时间和空间开销很大,严重地降低了程序的效率。因此最好的办法就是使用指针,即用指针变量作函数参数进行传送。这时由实参传向形参的只是地址,从而减少了时间和空间的开销

【例11-7】计算一组学生的平均成绩和不及格人数。用结构指针变量作函数参数编程。

 struct stu{
int num;
char *name;
char sex;
float score;
}boy[]={
{,"Li ping",'M',},
{,"Zhang ping",'M',62.5},
{,"He fang",'F',92.5},
{,"Cheng ling",'F',},
{,"Wang ming",'M',}
};
main(){
struct stu *ps;
void ave(struct stu *ps);
ps=boy;
ave(ps);
}
void ave(struct stu *ps){
int c=,i;
float ave,s=;
for(i=;i<;i++,ps++){
s+=ps->score;
if(ps->score<) c+=;
}
printf("s=%f\n",s);
ave=s/;
printf("average=%f\ncount=%d\n",ave,c);
}

本程序中定义了函数ave,其形参为结构指针变量ps。boy被定义为外部结构数组,因此在整个源程序中有效。main函数中定义说明了结构指针变量ps,并把boy的首地址富裕它,使ps指向boy数组。然后以ps作为实参调用ave。在函数ave中完成计算平均成绩和统计不及格人数的工作并输出结果。

由于本程序全部采用指针变量作运算和处理,故速度更快,程序效率更高。

C结构体【转】的更多相关文章

  1. Go结构体实现类似成员函数机制

    Go语言结构体成员能否是函数,从而实现类似类的成员函数的机制呢?答案是肯定的. package main import "fmt" type stru struct { testf ...

  2. C#基础回顾(二)—页面值传递、重载与重写、类与结构体、装箱与拆箱

    一.前言 -孤独的路上有梦想作伴,乘风破浪- 二.页面值传递 (1)C#各页面之间可以进行数据的交换和传递,页面之间可根据获取的数据,进行各自的操作(跳转.计算等操作).为了实现多种方式的数据传递,C ...

  3. go语言结构体

    定义: 是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体. 成员: 每个值称为结构体的成员. 示例: 用结构体的经典案例处理公司的员工信息,每个员工信息包含一个唯一的员工编号.员工的名字. ...

  4. C语言中的结构体

    用户自己建立自己的结构体类型 1.  定义和使用结构体变量 (1).结构体的定义 C语言允许用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体. (2).声明一个结构体类型的一般形式为: ...

  5. C++_系列自学课程_第_12_课_结构体

    #include <iostream> #include <string> using namespace std; struct CDAccount { double bal ...

  6. java socket传送一个结构体给用C++编写的服务器解析的问题

    另一端是Java写客户端程序,两者之间需要通信.c++/c接收和发送的都是结构体,而Java是直接发送的字节流或者byte 数组.解决方法:c++/c socket 在发送结构体的时候其实发送的也是字 ...

  7. swift学习笔记3——类、结构体、枚举

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  8. HDOJ 1009. Fat Mouse' Trade 贪心 结构体排序

    FatMouse' Trade Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  9. C语言结构体对齐

    1.结构体变量中的元素如何访问? (1)数组中元素的访问方式:表面上有2种方式(数组下标方式和指针方式):实质上都是指针方式访问.(2)结构体变量中的元素访问方式:只有一种,用.或者->的方式来 ...

  10. C与指针(结构体指针,函数指针,数组指针,指针数组)定义与使用

    类型 普通指针 指针数组(非指针类型) 数组指针 结构体指针 函数指针 二重指针 定义方式 int *p; int *p[5]; int (*p)[5]; int a[3][5]; struct{.. ...

随机推荐

  1. Quartus II 项目文件分类及内容

  2. 成都优步uber司机第三组奖励政策

    今天成都优步又推出了优步司机第三组,第一二组的奖励大家都晓得,但是第三组的奖励怎么样呢?还是先看看官方给出的消息. 滴滴快车单单2.5倍,注册地址:http://www.udache.com/如何注册 ...

  3. SQl 语句 表的连接

    当涉及到多个表查询时就需要使用将表连接的方法进行查询. SQL语句连接的方式根本上分为5种: •EQUI JOIN •SEMI JOIN 3 •ANTI JOIN 4 •CROSS JOIN •DIV ...

  4. 创龙DSP6748学习之RS485收发

    1. 先看下原理图,第一个问题,RS485其实就是使用的串口USART1,同时485的输出脚之间接120欧姆的电阻. 遇到个问题,为什么有两个使能引脚?还有RS485_A和RS485_B为什么分别接上 ...

  5. Windows Server 2008 R2 安装域

    在Windows Server 2008 R2里面安装域. 1.首先在"服务"里面添加"角色": 2.选择对应的域角色 3.安装完成后要启动配置向导 4.选择新 ...

  6. OpenSUSE 11 安装Qt5.0,失败,失败,失败,留个坑,以后来填,万一实现了呢

    我又来无耻的写问题来了,这次还真的是没有解决,线留坑吧,万一以后实现了. 同样,这次也是以恶搞网友说听说想在open suse 上面安装5.0版本以后的Qt,自己折腾好几没有成功. 我一想,哎,这不是 ...

  7. Jenkis 无法下载插件问题解决

    在新机器上安装jenkins后,安装插件报如下错误 sun.security.provider.certpath.SunCertPathBuilderException: unable to find ...

  8. 配置vConsole调试console

    1.使用 npm 安装: npm install vconsole 再使用webpack,然后js代码中 import VConsole from 'vconsole/dist/vconsole.mi ...

  9. 211. String Permutation【LintCode by java】

    Description Given two strings, write a method to decide if one is a permutation of the other. Exampl ...

  10. ubuntu networking 与 network-manager

    刚遇到的坑,因为操作不当导致网络中断,于是手动配置了/etc/network/interfaces , 修复了系统之后发现ubuntu-desktop中的有线链接不见了,百度了一下说是networki ...