IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 零基础入门C语言第七课:结构体 -> 正文阅读

[C++知识库]零基础入门C语言第七课:结构体

第七课:结构体

目录

第七课:结构体

1.1·结构体的声明

1.2·结构体成员的访问

1.3·结构体传参

1.4·C99中复合字面量和结构

1.5·C99中伸缩型数组成员

1.6·C11中的匿名结构


1.1·结构体的声明

在说明结构体之前我们先看一个问题:创建图书目录问题

要求说明:Gwen Glenn要打印一份图书目录。他想打印每本书的各种信息:书名、作者、出版社、出版日期、页数、册数和价格。数据类型自定。

//book.c 本书的图书目录#include<stdio.h>#include<string.h>#define MAXTITL 41//书名最大长度+1#define MAXAUTL 31//作者姓名的最大长度+1char* s_gets(char* st,int n);struct book//结构模板:标记是book{    char title[MAXTITL];//书名    char author[MAXAUTL];//作者名    float value;//单价};int main(void){    struct book library;//把library声明为一个book类型的变量    printf("现在请输入书的书名.");    s_gets(library.title,MAXTITL);//访问书名部分    printf("现在请输入书的作者.");    s_gets(library.author,MAXAUTL);//访问作者部分    printf("现在请输入书的单价.");    scanf("%f",&library.value);//录入单价    printf("%s由%s写成,单价是%f",library.title,library.author,library.value);    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,'');//查找换行符        if(find)            //如果地址不是NULL            *find='';     //在此处放置一个空字符        else            while(getchar()!='')                continue;//处理输入行中剩余的字符    }    return ret_val;}

运行结果:这里随便写的内容

现在请输入书名.

Chicken of the Andes

现在请输入作者.

Disma Lapoult

现在请输入单价.

29.99

Chicken of the Andes 由Disma Lapoult写的,单价是29.99

?

因此结构体我们掌握和了解3个技巧:

①为结构建立一个格式或样式

②声明一个适合该样式的变量

③访问结构变量的各个部分

结构的基础知识
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。

结构成员的类型:结构的成员可以是标量、数组、指针,甚至是其他结构体

结构的声明:

结构声明描述了一个结构的组织布局。在结构声明中用一对花括号括起来的是结构成员列表。每个成员都用自己的声明来描述。如果把结构声明置于函数外部,那么该声明之后所有函数都能使用它的标记。例如:struct book dickens;这样函数便创建了一个结构变量dickens,该变量的结构布局是book。

就计算而言,下面的声明:

//第一种struct book{    char title[MAXTITL];    char author[MAXAUTL];    float value;};struct book library;//第二种struct book{    char title[MAXTITL];    char author[MAXAUTL];    float value;}library;//声明的右花括号后跟变量名//第一种是第二种的简化(指struct book library)//声明结构的过程和定义结构变量的过程可以组合成一个步骤,即声明定义一起

?

结构体变量的定义和初始化:有了结构体类型,那如何定义变量,其实很简单。
?

struct Point{int x;int y;}p1; //声明类型的同时定义变量p1struct Point p2; //定义结构体变量p2//初始化:定义变量的同时赋初值。struct Point p3 = {x, y};struct Stu //类型声明{char name[15];//名字int age; //年龄};struct Stu s = {"zhangsan", 20};//初始化struct Node{int data;struct Point p;struct Node* next;}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化

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

?

扩展知识:结构的初始化器

C99和C11为结构提供了指定初始化器。结构的指定初始化器使用点运算符和成员名(而不是方括号和下标)标识特定的元素。例如:只初始化book结构的value成员,可以这样做:

struct book surprise={? .value=10.99};

可以按照任意顺序指定初始化器:

struct book gift={ .value=25.99,

? ? ? ? ? ? ? ? ? ? ? ? ? ? .author="James Boradfool",

? ? ? ? ? ? ? ? ? ? ? ? ? ? .title="Rue for the Toad"};

与数组类似,在指定初始化器后面的普通初始化器,为特定成员后面的成员提供初始值。另外,对特定成员的最后一次赋值才是它实际获得的值。例如:

struct book gift={? .value=18.90,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.author="Philionna Pestle",

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0.25?

????????????????????????????????}

赋给value的值是0.25,因为它在结构声明中紧跟在author成员之后,新值0.25取代了之前的18.9。(结构体存储成员是放在一个连续的内存空间里,初始化了author就顺着内存去读了value)就比如:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU2xvdyBKdXN0IEZhc3Q=,size_18,color_FFFFFF,t_70,g_se,x_16

?

?


1.2·结构体成员的访问

