C语言结构体和其他数据形式(C Primer Plus 第六版)

简介: C语言结构体和其他数据形式(C Primer Plus 第六版)

前言


这节会学到->运算符和struct结构 学完这些,再去学数据结构就很简单了! 加油!

资源在这

image.png


一、主要内容


关键字:struct、union、typedef

运算符:.    ->

什么是C结构,如何创建结构模板和结构变量

如何访问结构的成员,如何编写处理结构的函数

联合和指向函数的指针


二、生活中的实例


书店老板要去打印一份图书目录。她想打印每本书的各种信息,如作者,书名,出版社、价格等等,这些项目可以存放在不同的数组中,可是用这么多数组表示有点麻烦和繁琐了,因此如果能把图书目录的信息都包含在一个数组里更好,其中每个元素包含一个本书的相关信息

C结构就能满足这个需求


实例


#include <stdio.h>
#include <string.h>
char * s_gets(char * st,int n);
#define MAXTITL 41  /*书名的最大长度+1*/
#define MAXAUTL 31  /*作者姓名的最大长度*/
struct book {   //结构模板:标记是book
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};              //结构模板结束
int main(void)
{
    struct book library;   //把library声明为一个book类型的变量
    printf("Please enter the book title.\n");
    s_gets(library.title,MAXTITL);  //访问title部分
    printf("Now enter the author.\n");
    s_gets(library.author,MAXAUTL);
    printf("Now enter the value.\n");
    scanf("%f",&library.value);
    printf("%s by %s: $%.2f\n",library.title,library.author,library.value);
    printf("%s: \"%s\" ($%.2f)\n",library.author,library.title,library.value);
    printf("Done.\n");
}
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)
            *find = '\0';
        else
            while (getchar() != '\n')
                continue;
    }
    return ret_val;    
}
输出的结果为:
PS D:\Code\C\结构> cd "d:\Code\C\结构\" ; if ($?) { gcc struct.c -o struct } ;
 if ($?) { .\struct }
Please enter the book title.
Now enter the author.
罗贯中
Now enter the value.
99.9
三国演义 by 罗贯中: $99.90
罗贯中: "三国演义" ($99.90)
Done.

程序中创建的结构有3部分,每个部分都称为成员(member))或字段(field)。这3部分中,一部分储存书名,一部分储存作者名,一部分储存价格。下面是必须掌握的3个技巧:

  • 为结构建立一个格式或样式;
  • 声明一个适合该样式的变量;
  • 访问结构变量的各个部分。


三、建立结构声明


结构声明(structure declaration)描述了一个结构的组织布局。声明类似下面这样:


struct book {   //结构模板:标记是book
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};

该声明描述了一个由两个字符数组和一个float类型变量组成的结构。该声明并未创建实际的数据对象,只描述了该对象由什么组成。(有时,我们把结构声明称为模板,因为它勾勒出结构是如何储存数据的.如果读者知道C++的模板,此模板非彼模板,C++中的模板更为强大。)我们来分析一些细节。首先是关键字struct,它表明跟在其后的是一个结构,后面是一个可选的标记(该例中是 book),稍后程序中可以使用该标记引用该结构。所以,我们在后面的程序中可以这样声明: struct book library; 这把library声明为一个使用book 结构布局的结构变量。


四、定义结构变量


结构有两层含义。一层含义是“结构布局”,刚才已经讨论过了。结构布局告诉编译器如何表示数据,但是它并未让编译器为数据分配空间。下一步是创建一个结构变量,即是结构的另一层含义。程序中创建结构变量的一行是: struct book library; 编译器执行这行代码便创建了一个结构变量library。编译器使用book模板为该变量分配空间:个内含MAXTITL个元素的char数组、一个内含MAXAUTL个元素的char数组和一个float类型的变量。这些存储空间都与一个名称library结合在一起 在结构变量的声明中,**struct book所起的作用相当于一般声明中的int或float。**例如,可以定义两个struct book类型的变量,或者甚至是指向struct book类型结构的指针: struct book doyle, panshin, * ptbook;


