C语言复习 -- 结构体 & 联合体

结构体

出现前景 : 同时需要对多种数据进行操作
结构体--他就将不同类型的数据存放在一起,作为一个整体进行处理。


声明:

struct Test
{
 int a[20];
char c; 
};//注意分号不能少,这也相当于一条语句; 


结构体初始化:

1.先定义再一个个初始化 


typedef struct {
    int bandrate;
    int databits;
    int stopbits;
    int parity;
    int dtr;
}serial_hard_config_def;
 
serial_hard_config_def serial;
serial.bandrate = 115200;
serial.databits = 8;
serial.stopbits = 1;
serial.parity = 0;
serial.dtr = 0;


2.定义的同时初始化


2.1 顺序初始化


typedef struct {
    int bandrate;
    int databits;
    int stopbits;
    int parity;
    int dtr;
}serial_hard_config_def;
 
serial_hard_config_def serial = {
    115200,
    8,
    1,
    0,
    0
};
 

2.2 乱序初始化:

typedef struct {
    int bandrate;
    int databits;
    int stopbits;
    int parity;
    int dtr;
}serial_hard_config_def;
 
serial_hard_config_def serial = {
    .dtr = 0,
    .bandrate = 115200,
    .databits = 8,
    .stopbits = 1,
    .parity = 0,
};


结构体数组初始化:


typedef struct {
    int bandrate;
    int databits;
    int stopbits;
    int parity;
    int dtr;
}serial_hard_config_def;
 
serial_hard_config_def serial[2] = {
    [0] = {
        .dtr = 0,
        .bandrate = 115200,
        .databits = 8,
        .stopbits = 1,
        .parity = 0,
        },
    [1] = {
        .dtr = 0,
        .bandrate = 115200,
        .databits = 8,
        .stopbits = 1,
        .parity = 0,
    }
};


访问结构体成员:


1.变量名  .
2.指针  ->


 


===================================================

结构体数组-test -- 选票系统


test:
选票程序
#include<stdio.h>
#include<string.h>

struct XuanMing
{
    int tickets;
    char name[30];
    
};


int main()
{
    
    struct XuanMing xm[3];
    struct XuanMing max;
    int len =sizeof(xm)/sizeof(xm[0]);
    char tName[30];
    int i,j;
    int flag=0;
    int total=5;
    int lose=0;
    //初始化选民信息:
    for(i=0;i<len;++i)
    {
        xm[i].tickets=0;
        puts("请输入选民的姓名:");
        scanf("%s",xm[i].name);
    }
    
    //投票环节
    for(i=0;i<5;++i)
    {
        flag=0;
        memset(tName,'\0',sizeof(tName));
        puts("请输入你支持的选民的姓名:");
        scanf("%s",tName);
        
        for(j=0;j<len;++j)
        {
            if(!strcmp(xm[j].name,tName))
            {
                xm[j].tickets++;
                flag=1;
            }
            
        }
      if(!flag)
      {
          lose++;
          puts("输出错误视为弃票");
      }
        
    }
    
    puts("======================");
for(int i=0;i<len;++i)
{
    printf("姓名:%s  得票:%d\n",xm[i].name,xm[i].tickets);
    
    
}    
printf("弃票数:%d\n",lose);
    puts("=====公布结果====");
    max=xm[0];
for(int i=0;i<len;++i)
{
    if(xm[i].tickets>max.tickets)max=xm[i];
    
}
printf("恭喜!!!最终d当选者:%s  得票:%d\n",max.name,max.tickets);
  
    return 0;
}

结构体指针:

结构体的两种访问方式:


1.结构体变量名  -- 用 . 访问
2.指针访问    -- 用 -> 访问

#include<stdio.h>

struct Test
{
    int idata;
    char cdata;
    
};

int main()
{
    struct Test tt={12,'a'};
    struct Test *ptt=&tt;
    printf("idata= %d\n",tt.idata);
    printf("idata= %d\n",ptt->idata);
    printf("cdata= %c\n",tt.cdata);
    printf("cdata= %c\n",ptt->cdata);
    
    
    
    return 0;
}

// 指针 操作 注意


1.把以前的普通变量名,or下标访问 . 元素符改为 指针的->
2.指针++,用完记得复位

报错注意:
struct Test tt=NULL; //避免野指针
yy={12,'a'};

================================


结构体二级指针:

我们知道如果要修改一个变量的值,就要传递他的地址给函数,指针变量也一样,要传入二级指针

这样初始化就不用接收返回值,直接在初始化函数里面修改
p=(struct XuanMin*)malloc(sizeof(struct XuanMin)*n);

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


struct XuanMin
{
    char name[30];
    int tickets;
};

struct XuanMin* initXms(struct XuanMin *p,int *len)
{
    int i;
    int n=0;
    if(p==NULL){
    printf("请输入选民人数:\n");
    scanf("%d",len);
    n=*len;
    p=(struct XuanMin*)malloc(sizeof(struct XuanMin)*n);
    }
    for(i=0;i<n;++i)
    {
        printf("请输入第%d位选民的姓名:\n",i+1);
        scanf("%s",p->name);
        p->tickets=0;
        p++;
    }
    return p-n;
}

void printXms(struct XuanMin*p,int len)
{
    int i;  
    for(i=0;i<len;++i)
    {
        printf("姓名:%s 得票:%d\n",(p+i)->name,(p+i)->tickets);
        //printf("姓名:%s 得票:%d\n",p->name,p->tickets);
        //p++;
    }
    
    
}

