结构体和其他数据形式

一.结构体

    导引——在实际问题中,有时候我们需要几种不同类型变量一起来修饰某个变量,例如一个学生的信息就需要学号(整型),姓名(字符串),成绩(浮点型)等等,这些数据类型都不同但是他们又是表示一个整体,要存在联系,那么我们就需要一个新的数据类型。 所以我们引入了结构体。

1.结构体的声明

//声明一个结构体
struct student
{
    
    
    char name[20];//一个字符串表示学生姓名 ; 
    char num;//一个整型表示学生学号 ; 
    float score;//一个浮点型表示学生成绩; 
};//注意分号不能少,这也相当于一条语句;

    这个声明描述了一个由1个字符数组、1个int整型和1个float变量组成的结构体,但是注意,他并没有创建一个实际的数据对象,而是描述了一个组成这类对象的元素,【因此,我们也有时候将结构体声明叫做模板,因为它勾勒出数据该如何存储,并没有实例化数据对象】。
下面介绍一下上面的结构体声明;

  1. 首先使用关键字struct,他表示接下来是一个结构体。
  2. 后面是一个可选的标志(book),它是用来引用该结构体的快速标记。因此我们以后就会可以这样创建数据对象
struct student stu;
//把stu设为一个可以使用student结构体的结构体变量,则stu这个变量就包含了其student结构体中的所有元素
  1. 接下来就是一个花括号,括起了结构体成员列表,及就是每个成员变量,使用的都是其自己的声明方式来描述,用分号来结束描述;
    注意;其中每个成员可以使用任何一种c数据结构甚至是其他的结构体,也是可以的;
  2. 在结束花括号后的分号表示结构体设计定义 的结束(不能少)。
  3. 关于其struct声明的位置,也就是这段代码要放到哪里。同样这也是具有作用域的。
    这种声明如果放在任何函数的外面,那么则可选标记可以在本文件中,该声明的后面的所有函数都可以使用。如果这种声明在某个函数的内部,则它的标记只能咋内部使用,并且在其声明之后。
  4. 之前我们结构体类型的定义(结构体的声明)只是告诉编译器该如何表示数据,但是它没有让计算机为其分配空间。我们要使用结构体,那么就需要创建变量,也就是结构体变量;
    创建一个结构体变量;struct stduent stu;
    看到这条指令,编译器才会创建一个结构体变量stu,此时编译器才会按照studnt模板为该变量分配内存空间,并且这里存储空间都是以这个变量结合在一起的,这也是后面访问结构体变量成员的时候,我们就要用到结构体变量名来访问。

struct book的作用在结构体声明中,struct student所起到的作用就像int等基础数据类型名作用一样。

2.结构体的初始化

struct student stu={
    
      //对结构体初始化 
        "xiaoming",//姓名name为字符串 
        1001,     //学号num是整型
        120.5    //成绩score为flaot型 
    };
    //要对应起来,用逗号分隔开来,与数组初始化一样;

值得注意的是:

  • 关于结构体初始化和存储类时期的问题:
    如果要初始化一个具有静态存储时期的结构体,初始化项目列表中的值必须是常量表达式,如果存储时期是自动的,那么列表的值就不必是常量了。

  • 如果在定义结构体变量的时候没有初始化,那么后面就不能全部一起初始化了。
    意思就是:

——————这样是可以的,在定义变量的时候就初始化了。
struct student stu={
    
      //对结构体初始化 
        "xiaoming",//姓名name为字符串 
        1001,     //学号num是整型
        120.5    //成绩score为flaot型 
    };
——————这种就不行了,在定义变量之后,若再要对变量的成员赋值,那么只能单个赋值了。
struct student stu;
    stu={
    
     
       	  "xiaoming",
      		1001, 
       		120.5 
    };//这样就是不行的,只能在定义的时候初始化才能全部赋值,之后就不能再全体赋值了,只能单个赋值。
——————只能
    stu.name = "xiaoming";   //单个赋值;

