2020-12-20

结构和其他数据形式

一.建立结构声明

 结构声明:描述了一个机构的组织布局。

 struct student
 {
	char num [9];//成员列表
	char name[21];
	float sorce;
 } ;//注意分号不能省略,表示结构布局定义结束

 关键字struct,表明跟在其后的是一个结构,后面是一个可选的标记,程序中可以使用该标记引用该结构。所以在后面程序中可以声明

struct student stu1;

这将stu1声明为一个使用student结构布局的结构变量。

二.定义结构变量

 结构有两层含义:一层含义是“结构布局”,即刚才的示例,其只是告诉编译器如何使用数据,并未分配空间;另一层含义就是在程序中创建结构变量:struct student stu1; 在结构变量的声明中,struct student所起的作用相当于一般声明的int或float.例如:可以定义两个struct student 类型的变量,或者是指向结构体的指针。

struct student stu1,stu2,*ptstudent;

 定义一个结构体可以有以下几种方式:

struct point
{
	int x;
	int y;
};
struct point p1,p2;
struct
{
	int x;
	int y;
}p1,p2;
struct point
{
	int x;
	int y;
}p1,p2;

(一).初始化结构

int a=0;//初始化变量;
int b[7]={0,1,2,3,4,5,6};//初始化数组;
struct student stu1//初始化结构体
 {
	093357843,//独占一行可以提高可读性;
	li lei,//注意要用逗号分隔;
	89.7 
 } ;

(二).访问结构成员
 结构体可以包含多个数据类型,要访问其内部成员使用符号.(点);
例如:stu1.num;
(三).结构的初始化器
 c99和c11为结构提供了初始化器,结构的初始化器使用运算符点和成员名标识的特定元素
struct student stu1= {.num = 896793675, . sorce=87.5, .name=Han meimei; } ;
注意:对特定的成员最后一次赋值才是他实际获得的值。

三.结构数组

(一).声明结构数组