int doVote(struct XuanMin*p,int len)
{
    int i,j;
    int flag=0;
    int lose=0;\
    char tName[30];
    struct XuanMin*sta=p;
    //投票环节
    for(i=0;i<5;++i)
    {
        p=sta;
        flag=0;
        memset(tName,'\0',sizeof(tName));
        puts("请输入你支持的选民的姓名:");
        scanf("%s",tName);
        
        for(j=0;j<len;++j)
        {
            if(!strcmp(p->name,tName))
            {
                p->tickets++;
                flag=1;
                break;
            }
            p++;
        }
      if(!flag)
      {
          lose++;
          puts("输出错误视为弃票");
      }
        
    }
    
    return lose;
}


struct XuanMin *getWiner(struct XuanMin*p,int len)
{
struct XuanMin    *max=p;
for(int i=0;i<len;++i)
{
    if(p->tickets>max->tickets)
        max=p;
    ++p;
    
}
printf("恭喜!!!最终d当选者:%s  得票:%d\n",max->name,max->tickets);
  
    return 0;
    
}

int main()
{
    struct XuanMin *xm=NULL;
    int total=0;
    xm=initXms(xm,&total); //初始化指针 -- 避免野指针
    //printf("%d",total);
    //printXms(xm,total);
   int lose= doVote(xm,total);    
    printf("弃票数:%d\n",lose);
    printXms(xm,total);
    getWiner(xm,total);
    return 0;
}

//  要修改一个变量 就要传入他的实参 -- 地址 修改int *,传入int** 


void initXms2(struct XuanMin **pxm,int *pt)
{
    int i;
         if(*pxm==NULL)    {
            puts("请输入选民人数:");
            scanf("%d",pt);    
            *pxm=(struct XuanMin *)malloc(sizeof(struct XuanMin)*(*pt));
        }
    for(i=0;i<*pt;++i)
    {
        printf("请输入第%d位选民的姓名:\n",i+1);
        scanf("%s",(*pxm)->name);
        (*pxm)->tickets=0;
        (*pxm)++;
    }
    *pxm=*pxm-*pt; //实现 初始化
    
    
}

共用体/联合体: -- union

定义和 结构体一样,把struct 换成 union

特性 -- 不同类型的变量,共享同一空间


结构体 和联合体的区别;


1. 结构体元素有各自单独的空间 , 联合体共享空间
2.结构体元素互不影响,联合体赋值会导致覆盖


 

结构体大小占用规则


1、第一个成员在与结构体变量偏移量为0的地址处。(即结构体的首地址处,即对齐到0处)

2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

3、结构体的总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

4、如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

对齐数 = 该结构体成员变量自身的大小与编译器默认的一个对齐数的较小值。
注:VS中的默认对齐数为8,不是所有编译器都有默认对齐数,当编译器没有默认对齐数的时候,成员变量的大小就是该成员的对齐数。

联合体的内存 == 其中元素中的占用最大内存的元素

验证程序:
#include<stdio.h>

struct Test1 
{
    int  idata;
    char cdata;
    double ddata;
};

union Test2 
{
    int  idata;
    char cdata;
    double ddata;
};

int main()
{
    
    struct Test1 t1;
    union  Test2 t2;
    
    puts("大小区别");
    printf("结构体: %d\n",sizeof(t1)); // 16 
    printf("联合体: %d\n",sizeof(t2)); //8 -- double
    
    puts("存放地址区别");
    
    printf("结构体idata: %p\n",&t1.idata);
    printf("联合体idata: %p\n",&t2.idata);
    puts("====================================");
    printf("结构体cdata: %p\n",&t1.cdata);
    printf("联合体cdata: %p\n",&t2.cdata);
    puts("====================================");
    printf("结构体ddata: %p\n",&t1.ddata);
    printf("联合体ddata: %p\n",&t2.ddata);
    
    puts("存放数值区别");
    t1.idata=4;
    t1.cdata='a';
    t1.ddata=12.5;
    printf("idata=%d cdata=%c ddata%.2lf\n",t1.idata,t1.cdata,t1.ddata);
    puts("====================================");
    t2.idata=12;
    t2.cdata='a';
    
    printf("t2.idata:%d\n",t2.idata); // 97
    
    
    return 0;
}

test:
现在有学生和老师的成员数据,学生数据包括:姓名,号码,性别,年龄,职业,班级
老师的数据包括:姓名,号码,性别,年龄,职业,职务,要求使用同一个表格来处理

// 思路: 根据观察,学生和老师  数据类型只差, 班级和职务不同 -- 可以都存在联合体里面去处理

#include<stdio.h>
 
 struct Person
 {
     char name[20];
     char occup;//occupation
     union D
     {
        int class;
        char subject[20];        
     }uu;
     
 };
 
 
 int main()
 {
     struct Person p[2];
     int i;
     for(i=0;i<2;++i)
     {
     puts("请输入您的职业: s-学生 t-老师");
     scanf("%c",&(p[i].occup));
     getchar();
      if(p[i].occup=='s')
      {
      puts("请输入学生姓名:");        
      scanf("%s",p[i].name);
      puts("请输入学生班级:");        
      scanf("%d",&(p[i].uu.class));
          
      }
      else
      {
       puts("请输入老师姓名:");        
      scanf("%s",p[i].name);
      puts("请输入;老师所教科目:");        
      scanf("%s",p[i].uu.subject); 
          
          
      }
      
     }
     for(int i=0;i<2;++i)
     {
         if(p[i].occup=='s')
         {
             puts("一名学生");
             printf("姓名:%s   班级:%d\n",p[i].name,p[i].uu.class);
         }
         else
         {
             
             puts("一位老师");
             printf("姓名:%s   所教科目:%s\n",p[i].name,p[i].uu.subject);
             
         }
              
     }
      
     
 }


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值