3.访问结构成员

    结构体就像一个超级数组,在这个超级数组内,一个元素可以是char类型,下个元素就可以是flaot类型,再下个还可以是int数组型,这些都是存在的。在数组里面我们通过下标可以访问一个数组的各个元素,那么如何访问结构体中的各个成员呢?

用结构成员运算符点(.)就可以了。
    结构体变量名.成员名;
注意,点其结合性是自左至右的,它在所有的运算符中优先级是最高的
    例如,s1.title指的就是s1的title部分,stu.name指的就是stu的name部分。然后就可以像字符数组那样使用s1.name,像使用float数据类型一样使用stu.score。
    注意,stu虽然是个结构体,但是stu.score却是float型的,因此stu.score就相当于float类型的变量名一样,按照float类型来使用。
如:printf(“%s%s\n%f”,s1.title,s1.author,s1.value);//访问结构体变量元素

    注意:scanf(“%d”,&s1.value); 这语句存在两个运算符,&和结构成员运算符点,按照道理我们应该将(s1。value括起来,因为他们是整体,表示s1的value部分)但是我们不括起来也是一样的,因为点的优先级要高于&。
    如果其成员本身又是一种结构体类型,那么可以通过若干个成员运算符,一级一级的找到最低一级成员再对其进行操作。
结构体变量名.成员.子成员………最低一级子成员。

整体与分开:

  • 可以将一个结构体变量作为一个整体赋值给另一相同类型的结构体变量,可以到达整体赋值的效果;这个成员变量的值都将全部整体赋值给另外一个变量。
  • 不能将一个结构体变量作为一个整体进行输入和输出;在输入输出结构体数据时,必须分别指明结构体变量的各成员。

4.结构体数组

    为什么要引用结构体数组,显然,在上面的book类型的结构体 ,每本书就需要用一个book类型的结构体变量来描述,若是要描述两本书,需要使用两个这样的变量,依次类推;因此要使用一个该结构体的数组,来表示这些图书;并且数组就是存储一组具有相同类型的数据,因此就有了结构体数组的出现,注意本置,

1.声明结构体数组

与普通的数组声明一样,int a[10];int为元素的数据类型,a为数组名 【10】表示申请了10的int单元的内存。再看结构体声明;struct student stu[10];是不是类似,struct student为数组元素的数据类型,stu为数组名,[10]为申请了10个struct student单元的内存。
解释:声明library为一个具体10个元素的数组,并且每个元素都student类型的结构,因此可以得到stu[0],stu[1]…….都是单独独立的一个book结构。
注意library本身不是结构体名而是一个数组名。

2.访问结构体数组的成员

规则:在结构体名后加点运算符,然后再是成员名。
stu[5].name; //表示第5个元素的name成员,stu[5]是结构体变量名,name就是成员名;
stu[5].name[4];//注意name是数组类型,第5个数组元素的name成员的第4个字符;访问结构体数组的成员。
使用指向结构体的好处;就像指向数组的指针一样,它比数组本身更容易操作,指向结构体的指针通常也比结构体本身更容易操作;

3.声明和初始化结构体指针

声明struct student * him;
规则就是,struct 结构体名+ * + 指针名;
这个声明不是建立一个新的结构体,而是创建了一个指针类型的him指针变量,他可以指向任何现有的student类型的结构体;
him = &stu[0];
指针him正指向结构体stu[0],如何使用him来取得stu[0]的一个成员呢?
方法一:
引入一个运算符 : ->
后跟->运算符的结构体指针和后跟.点运算符的结构体名是一样操作的。
注意一点的是,不能使用him.成员,因为him不是结构体名。
方法二:
如果him=&stu[0],那么him=stu[0];因为&和是一个互逆的运算符;
&取地址,*取值;
=>stu[0].score 等价于 (*him).score;注意必须使用圆括号,优先级问题;
然后都与him.score是一个作用。

猜你喜欢

转载自blog.csdn.net/qq_52355487/article/details/111460919
今日推荐