结构变量 doyle和 panshin中都包含title、author和 value部分。指针 ptbook可以指向doyle,panshin或任何其他book类型的结构变量。从本质上看, book结构声明创建了一个名为structbook的新类型。 就计算机而言,下面的声明:

struct book library;

是以下声明的简化:

struct book { char title [ MAXTITL];

char author [AXA0TL];

float value; }library; //声明的右右花括号后跟变量名

换言之,声明结构的过程和定义结构变量的过程可以组合成一个步骤。如下所示,组合后的结构声明和结构变量定义不需要使用结构标记: struct { //无结构标记 char title [ MAXTITL];

char author [ MAXAUTL];

float value; } library; 然而,如果打算多次使用结构模板,就要使用带标记的形式;在这个例子中,并未初始化结构变量。


4.1 初始化结构


初始化变量和数组如下:

int count = 0 ;

int fibo [ 7] = {0,1,1,2,3,5,8 };

结构变量是否也可以这样初始化?是的,可以。初始化一个结构变量(ANSI之前,不能用自动变量初始化结构:ANSI之后可以用任意存储类别)与初始化数组的语法类似

简而言之,我们使用在一对花括号中括起来的初始化列表进行初始化,各初始化项用逗号分隔 因此,**title成员可以被初始化为一个字符串,value 成员可以被初始化为一个数字。**为了让初始化项与结构中各成员的关联更加明显,我们让每个成员的初始化项独占一行。这样做只是为了提高代码的可读性,对编译器而言,只需要用逗号分隔各成员的初始化项即可。

不是我说,这本书写的真好!


4.2 访问结构成员


结构类似于一个“超级数组”,这个超级数组中,可以是一个元素为char类型,下一个元素为forat类型,下一个元素为int 数组。可以通过数组下标单独访问数组中的各元素,那么,如何访问结构中的成员﹖使用结构成员运算符——一点( .)访问结构中的成员。例如,library.value即访问library的value部分。可以像使用任何float类型变量那样使用library.value。与此类似,可以像使用字符数组那样使用library.title。因此,上面的程序中有 s_gets(library.title,MAXTITL);和scanf(""号f",&library.value);这样的代码。

C语言不亏是基础,如果首先学会C语言,学面向对象这种访问方式应该更好理解了!

学过其他语言应该会很好理解,就像Java中访问类中的方法也是类名.方法名()



相关文章
|
23天前
|
存储 C语言
如何在 C 语言中实现结构体的深拷贝
在C语言中实现结构体的深拷贝,需要手动分配内存并逐个复制成员变量,确保新结构体与原结构体完全独立,避免浅拷贝导致的数据共享问题。具体方法包括使用 `malloc` 分配内存和 `memcpy` 或手动赋值。
30 10
|
22天前
|
存储 大数据 编译器
C语言:结构体对齐规则
C语言中,结构体对齐规则是指编译器为了提高数据访问效率,会根据成员变量的类型对结构体中的成员进行内存对齐。通常遵循编译器默认的对齐方式或使用特定的对齐指令来优化结构体布局,以减少内存浪费并提升性能。
|
27天前
|
编译器 C语言
共用体和结构体在 C 语言中的优先级是怎样的
在C语言中,共用体(union)和结构体(struct)的优先级相同,它们都是用户自定义的数据类型,用于组合不同类型的数据。但是,共用体中的所有成员共享同一段内存,而结构体中的成员各自占用独立的内存空间。
|
27天前
|
存储 C语言
C语言:结构体与共用体的区别
C语言中,结构体(struct)和共用体(union)都用于组合不同类型的数据,但使用方式不同。结构体为每个成员分配独立的内存空间,而共用体的所有成员共享同一段内存,节省空间但需谨慎使用。
|
1月前
|
编译器 C语言 C++
C语言结构体
C语言结构体
25 5
|
1月前
|
存储 C语言 C++
深入C语言,发现多样的数据之枚举和联合体
深入C语言,发现多样的数据之枚举和联合体
深入C语言,发现多样的数据之枚举和联合体
|
1月前
|
编译器 Linux C语言
C语言 之 结构体超详细总结
C语言 之 结构体超详细总结
19 0
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
34 3
|
7天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
23 6
|
27天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
34 10