06_结构体与结构体指针数组

结构体与结构体指针数组

1. 上节课作业讲解

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

// TODO 第一版   通用
void substrAction1(char * result, char * str, int start, int end) {
    char * temp = str; // 定义临时指针,不破坏str指针
    int count = 0; // 记录当前的位置
    while (*temp) {
        // 2 到 5 的位置  在截取的范围内
        if (count >= start && count < end) {
            *result = *temp; // *temp 取出 D e r r y ...
            result++; // (接收值也要挪动)挪动指针来接收   =   *temp给我的值
        }
        temp++; // 取值也要挪动
        count++; // 当前的位置要同步
    }
}

// TODO 第二版    有意让同学,深刻理解  栈区 堆区 开辟(1)
void substrAction2(char ** result, char * str, int start, int end) {
    // 方法一
    char * temp = str; // 定义临时指针,不破坏str指针
    // 合理分配,截取多少用多少,节约
    char resultArr[end - start]; // 我只需要你截取的大小空间:例如:rry
    int count = 0;
    for (int i = start; i < end; ++i) {
        resultArr[count] = *(temp + i); // *(temp + i);取出D e r r y 给数组容器
        count++;
    }
    // * 取出二级指针的一级指针 ==  main函数的result一级指针
    // *result = resultArr; // 不能让我们的一级指针 指向容器,因为容器会被回收掉
    strcpy(*result, resultArr); // 第一种解决方案
    printf("%s\n", resultArr);

    // 方法二
    // char * temp = str;
    // 尽量不要使用第二种方式,会被C工程师鄙视的,为什么? 你开辟的,就应该你回收
    // char * resultArr = malloc(end - start); // 堆区开辟,第二种解决方案
    // int count = 0;
    // for (int i = start; i < end; ++i) {
    //     resultArr[count] = *(temp + i); // *(temp + i);取出D e r r y 给数组容器
    //     count++;
    // }
    // 注意:不能回收堆空间,否则main函数 打印了空
    // free(resultArr);(此段代码是错误代码,不能回收堆空间)
} // 函数弹栈后,会回收所有的栈成员,包括:resultArr

// TODO 第三版    三行代码搞定
void substrAction3(char * result, char * str, int start, int end) { // 没有涉及栈区 堆区的概念
    // 合理分配,截取多少用多少,节约 思路
    for (int i = start; i < end; ++i) { // 刚好结束 循环三次
        *(result++) = *(str+i); // i = 2
    }
}

// TODO 第四版   一行代码搞定
void substrAction4(char * result, char * str, int start, int end) {
    // 参数1:我最终是copy到result容器里面
    // 参数2:直接从r开始,因为我一级做了,指针挪动了
    // 参数3:你从r开始,挪动多少
    strncpy(result, str+start, end - start);
}
int main() {
    char * str = "Derry is";
    // 正好她是一级指针
    char * result; // char * 不需要结尾符\0

    // 截取第二个位置到第五个位置 2,5
    // substrAction1(result, str, 2, 5);
    // substrAction2(&result, str, 2, 5);
    // substrAction3(result, str, 2, 5);
    substrAction4(result, str, 2, 5);
    printf("main 截取的内容是:%s", result); // 最终截取:rry

    // 方法二在这里回收,输出是正确的.
    // if (result) {
    //     free(result);
    //     result = NULL;
    // }
    return 0;
}

在这里插入图片描述

// 上节课指针练习
#include <stdio.h>
int main() {
    int a[] = {6,4,8,3,1,2,9,7,0,5};
    // *(a+4) == (a+4):a数组默认指向首元素地址 挪动到 第四个元素    *取出第四个元素内存地址的值 == 1
    //*(a+1) == a数组默认指向首元素地址 挪动到 第一个元素    *取出第一个元素内存地址的值 == 4
    //a[4] == 挪动到第四个元素 内存地址的值 == 1
    int result = a[*(a+*(a+4))];
    printf("result的值是:%d\n", result);
    return 0;
}

2. 结构体定义与使用

// 2.结构体定义与使用.    第一种写法
// Java/Kotlin有类的概念, C语言 函数 结构体(相当于是Java的类)

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

struct Dog {
    //成员
    char name[10]; //copy进去
    int age;
    char sex;
};  //必须给写";"这个结束号

