C语言之结构体

结构体

为什么需要结构体
    为了表示一些复杂的事物,而普通的基本类型无法满足实际要求
什么叫结构体
    把一些基本类型数据组合在一起形成的一个新的复合数据类型,这个叫做结构体
如何定义一个结构体
    3种方式(推荐第一种)
   //第一种方式 ,一般用第一种 
  struct Student
  {
  int age;
  float score;
  char sex;
  };
  //第二种方式
  struct Student2
  {
  int age;
  float score;
  char sex;
  } st2;
  //第三种方式
   struct 
  {
  int age;
  float score;
  char sex;
  } st3;
怎么使用结构体变量
    赋值和初始化
        定义的同时可以整体赋初值
        如果定义完之后,则只能单个的赋初值
# include <stdio.h>
struct Student
{
    int age;
    float score;
    char sex;
};
int main(void)
{
    struct Student st = {80,66.6,'F'};  
    //初始化  定义的同时赋初值(第一种) 
     struct Student st2;
     st2.age = 10;
     st2.score = 88;
     st2.sex = 'F';
     //第二种 
     printf("%d %f %c\n",st.age,st.score,st.sex);
     printf("%d %f %c\n",st2.age,st2.score,st2.sex); 
}
如何取出结构体变量中的每一个成员
        1.结构体变量名.成员名
        2.指针变量->成员名
            指针变量->成员名    在计算机内部会被转化成(*指针变量名).成员名的方式来执行,所以说这两种方式是等价的
# include <stdio.h>
struct Student
{
    int age;
    float score;
    char sex;
};
int main(void)
{
    struct Student st = {80,66.6,'F'};  
    struct Student * pst = &st;  //&st不能改成st
     
    pst->age = 88;//第二种方式 
    st.age;//第一种方式 
    
    return 0; 
}
  1.pst->age  在计算机内部会被转化成(*pst).age 
  2.所以pst->age 等价于 (*pst).age 也等价于  st.age
  3.pst->age的含义:
   pst所指向的那个结构体变量中的age这个成员
    
# include <stdio.h>
struct Student
{
    int age;
    float score;
    char sex;
};
int main(void)
{
    struct Student st = {80,66.6F,'F'};  
    struct Student * pst = &st;  //&st不能改成st
     
    pst->age = 88;//第二种方式 
    st.score = 66.6f;//第一种方式 
    //强制将66.6转换为float类型,原本66.6是double类型
     
    printf("%d %f\n",st.age,pst->score);
    
    return 0; 
}
结构体变量和结构体指针变量作为函数参数传递的问题
        推荐使用结构体指针变量作为函数参数来传递
/*
    2009年11月24日9:17:43
    通过函数完成对结构体变量的输入和输出
*/


# include <stdio.h>
# include <string.h>

struct Student
{
    int age;
    char sex;
    char name[100];
}; //分号不能省
//函数申明 
void InputStudent(struct Student *);
void OutputStudent(struct Student ss);
int main(void)
{
    struct Student st;  //15行

    InputStudent(&st); //对结构体变量输入  必须发送st的地址
//    printf("%d %c %s\n", st.age, st.sex, st.name);
    OutputStudent(st); //对结构体变量输出  可以发送st的地址也可以直接发送st的内容

    return 0;
}

void OutputStudent(struct Student ss)//不需要修改st,内容只是输出,所以指针可有可无 
{
    printf("%d %c %s\n", ss.age, ss.sex, ss.name);
}

void InputStudent(struct Student * pstu) //pstu只占4个字节
{
    (*pstu).age = 10;
    strcpy(pstu->name, "张三");
    pstu->sex = 'F';    
}

/*
//本函数无法修改主函数15行st的值 所以本函数是错误的
void InputStudent(struct Student stu)
{
    stu.age = 10;
    strcpy(stu.name, "张三");  //不能写成 stu.name = "张三";
    stu.sex = 'F';
}
*/
示例:
        发送地址还是发送内容
目的:
       指针的优点之一:
                快速的传递数据
                耗用内存小
                执行速度快 
/*
    2009年11月24日9:17:43
    示例:
        发送地址还是发送内容
    目的:
        指针的优点之一:
            快速的传递数据,
            耗用内存小
            执行速度快
*/


# include <stdio.h>
# include <string.h>

struct Student
{
    int age;
    char sex;
    char name[100];
}; //分号不能省

void InputStudent(struct Student *);
void OutputStudent(struct Student *);
int main(void)
{
    struct Student st ;  //15行
    //printf("%d\n", sizeof(st));

    InputStudent(&st); //对结构体变量输入  必须发送st的地址
    OutputStudent(&st); //对结构体变量输出  可以发送st的地址也可以直接发送st的内容 但为了减少内存的耗费,也为了提高执行速度,推荐发送地址

    return 0;
}

