C语言基础之结构体

一、为什么要用结构体?

  • 结构体是类型不同的一组数据集合,数据更多,类型更丰富,信息量更大
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//这样定义一个结构体
struct student
{
       int score;
       char name[128];
};//注意分号要写

int main()
{             
                 //stu1 是结构体变量名
    struct student stu1 = {100,"free"};//大括号里面的是初始值
    //访问结构体数据
    printf("stu1结构体的: score=%d\n",stu1.score);
    printf("stu1结构体的:name=%s\n",stu1.name);//结构体变量名.内部变量名
    
    struct student stu2;//没做初始化的结构体
    stu2.score = 99;//给结构体内部数据赋值
    //stu2.name = "张三";这样是不行的
    strcpy(stu2.name,"张三");
    printf("stu2结构体的: score=%d\n",stu2.score);
    printf("stu2结构体的:name=%s\n",stu2.name);
    
    return 0;
}

2.运行结果:
在这里插入图片描述
3.注意常犯的错误 “野指针”

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct stu
{
      char *name;
       
};

struct text
{
       char name[128];
};
int main()
{
    struct stu a;
    struct text b;
    /*第一种
    strcpy(a.name,"感觉自己萌萌哒");
    printf("stu的name = %s\n",a.name);
    */
    
    //第二种
    strcpy(b.name,"感觉自己萌萌哒");
    printf("text的name = %s\n",b.name);
    
    return 0;
}

第一种运行结果:

在这里插入图片描述
因为是对野指针直接赋值,出现段错误,人家都还只是一个地址,都还没有开辟空间呢你就给人家赋值,所以对使用指针一定要注意,要先开辟空间再初始化,最后再赋值!!!

第二种运行结果:
在这里插入图片描述
因为是对字符串数组进行赋值,数组定义出来就已经申请了空间,所以可以直接赋值。

二、结构体数组来玩成绩

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct student
{
       int score;
       char *name;

};
int main()
{
    int i;
    struct student stu[3];//定义了一个结构体数组,也是通过下标法来访问
    for(i=0;i<sizeof(stu) / sizeof(stu[0]);i++){
        printf("请输入第%d个学生的成绩:\n",i+1);
        scanf("%d",&(stu[i].score));

        printf("请输入第%d个学生的名字:\n",i+1);
        stu[i].name = (char *)malloc(128);//注意对结构体内部指针,使用前要申请开辟空间
        scanf("%s",stu[i].name);
    }
    for(i=0;i<sizeof(stu) / sizeof(stu[0]);i++){
        printf("你输入的%d个学生的成绩是:%d 名字是:%s\n",i+1,stu[i].score,stu[i].name);
    }
    
    struct student maxStu;
    struct student minStu;
    
    maxStu = minStu = stu[0];
    for(i=0;i<sizeof(stu) / sizeof(stu[0]);i++){
        if(maxStu.score < stu[i].score){
           maxStu = stu[i];
        }
        if(minStu.score > stu[i].score){
           minStu = stu[i];
        }
    }
    printf("考最高分的是:%s 分数是:%d\n",maxStu.name,maxStu.score);
     printf("考最低分的是:%s 分数是:%d\n",minStu.name,minStu.score);
    return 0;
}

运行结果:
在这里插入图片描述

三、结构体指针

1.注意:

  • 如果结构体指针,访问结构体中的变量时就不能用点运算符,要用->
  • 使用结构体指针时,要注意是否是野指针或者是NULL!!!
  • 结构体指针的偏移值是整个结构体的大小

2.看代码:

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

struct student
{
       int score;
       char name[128];
};
int main()
{
    struct student *p;//这样定义一个结构体指针,不过这是野指针,还没有开辟空间
    p = (struct student *)malloc(sizeof(struct student));//开辟空间
    p->score = 98;//赋值
    strcpy(p->name,"李四");
    printf("结构体指针的score=%d name=%s\n",p->score,p->name);

    //看下偏移值
    printf("结构体指针的地址是:%p\n",p);
    printf("++后的地址是:%p\n",++p);
    
    
    return 0;
}

3.运行结果:
在这里插入图片描述

四、结构体指针函数综合处理学生成绩

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

struct student
{
       int score;
       char *name;
};
struct student * initStuScore(int len)
{
       int i;
       //在堆上开辟空间,函数结束调用不会释放
       struct student *p = (struct student *)malloc(len * sizeof(struct student));
       for(i=0;i<len;i++){
           printf("请输入第%d个学生的名字:\n",i+1);
           p->name = (char *)malloc(128);
           scanf("%s",p->name);
           
           printf("请输入第%d个学生的成绩:\n",i+1);
           scanf("%d",&(p->score));
           p++;
       }
           return p - len;
}