int main() {
    struct Dog dog;
    // 这样写完,成员是没有任何初始化的,成员默认值是系统值(name:?@, age:3133440, sex:?)
    printf("name:%s, age:%d, sex:%c \n", dog.name, dog.age, dog.sex);

    // 赋值操作
    // dog.name = "旺财";
    strcpy(dog.name, "旺财");
    dog.age = 3;
    dog.sex = 'G';
    printf("name:%s, age:%d, sex:%c \n", dog.name, dog.age, dog.sex);
    return 0;
}
// 2.结构体定义与使用。  第2种写法
#include <stdio.h>

struct Person {
    // 成员
    char * name; // 字符指针 = "赋值"
    int age;
    char sex;
} ppp = {"Derry", 33, 'M'},
        ppp2,
        ppp3,
        pppp4,
        pppp5
// ...
;

int main() {
    // Person == ppp <==> struct Person ppp;
    printf("name:%s, age:%d, sex:%c \n", ppp.name, ppp.age, ppp.sex);

    // char* 只能赋值copy报错,如何是char name[10]数组就需要copy赋值就报错
    // 赋值
    // strcpy(pppp5.name, "Derry5");
    pppp5.name = "DerryO";
    pppp5.age = 4;
    pppp5.sex = 'M';
    printf("name:%s, age:%d, sex:%c \n", pppp5.name, pppp5.age, pppp5.sex);
    return 0;
}
// 2.结构体定义与使用。  第3种写法
#include <stdio.h>
struct Study {
    char * studyContent; // 学习的内容
};
struct Student {
    char name[10];
    int age;
    char sex;

    // Study study; // VS的写法
    struct Study study; // Clion工具的写法

    struct Wan {
        char * wanContent; // 玩的内容
    } wan;
};

int main() {
    struct Student student =
            {"李元霸", 88, 'm',
            {"学习C"},
            {"王者农药"}
            };

    printf("name:%s, age:%d, sex:%c,study:%s, wan:%s \n",
           student.name, student.age, student.sex, student.study.studyContent, student.wan.wanContent);
    return 0;
}

3. 结构体指针与动态内存开辟

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

struct Cat {
    char name[10];
    int age;
};