void OutputStudent(struct Student *pst)
{
    printf("%d %c %s\n", pst->age, pst->sex, pst->name);
}

void InputStudent(struct Student * pstu) //pstu只占4个字节
{
    (*pstu).age = 10;
    strcpy(pstu->name, "张三");
    pstu->sex = 'F';    
}

/*
//本函数无法修改主函数15行st的值 所以本函数是错误的
void InputStudent(struct Student stu)
{
    stu.age = 10;
    strcpy(stu.name, "张三");  //不能写成 stu.name = "张三";
    stu.sex = 'F';
}
*/
结构体变量的运算
          结构体变量不能相加,不能相减,也不能相互乘除
           但结构体变量可以相互赋值
     举例
           动态构造存放学生信息的结构体数组
                动态构造一个数组,存放学生的信息,然后按分数排序输出
# include <stdio.h>
# include <malloc.h>

struct Student
{
    int age;
    float score;
    char name[100];
};

int main(void)
{
    int len;
    struct Student * pArr;
    int i, j;
    struct Student t;
    

    //动态的构造一维数组
    printf("请输入学生的个数:\n");
    printf("len = ");
    scanf("%d", &len);
    pArr = (struct Student *)malloc(len * sizeof(struct Student));
    
    //输入
    for (i=0; i<len; ++i)
    {
        printf("请输入第%d个学生的信息:\n", i+1);
        printf("age = ");
        scanf("%d", &pArr[i].age);

        printf("name = ");
        scanf("%s", pArr[i].name);  //name是数组名,本身就已经是数组首元素的地址, 所以pArr[i].name 不能改成 &pArr[i].name

        printf("score = ");
        scanf("%f", &pArr[i].score);
    }

    //按学生成绩升序排序 冒泡算法
    for (i=0; i<len-1; ++i)
    {
        for (j=0; j<len-1-i; ++j)
        {
            if (pArr[j].score > pArr[j+1].score) //>升序 <降序
            {
                t = pArr[j];
                pArr[j] = pArr[j+1];
                pArr[j+1] = t;
            }
        }
    }

    printf("\n\n学生的信息是:\n");
    //输出
    for (i=0; i<len; ++i)
    {
        printf("第%d个学生的信息是:\n", i+1);
        printf("age = %d\n", pArr[i].age);
        printf("name = %s\n", pArr[i].name);  //name是数组名,本身就已经是数组首元素的地址, 所以pArr[i].name 不能改成 &pArr[i].name
        printf("score = %f\n", pArr[i].score);
    
        printf("\n");
    }

    return 0;
}
枚举    
   什么是枚举
       把一个事物所有可能的取值一一列举出来
   怎样使用枚举
# include <stdio.h>

//只定义了一个数据类型,并没有定义变量,该数据类型的名字是enum WeekDay
enum WeekDay
{
    MonDay,TuesDay,WednesDay,ThursDay,FriDay,SaturDay,SunDay
        
};

int main(void)
{
    //int day;  //day定义成int类型不合适 
    enum WeekDay day = WednesDay;
    printf("%d\n",day);
        
    return 0;
}
枚举的优缺点:
        代码更安全
        书写麻烦
位运算符:
    补码:
学习目标:
     在C++中一个int 类型的变量所能存储的数字的范围是多少
     最小负数的二进制代码是多少
     最大正数的二进制代码是多少
     已知一个整数的二进制代码求出原始的数字
     数字超过最大正数会怎样
    进制转换
    字符串的处理
     链表
 算法
            通俗的定义:
                解题的方法和步骤
             狭义的定义:
               对存储数据的操作
               对不同的存储结构,要完成的某一功能所执行的操作是不一样的
            广义的定义:
                广义的算法也叫泛型
                无论数据是如何存储的,对该数据的操作都是一样的
            我们至少可以通过两种结构来存储数据
                    数组
优点:
    存取速度快
缺点:
     需要一个连续的很大的内存
     插入和删除元素的效率很低
                     链表
专业术语:
头节点:头节点的数据类型和首节点的数据类型一模一样
头指针:存放头节点地址的指针变量
首节点:存放第一个有效数据的节点
尾节点:存放最后一个有效数据的节点
优点:
    插入删除元素效率高
    不需要一个连续的很大的内存
缺点:
    查找某个位置的元素

 

posted @ 2018-03-26 19:38  骑猪少年  阅读(270)  评论(0编辑  收藏  举报