#include <stdio.h>
#include <stdlib.h>

    struct list{
        char name[11];
        int date;
        char num[18];
    }p[12],temp;//定义了结构数组

    int main()
    {
        int n;
        scanf("%d",&n);
        getchar();
        for(int i=0;i<n;i++)
        {
            scanf("%s %d %s",p[i].name,&p[i].date,p[i].num);//注意读入字符串时不用使用运算符&;
        }

        for(int i=1;i<n;i++)//对结构数组按年龄进行排序
        {                   
            for(int j=0;j<n-i;j++)
            {
                if(p[j].date>p[j+1].date)
                {     
                    temp=p[j];
                    p[j]=p[j+1];
                    p[j+1]=temp;
                }
            }
        }
        for(int i=0;i<n;i++)
            printf("%s %d %s\n",p[i].name,p[i].date,p[i].num);

        return 0;

 数组的每个元素都是一个list类型的数组。p[0]是第一个list类型的结构变量,数组名p本身不是结构名,而是一个数组名,该数组中的每个元素都是struct list 类型的结构变量。
(二).标识结构数组的成员
举一个例子以便清楚的理解

p//一个list结构的数组;
p[2]//一个数组元素,该元素是list结构;
p[2].name//一个char数组;
p[2].name[3]//数组p[2]元素的name成员的一个字符;

四.嵌套结构

struct names {
    char first[20];
    char last[20];
};
struct guy {
    struct names handle;//结构体嵌套,找到name,再访问期内部成员
    char favfood[20];
    char job[20];
    float income;
};

五.指向结构的指针

声明结构指针:

struct guy *him
/* 嵌套结构示例 */
#include <stdio.h>
#define LEN 20
const char * msgs[5] =
{
    "   Thank you for the wonderful evening, ",
    "You certainly prove that a ",
    "is a special kind of guy. We must get together",
    " and have a few laughs"
};

struct names {
    char first[LEN];
    char last[LEN];
};

struct guy {
    struct names handle;
    char favfood[LEN];
    char job[LEN];
    float income;
};

int main(void)
{
	struct guy fellow[2] = {
	    {
	        { "Ewen","Villard" },
	        "grilled salmon",
	        "personality coach",
	        68112.00
	    },
	    {
	       { "Rodney","Swillbelly" },
	       "tripe",
	       "tabloid editor",
	       432400.00
	    }
	};
	struct guy * him; /* 这是一个指向结构的指针 */

	printf("address #1: %p #2: %p\n",&fellow[0],&fellow[1]);
	him = &fellow[0]; /* 告诉编译器该指针指向何处 */
	printf("pointer #1: %p #2: %p\n",him,him + 1);
	printf("him->inicome is $%.2f; (*him).income is $%.2f\n",him->income,(*him).income);

	him++; /* 指向下一个结构 */
	printf("him->favfood is %s; him->handle.last is %s\n",him->favfood,him->handle.last);

	return 0;
}

(一).用指针访问成员
 法一:使用->
如果him==&barney,那么him->income即是barney.income;
 法二:以顺序指定结构成员的值:
如果him==&fellow[0],那么him==fellow[0],因为&与是一对互逆运算符
即:fellow[0].income==(*him).income
注意:必须使用圆括号,因为.的运算符比*高

六.向函数传递结构的信息

1, 传递结构成员:可以将结构体中的成员作为函数参数;
2,传递结构的地址:将结构(或结构中某个成员)地址作为参数;
3,传递结构:将结构作为参数;

七.联合

 联合体是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。可以定义一个带有多成员的联合体,但是任何时候只能有一个成员带有值。联合体提供了一种使用相同的内存位置的有效方式。
定义联合体 为了定义联合体,必须使用 union 语句,方式与定义结构类似。union 语句定义了一个新的数据类型,带有多个成员。union 语句的格式如下:

union hold {
	int digit;
	double bigfl;
	char letter;
};

 根据以上形式声明的结构可以储存一个 int 类型、一个 double 类型和 char 类型的值。然而,声明的联合只能储存一个 int 类型的值或一个 double 类型的值或 char 类型的值。

八.枚举类型

 可以用枚举类型声明符号名称来表示整型常量。使用 enum 关键字,可以创建一个新“类型”并指定它可具有的值(实际上,enum 常量是 int 类型,因此,只要能使用 int 类型的地方就可以使用枚举类型)。枚举类型的目的是提高程序的可读性。它的语法与结构的语法相同。例如,可以这样声明:

enum spectrum {red,orange,yellow,green,blue,violet};
enum spectrum color;

 第 1 个声明创建了 spectrum 作为标记名,允许把 enum spectrum 作为一个类型名使用。第 2 个声明使 color 作为该类型的变量。第 1 个声明中花括号内的标识符枚举了 spectrum 变量可能有的值。因此,color 可能得值是 red,orange,yellow 等。这些符号常量被称为没巨幅(enumerator)。然后,便可这样用:

int c;
color = blue;
if(color == yellow)
	...;
for(color = red; color <= violet; color++)
	...;

 虽然枚举符是 int 类型,但是枚举变量可以是任意整数类型,前提是该整数类型可以储存枚举常量。例如,spectrum 的枚举符范围是 0 ~ 5,所以编译器可以用 unsigned char 类表示 color 变量。
(一).enum常量
 blue 和 red 到底是什么?从技术层面看,它们是 int 类型的常量。例如,假定有前面的枚举声明,可以这样写:
printf("red =%d, orange = %d\n",red,orange);
输出 red = 0, orange = 1;
 red 成为一个有名称的常量,代表整数 0。类似地,其他标识符都是有名的常量,分别代表 1 ~ 5。只要是能使用整型常量的地方就可以使用枚举常量。例如,在声明数组时,可以用枚举常量表示数组的大小;在 switch 语句中,可以把枚举常量作为标签。
 注意:默认情况下,枚举列表中的常量都赋予 0、1、2 等。因此,下面的声明中 nina 的值是 3:enum kids {nippy,slats,skippy,nina,liz};

(二).赋值
 在枚举声明中,可以为枚举常量指定整数值:enum levels ( low = 100, medium = 500, high = 2000};
 如果只给一个枚举常量赋值,没有对后面的枚举常量赋值,那么后面的常量会被赋予后续的值。例如,enum feline {cat,lynx = 10,puma,tiger};那么,cat 的值是 0(默认),lynx、puma 和 tiger 的值分别是 10、11、12。

(三).enum 的用法
 枚举类型的目的是为了提高程序的可读性和可维护性。如果要处理颜色,使用 red 和 blue 比使用 0 和 1 更直观。注意,枚举类型只能在内部使用。如果要输入 color 中 orange 的值,只能输入 1,而不是单词 orange。或者,让程序先读入字符串“orange”,再将其转换为 orange 代表的值。

 因为枚举类型是整数类型,所以可以在表达式中以使用整数变量的方式使用 enum 变量。它们用的 case 语句中很方便。

 程序演示了一个使用 enum 的小程序。该程序示例使用默认值的方案,把 red 的值设置为 0,使之成为指向字符串“red”的指针的索引。

#include <stdio.h>
#include <string.h> /* 提供 strcmp()、strchr() 函数的原型 */
#include <stdbool.h> /* C99 特性 */
char * s_gets(char * st, int n);

enum spectrum {red,orange,yellow,green,blue,violet};
const char * colors[] = {"red","orange","yellow","green","blue","violet"};
#define LEN 30

int main(void)
{
	char choice[LEN];
	enum spectrum color;
	bool color_is_found = false;

	puts("Enter a color (empty line to quit):");
	while(s_gets(choice,LEN) != NULL && choice[0] != '\0')
    {
        for(color = red; color <= violet; color++)
        {
            if(strcmp(choice,colors[color]) == 0)
            {
                color_is_found = true;
                break;
            }
        }
        if(color_is_found)
            switch(color)
        {
            case red : puts("Roses are red.");
                break;
            case orange: puts("Poppies are orange.");
                break;
            case yellow: puts("Sunflowers are yellow.");
                break;
            case green: puts("Grass is green.");
                break;
            case blue: puts("Bluebells are blue.");
                break;
            case violet: puts("Violets are violet.");
                break;
        }
        else
            printf("I don't know about the color %s.\n",choice);
        color_is_found = false;
        puts("Next colot, please (empty line to quit):");

    }
    puts("Goodbye!");

    return 0;
}

char * s_gets(char * st, int n)
{
    char * ret_val;
    char * find;

    ret_val = fgets(st,n,stdin);
    if(ret_val)
    {
        find = strchr(st,'\n'); /* 查找换行符 */
        if(find) /* 如果地址不是 NULL */
            *find = '\0'; /* 在此处房子一个空字符 */
        else
            while(getchar() != '\n')
                continue; /* 清理输入行 */
    }
    return ret_val;
}

九.typedef 简介

 typedef可用于为某一类型自定义名称,相当于改名字的关键字,如:

typedef int x;

 那么在这条声明之后int a=1与x a=1相同,都是设置一个a变量;用typedef来命名一个结构类型时,可以省略该结构的标签:

typedef struct {double x; double y;} rect;

 typedef常用于给复杂类型命名,使用时记住typedef没有创建任何新类型,它只是将原类型改了个名

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值