int main() { // 栈
    // 结构体
    struct Cat cat = {"小花猫", 2};

    // 结构体 指针    "->"调用一级指针成员
    // VS的写法:Cat * catp = &cat;
    struct Cat * catp = &cat;
    catp->age = 3;
    strcpy(catp->name, "小花猫2");
    printf("name:%s, age:%d \n", catp->name, catp->age);
    return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct Cat2 {
    char name[10];
    int age;
};

int main() { // 堆

    // VS的写法:Cat2 * cat = (Cat2 *) malloc(sizeof(Cat2));
    struct Cat2 *cat = malloc(sizeof(struct Cat2));

    strcpy(cat->name, "金色猫");
    cat->age = 5;

    printf("name:%s, age:%d \n", cat->name, cat->age);

    // 堆区的必须释放
    free(cat);
    cat = NULL;

    return 0;
}

4. 结构体数组

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

struct Cat3 {
    char name[10];
    int age;
};

int main() {

    // 栈区 静态范畴
    struct Cat3 cat [10] = {
            {"小黄", 1},
            {"小白", 2},
            {"小黑", 3},
            {},
            {},
            {},
            {},
            {},
            {},
            {},
    };

    // VS的写法
    // cat[9] = {"小黑9", 9},

    // ClION的写法
    struct Cat3 cat9 =  {"小黑9", 9};
    // cat[9] = cat9;
    *(cat + 9) = cat9;
    printf("name:%s, age:%d \n", (cat + 9).name, (cat + 9).age);

    // 堆区 动态范畴 ==============================
    struct Cat3 * cat2 = malloc(sizeof(struct Cat3) * 10);

    // 【1元素地址的操作】给他赋值,请问是赋值,那个元素  (默认指向首元素地址)
    strcpy(cat2->name, "小花猫000");
    cat2->age = 9;
    printf("name:%s, age:%d \n", cat2->name, cat2->age);

    // 【8元素地址的操作】 给第八个元素赋值
    cat2 += 7;
    strcpy(cat2->name, "小花猫888");
    cat2->age = 88;
    printf("name:%s, age:%d \n", cat2->name, cat2->age);

    free(cat2);
    cat2 = NULL;

    return 0;
}

5. 结构体与结构体指针 取别名

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

struct Worker_ {
    char name[10];
    int age;
    char sex;
};

// VS的写法:typedef Worker_
typedef struct Worker_ Worker_; // 给结构体取别名

typedef Worker_ * Worker; // 给结构体指针取别名

// C库的源码,系统源码...,为什么 typedef 还取一个和结构体一样的名字(兼容代码的写法,保持一致)

int main() {
    // 以前 Clion工具 必须加上 struct   VS又不用加  代码差异化大
    //    VS的写法:Worker_ worker1 = malloc(sizeof(Worker_));
    // Clion的写法:struct Worker_ worker1 = malloc(sizeof(struct Worker_));

    // 现在 (兼容代码的写法,保持一致)
    Worker_ worker1 = malloc(sizeof(Worker_));

    // VS  CLion  他们都是一样的写法
    Worker worker = malloc(sizeof(Worker_));

    return 0;
}
// 系统源码都是这样写的
#include <stdio.h>
#include <stdlib.h>

struct DAO {
    char name[10];
    int age;
    char sex;
};

// 匿名结构体的别名(这样写意义不大,因为没有名字)
typedef struct {
    char name[10];
    int age;
    char sex;
};

// 源码是这样写的
// 给结构体AV 取了一个别名等于AV
typedef struct {
    char name[10];
    int age;
    char sex;
} AV;

//  // 取一个别名
//  typedef struct DAO DAO;
//  void show(DAO dao) {} // 在不同工具上 又的要加,又的不用加 又差异化
//  // 不取别名
//  void show(struct DAO dao) {}


int main() {
    // VS 不需要这样写,   Clion工具 要加入关键字  代码不统一
    // struct DAO * dao  = malloc( sizeof(struct DAO));

    // 加别名后  代码的统一了

    // VS
    DAO * dao  = malloc( sizeof(DAO));

    // CLion工具也这样写
    DAO * dao1  = malloc( sizeof(DAO));

    // xxx 工具也这样写
    DAO * dao2  = malloc( sizeof(DAO));

    // 加别名后  代码的统一了
    // C库的源码,系统源码...,为什么 typedef 还取一个和结构体一样的名字(兼容代码的写法,保持一致)
    AV av = {"VideoInfo", 54, 'M'}; // 结构体  VS  Clion  xxx工具  兼容写法

    AV * avp = malloc(sizeof(AV)); // 结构体指针

    return 0;
}

6. 枚举及练习题(处理好不同平台差异化)

//#include <stdio.h>
 枚举 int 类型的
//enum CommentType {
//    TEXT = 10,
//    TEXT_IMAGE,
//    IMAGE
//};
 作业:处理好 差异化代码
//int main() {
//    // Clion工具的写法如下:
//    enum CommentType commentType = TEXT;
//    enum CommentType commentType1 = TEXT_IMAGE;
//    enum CommentType commentType2 = IMAGE;
//    // VS工具的写法如下:
//    // CommentType commentType = TEXT;
//    printf("%d, %d, %d \n", commentType, commentType1, commentType2);
//    return 0;
//}

#include <stdio.h>
// 作业:处理好 差异化代码
// 枚举 int 类型的
typedef enum {
    TEXT = 10,
    TEXT_IMAGE,
    IMAGE
} CommentType;

int main() {
    // Clion工具的写法如下:
    CommentType commentType = TEXT;
    CommentType commentType1 = TEXT_IMAGE;
    CommentType commentType2 = IMAGE;

    // VS工具的写法如下:
    // CommentType commentType = TEXT;

    printf("%d, %d, %d \n", commentType, commentType1, commentType2);

    return 0;
}
#include <stdio.h>
typedef enum {
    AUDIO = 11,
    VIDEO,
    INFO
} AV;
int main() {
    printf("截拳道");
    // 以后写C代码的习惯,尽量加上别名,来保证代码的 统一
    AV av1 = AUDIO;
    AV av2 = VIDEO;
    AV av3 = INFO;
    printf("AUDIO:%d, VIDEO:%d, INFO:%d\n", av1, av2, av3);
    // 截拳道audio:111, video:112, info:113,
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

左绍骏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值