博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
通讯录的输入输出
阅读量:7192 次
发布时间:2019-06-29

本文共 4102 字,大约阅读时间需要 13 分钟。

在实际问题中,一组数据往往具有不同的数据类型。例如,在学生登记表中,姓名为字符型,学号为整型或字符型,年龄为整型,性别为字符型,成绩为整型或实数型别,显然,不能使用一个数组来存放这一组数据。因为数组中各个元素的类型和长度都必须一致,以便于编译系统处理。为了解决这个问题,C语言中给出了另一种构造数据类型–结构。他相当于其他高级语言中的记录。

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

1:结构的定义

定义一个结构的一般形式为:

struct 结构名

{
成员列表
};

2:结构类型变量的说明

说明结构变量有3中方法,以结构stu为例。

struct stu{    int num;    char name[20];    char sex;    float score;}; //说明结构变量struct stu boy1,boy2;

说明变量boy1和boy2为stu结构类型。也可以使用宏定义用一个符号常量来表示一个结构类型,例如

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

还可以在定义结构类型的同时说明结构变量,例如:

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

或者是直接说明结构变量,例如

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

注意:

如果结构变量是全局变量或为静态变量,则可以对它进行 初始化赋值。对局部或自动结构变量不能进行初始化赋值。

3:结构数组

继续使用上面stu的例子:

struct stu boys[20];

4:结构指针变量

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

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

例如,如果要说明一个指向stu的指针变量pstu,可写为:

struct stu *pstu;

当然,也可以在定义stu结构的时候同时说明pstu。与前面变量的声明相同。结构指针变量必须要先赋值后才能使用。赋值是把结构变量的首地址赋予该指针变量,不能把结构名赋予该指针变量,如过boy是被说明为stu类型的结构变量,则”pstu=&boy”是正确的,但是”pstu=&stu”是错误的。

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

程序访问的一般形式为:(*结构指针变量).成员名 或为:

结构指针变量->成员名

例如”(*pstu).num”或者”pstu->num”。

应该注意(pstu)两侧的括号不可少,因为成员符号“.”的优先级高于”“。如果去掉括号协作pstu.num,就等效于”(pstu.num)”,这样意义就不对了。

5:结构指针变量作为函数参数

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

在本例中,假设一个通讯录由以下几项数据信息组成

数据项 类型
姓名 字符串
地址 字符串
邮政编码 字符串
电话号码 字符串

下面请看一下代码的实现:

#include 
#include
#include
#define ZIPLEN 10#define PHONLEN 10struct addr{ char *name; /* 姓名 */ char *address; /* 地址 */ char zip[ZIPLEN]; /* 邮编 */ char phone[PHONLEN]; /* 手机号码 */};int readaddr(struct addr *dpt); int writeaddr(struct addr *dpt);/** * 编制一个包含姓名,地址,邮编和电话的通讯录 * 输入输出函数。 */int main(){ struct addr p[1]; int i,j; for(i=0;readaddr(p+i);i++); for(j = 0;j < i;j++) writeaddr(p+j); puts("Press any key to quit...\n"); getch(); return 0;}/** * 向结构中的成员赋值 * */int readaddr(struct addr *dpt){ int len; char buf[120]; //输入字符串的缓冲区 printf("Please input the Name:\n"); if(scanf("%s",buf)==1){ len = strlen(buf); dpt->name = (char *)malloc(len+1); strcpy(dpt->name,buf); }else return 0; printf("Please input the Address:\n"); if(scanf("%s",buf) == 1){ len = strlen(buf); dpt->address = (char *)malloc(len+1); strcpy(dpt->address,buf); }else{ free(dpt->name); return 0; } printf("Please input the Zip:\n"); if(scanf("%s",buf) == 1){ strncpy(dpt->zip,buf,ZIPLEN-1); }else{ free(dpt->name); free(dpt->address); return 0; } printf("Please input the Phone:\n"); if(scanf("%s",buf) == 1){ strncpy(dpt->phone,buf,PHONLEN-1); }else{ free(dpt->name); free(dpt->address); return 0; } return 1;}/** * 输出通讯录 */ int writeaddr(struct addr *dpt) { printf("Name : %s\n",dpt->name); /* 输出姓名 */ printf("Address : %s\n",dpt->address); /* 输出地址 */ printf("Zip : %s\n",dpt->zip); /* 输出邮编 */ printf("Phone : %s\n",dpt->phone); /* 输出手机号 */ }

下面是运行结果:

这里写图片描述

注意:关于动态内存分配问题:

在数组中,数组的长度是预先定义好的,在整个程序中固定不变。C语言不允许动态数组类型。例如”int n;scanf(“%d”,n);int a[n];”,这是错误的。但是在实际编译过程中,往往会发生这种情况,即所需的内存空间取决于实际输入的数据,而无法预先确定。对于这种问题,用数组的办法很难解决。为了解决上述问题,C语言提供了一些内存管理函数,这些内存管理函数可以按照需要动态分配内存空间,也可以把不再使用的空间收回待用。常用的内存管理函数有3个:

1:分配内存空间函数malloc。调用形式

(类型说明符 *)malloc(size);

在内存的动态存储区中分配一块长度为”size”字节的连续区域。函数的返回值为该区域的首地址。

2:分配内存空间函数 calloc。calloc也用于分配内存空间,调用形式:

(类型说明符 *)calloc(n,size);

在内存动态存储区中分配n快长度为”size”字节的连续区域。函数的返回值为该区域的首地址。

3:释放内存空间函数free.调用形式

free(void *ptr);
释放ptr所指向的一块内存区域,ptr是一个任意类型的指针变量,他指向被释放区域的首地址。被释放区域应是由malloc或calloc函数所分配的区域。

转载于:https://www.cnblogs.com/bobo1223/p/7287574.html

你可能感兴趣的文章
CCNA网络技术实验手册:Cisco IOS备份与升级
查看>>
相关VB.NET文件对象基础知识讲解
查看>>
简单描述Servlet Filter(过滤器) 相关知识
查看>>
生成自增的编号,生成订单号
查看>>
SqlSever2005 一千万条以上记录分页数据库优化经验总结【索引优化 + 代码优化】一周搞定...
查看>>
企业内部IT一体化系列之四:WEB平台 SharePoint服务配置
查看>>
ksh里三个月之外的文件移动脚本
查看>>
MSDN Windows8 中文版 下载地址
查看>>
MYSQL 中实现时间比较的方法
查看>>
支付宝担保交易接口
查看>>
深入浅出三剑客之sed必杀技一例
查看>>
django sitemap设置为https
查看>>
我的友情链接
查看>>
微信内部浏览器打开网页时提示外部浏览器打开遮罩升级版
查看>>
Go语言类型的本质
查看>>
界面主窗体,子窗体的InitializeComponent(构造函数)、Load事件执行顺序
查看>>
java导入导出Excel数据的要点记录
查看>>
汇编2——完整的例子集合
查看>>
TP缓存设计方案解析
查看>>
APIO2010 特别行动队
查看>>