void printMes(struct student *p,int len)
{
     int i;
     for(i=0;i<len;i++){
         printf("你输入的第%d个学生的成绩是:%d 名字是:%s\n",i+1,p->score,p->name);
         p++;
     }
}
struct student *findMax(struct student *p,int len)
{
       int i;
       struct student *max;
       max = p;
       for(i=0;i<len;i++){
           if(max->score < p->score){
              max = p;
           }
           p++;
       }
       return max;
}

struct student *findMin(struct student *p,int len)
{
       int i;
       struct student *min;
       min = p;
       for(i=0;i<len;i++){
           if(min->score > p->score){
              min = p;
           }
           p++;
       }
       return min;

}

float getAverage(struct student *p,int len)
{
      int i;
      int total = 0;     
      for(i=0;i<len;i++){
          total += p->score;
          p++;
      } 
      return (float)total / len;
}
int findSomeOneName(struct student *p,int len,char *name)
{
     int i;
     for(i=0;i<len;i++){
         if(strcmp(name,p->name) == 0){
            return 1;
         }
         p++;
     } 
         return -1;
}
int main()
{
    int len = 0;
    printf("请输入学生总人数:\n");
    scanf("%d",&len);
    
    struct student *max;
    struct student *min;
    struct student *pstus = initStuScore(len);
    printMes(pstus,len);
    max = findMax(pstus,len);
    min = findMin(pstus,len);
    printf("你输入学生成绩的最高分是:%d 名字是:%s\n最低分是:%d 名字是:%s 平均分是:%f\n",max->score,max->name,min->score,min->name,getAverage(pstus,len));
    
    if(findSomeOneName(pstus,len,"王五") == -1){
       printf("没有此人\n");
    }else{
       printf("恭喜,找到了\n");
    } 
    return 0;
}

>运行结果:
在这里插入图片描述

五、结构体大小的计算方式:

1)结构体成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)

2)结构体大小必须是所有成员大小(数组除外,结构体除外)的整数倍

注意:

  • 对齐方式确实很浪费空间,但是按照计算机的访问规则,这种对齐方式大大提升了效率

代码段:

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

struct s1
{
       char ch1;
       char ch2;
       int i;
};
struct s2
{
       char ch1;
       int i;
       char ch2;
       
};
struct s3
{
       char ch1;
       int i;
       char str[10];
       
};
struct s4
{
       char ch1;
       int i;
       struct s{
       char ch;
       int j;
       };
      float f;       
};
struct s5
{
       char ch1;
       int i;
       union{
           char ch;
           int j;
       };     
};
//#pragma pack(4)  //指定向4对齐,最大是8,指定的大小没有超过结构体成员的大小,所以指向4对齐
struct s6
{
       char ch;
       int i;
       float f;
       double d;
};
#pragma pack(10)//指定向10对齐,超过了结构体成员最大的大小,所以指向8对齐
struct s7
{
       char ch;
       int i;
       float f;
       double d;
};
int main()
{
    printf("s1:%ld\n",sizeof(struct s1));//结果:8
    printf("s2:%ld\n",sizeof(struct s2));//结果:12
    printf("s3:%ld\n",sizeof(struct s3));//结果:20
    printf("s4:%ld\n",sizeof(struct s4));//结果:12
    printf("s5:%ld\n",sizeof(struct s5));//结果:12
    printf("s6:%ld\n",sizeof(struct s6));//结果:20
    printf("s7:%ld\n",sizeof(struct s7));//结果:24
    
    return 0;
}

六、typedef关键字

1)typedef为c语言的关键字

2)作用是为一种数据类型定义一个新名字

3)这里的数据类型包括内部数据类型(int ,char 等)和自定义数据类型(struct 等)

4)和struct 来匹配为了代码编写简洁,和普通类型匹配,通过名字来获取一些信息

代码段:

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

//在单片机开发,寄存器8位,16位,32位
typedef unsigned char u_int8;
typedef unsigned short int u_int16;
typedef unsigned int u_int32;

typedef struct student
{
        int score;
        char *name;
}STU,*PSTU;

int main()
{
   u_int8 data1 = 10;
   u_int16 data2 = 20;
   u_int32 data3 = 30;
   printf("%d %d %d\n",data1,data2,data3);

   STU stu1;
   stu1.score = 99;
   printf("stu1的score=%d\n",stu1.score);

   PSTU pstu;
   pstu = (PSTU)malloc(sizeof(STU));
   pstu->score = 100;
   printf("pstu的score=%d\n",pstu->score);

}

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值