结构体变量访问成员:结构变量的成员是通过点操作符(.)访问的(也可以用->访问,这里不谈)。点操作符接受两个操作数。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU2xvdyBKdXN0IEZhc3Q=,size_10,color_FFFFFF,t_70,g_se,x_16

?

struct stu{    char name[20];    int age;};struct stu s;//我们可以看到 s 有成员 name 和 age ;//那我们如何访问s的成员?struct S s;strcpy(s.name, "zhangsan");//使用.访问name成员s.age = 20;//使用.访问age成员

结构体指针访问指向变量的成员有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针。那该如何访问成员?

如下:

struct Stu{char name[20];int age;};void print(struct Stu* ps){printf("name = %s age = %d", (*ps).name, (*ps).age);//使用结构体指针访问指向对象的成员printf("name = %s age = %d", ps->name, ps->age);}int main(){struct Stu s = {"zhangsan", 20};print(&s);//结构体地址传参return 0;}

1.3·结构体传参

道理相同直接上代码把,大家好好看看就行:

struct S{int data[1000];int num;};struct S s = {{1,2,3,4}, 1000};//结构体传参一void print1(struct S s){printf("%d", s.num);}//结构体地址传参二void print2(struct S* ps){printf("%d", ps->num);}int main(){print1(s); //传结构体print2(&s); //传地址return 0;}

思考:print1 和 print2 函数哪个好些?

答案:首选print2函数

原因:函数传参的时候,参数是需要压栈的。如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。

结论:结构体传参的时候,要传结构体的地址。


1.4·C99中复合字面量和结构

C99的复合字面量特性可用于结构和数组。如果只需要一个临时结构值。复合字面量很好用。例如,可以使用复合字面量创建一个结构作为函数的参数或赋给另一个结构。语法是把类型名放在括号中,后面紧跟一个花括号括起来的初始化列表。例如:下面是struct book类型的复合字面量:

(struct book) {"The Idiot","Fyodor Dostoyevsky",6.99}

举例:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU2xvdyBKdXN0IEZhc3Q=,size_15,color_FFFFFF,t_70,g_se,x_16

?如果复合字面量在所有函数的外部,就具有静态存储期;

如果复合字面量在块里,就具有自动存储期;

复合字面量中可以使用指定初始化器。


1.5·C99中伸缩型数组成员

C99新增了一个特性:伸缩型数组成员,利用这项特性声明的结构,其最后一个数组成员具有一些特征。第1个特征是,该数组不会立即存在。第2个特征是,使用这个伸缩型数组成员可以编写合适的代码,就好像它确实存在并具有所需数目的元素一样。这可能听起来很奇怪,所以我们来一步步地创建和使用一个带伸缩型数组成员的结构。

首先,声明一个伸缩型数组成员有如下规则:

①伸缩型数组成员必须是结构的最后一个成员

②结构中必须至少有一个成员

③伸缩数组的声明类似于普通数组,只是它的方括号中是空的

实例:

struct flex{    int count;    double average;    double scores[];//伸缩型数组成员};

声明一个struct flex类型的结构变量时,不能用scores做任何事情,因为没有给这个数组预留存储空间。实际上,C99的意图并不是让你声明struct flex类型的变量,而是希望你声明一个指向struct flex类型的指针,然后用malloc()来分配足够的空间,以存储struct flex类型结构的常规内容和伸缩型数组成员所需的额外空间。例如:假设用scores表示一个内含5个double类型值的数组,可以这样做:

struct flex* pf;//声明一个指针//请求为一个结构和一个数组分配存储空间pf=malloc(sizeof(struct flex)+5*sizeof(double));

现在有足够的存储空间存储count、average和一个内含5个double类型值的数组。可以用指针pf访问这些成员:

pf->count=5;//设置count成员pf->scores[2]=18.5;//访问数组成员的一个元素

1.6·C11中的匿名结构

匿名结构是一个没有名称的结构成员。为了理解它的工作原理,我们先考虑如何创建嵌套结构:

struct names{    char first[20];    char last[20];};struct person{    int id;    struct names name;//嵌套结构成员};struct person ted={8483,{"Ted","Grass"}};

这里,name成员是一个嵌套结构,可以通过类似ted.name.first的表达式访问"red";例如:puts(ted.name.first)。

在C11中,可以用嵌套的匿名成员结构定义person:

struct person{    int id;    struct {char first[20];char last[20];};//匿名结构};初始化ted的方法相同:struct person ted={8483,{"Ted","Grass"}};但是,在访问ted时简化了步骤,只需要把first看作时person的成员那样使用它例如:Puts(ted.first);当然,也可以把first和last直接作为person的成员,删除嵌套循环。匿名特性在嵌套联合中更让你更加有用。

?

?

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-24 10:38:58  更:2022-01-24 10:40:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:56:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码