结--结构体

————————————————————————

 //输入字符串的案例

   char chs[10];

   int index = 0;

   char ch;

   while((ch = getchar()) !='\n' && index < 256 -1) {

        

        chs[index ++] = ch;

    }

    // 如果 ch == '\n'  ch != '\n'

   if(ch != '\n') {

       while(getchar() !='\n');

    }

    

    //内存有时会浪费有时又会不够用

    //数组是存储的数据

    //需要可以动态伸缩的内存

    // 什么是内存管理

    // 对程序运行中申请的内存进行维护与销毁的过程

    // 栈内存由系统申请并维护,函数一执行就有栈内存函数结束,内存回收

    // 堆内存程序运行过程中,由程序员申请的内存内存的回收与管理由程序员来维护

    //     如果程序员没有回收不用的内存容易造成内存泄露

    

    



————————————————————————


    malloc 函数

        向操作系统申请指定字节数的内存,如果申请成功,

        返回内存的首地址如果失败返回 NULL

        语法:

            void *malloc(unsigned long size);

        返回 void 类型的指针

            void  C89 提出的概念目的是用来表示通用指针类型


    calloc 函数



    realloc 函数




    free 函数

        回收申请的内存,注意申请的内存变量不要随意的修改

        void free(void *);


 */

#include <stdio.h>

#include <stdlib.h>


int main(int argc,const char *argv[]) {


  int *p = (int *)malloc(40);// 不写 (int *) 也是默认转成 int 指针

  //此时我实际上声明了一个长度为 10  int数组


  char *str = (char *)malloc(10);// 长度为 40 的字符串(char 数组)


  // int 数组

  // int *temp = p;

  //    int *temp = NULL;

  //    temp = p;

  //    // temp  p 都是指针类型的变量都指向刚刚创建的 40 个字节的内存

 //

  //    for (int i = 0; i < 10; i++) {

  //        scanf("%d", temp++);

  //        // scanf("%d", p++);

  //    }

 //

  //    printf("==========\n");

  //    temp = p;

  //    // p -= 10;

  //    for (int i = 0; i < 10; i++) {

  //        printf("%d\n", *temp++);

  //        // printf("%d\n", *p++);

  //    }


  // ==============================================


  // char 数组

 int index = 0;

 char ch;

 while ((ch = getchar()) !='\n' && index < 10 -1) {


    str[index++] = ch;// index 表示将要添加字符是位置

  }

  // 如果 ch == '\n'  ch != '\n'

 char tempChar;

 if (ch != '\n') {

   while ((tempChar = getchar()) != '\n') {

      // printf("%c\n", tempChar);

    }

  }

  str[index] = '\0';// 在字符串结尾加一个 \0 表示字符串结束


  printf("=====\n");


 printf("%s\n", str);


 char c = getchar();// 为什么?

  //检验是否已经清空缓存中的数据

  // 如果清空了, getchar 会阻塞

  //如果没有, getchar 会从缓存中直接去数据,而不会阻塞


  // 使用 free 函数回收内存


 free(p);

 free(str);


  return 0;

}




————————————————————————


#include <stdio.h>

#include <stdlib.h>


void *czalloc(int size1,int size2) { returnmalloc(size1 * size2); }


int main(int argc,const char *argv[]) {


  //    // malloc 是申请指定长度的内存

  //    int *p = (int *)malloc(4000);

 //

  //    // 首地址 calloc(单位长度多少个单位);

  //    int *p1 = (int *)calloc(4, 1000);

 //

  //    // 在功能上, malloc  calloc 是一样的为了申请内存

  //    //申请后的内存是需要回收的但是他们的区别在内存数据上

  //    // malloc 申请的内存里面是垃圾数

  //    // calloc 申请的内存会全部清零

 //

 //

  //    for (int i= 0; i< 1000; i++) {

  //        printf("%d ", p1[i]);

  //        if(i % 20 == 0) printf("\n");

  //    }


 //

  // re-  英文词缀重复

 int *p = malloc(10);// 十个字节

 printf("%p\n", p);


  p =realloc(p, 20);// 扩充为二十个字节

 printf("%p\n", p);


  p =realloc(p, 5);

 printf("%p\n", p);


  // p修改大小以后的地址的值不一定是一样的

  //如果是扩容系统会检查原来的内存中是否可以容得下这些字节


 free(p);

  return 0;

}



——————指针函数——————————————————


/*

    指针函数

        就是返回指针类型数据的函数,其语法

            数据类型 *函数名(...) { ... }


    写一个函数,返回用户输入的字符串


 */


#include <stdio.h>

#include <stdlib.h>


char *inputString() {


  // char str[10];


 int length = 10;

 char *str = malloc(length);// 内存的管理必须由程序员自己完成


 int index = 0;

 char ch;

 while ((ch = getchar()) !='\n' && index < length - 1) {


    str[index++] = ch;

  }


 char tempChar;

 if (ch != '\n') {

   while ((tempChar = getchar()) != '\n')

      ;

  }

  str[index] ='\0';


 printf("%p\n", str);


 return str;

}


int main(int argc,const char *argv[]) {

  // insert code here...

  // printf("Hello, World!\n");


 char *str = inputString();


 printf("%p\n", str);


 printf("|%s|\n", str);


 printf("|%c|\n", *(str +0));

 printf("|%c|\n", *(str +1));

 printf("|%c|\n", *(str +2));

 printf("|%c|\n", *(str +3));

 printf("|%c|\n", *(str +4));

 printf("|%c|\n", *(str +5));

 printf("|%c|\n", *(str +6));

 printf("|%c|\n", *(str +7));

 printf("|%c|\n", *(str +8));

 printf("|%c|\n", *(str +9));


 free(str);


  return 0;

}




———————函数指针—————————————————


    函数指针就是指函数的地址

    函数指针变量,就是一个存储函数首地址的变量

    函数名表示的就是函数的首地址



    函数指针变量如何定义:

        int *p;

        char *p;


        char (*p)[10];

        void (*p)();   // 指向一个无参无返回值的函数,变量是 p


        int (*p)(int num1, int num2);



    函数指针如何使用:

        1, 语法用法

            p = 函数名;

            p() 来调用该函数好比 p 就是函数的别名一样


            如何使用如何调用即可


        2, 实际用法

            函数指针可以让函数作为变量来使用,

   最大的优势是可以作为参数在函数间进行传递

            void func(int num) { ... }

            void func( int (*p)() ) { ... }


 */


#include <stdio.h>


void func1() {printf("func被打印了\n"); }

void func2() {printf("这里是func2函数\n"); }


void func3(int num) {printf("num的两倍是 %d\n",2 * num); }


void func4(int num) {printf("%d\n", num); }


int func5(int num) {return 2 * num; }

int func6(int num) {return num * num; }


int main(int argc,const char *argv[]) {


  //    printf("%p\n", func);

  //    printf("%p\n", main);


  //    //定义了一个指向无参无返回的函数指针变量

  //    void  (*p)();

 //

  //    // 让这个函数指针变量指向函数 func

  //    p = func1;

 //

 //

  //    // 使用 p 就可以调用 func 

  //    p();   // func()

 //

 //

  //    p = func2;

 //

  //    p();


  //    void (*p1)(int num);

 //

  //    p1 = func3;

 //

  //    p1(13);

 //

  //    p1 = func4;

 //

  //    p1(5);


 int (*p2)(int);

  p2 =func5;


 int res1 = p2(5);

 printf("%d\n", res1);


  p2 =func6;


 int res2 = p2(5);

 printf("%d\n", res2);


  return 0;

}



—————————函数做函数参数———————————————


#include <stdio.h>


void func() {printf("打印测试\n"); }


void _01() {printf("用第一种方法卖房子\n"); }


void _02() {printf("用第二种方法卖房子\n"); }


void invokeFunc(void (*p)()) { p(); }


void _0我要卖房子(void (*中介)()) {


 if (中介 ==NULL) {

    printf("没有找到好中介\n");

  }else {

   中介();

  }

}


int main(int argc,const char *argv[]) {


  // invokeFunc(func);


 _0我要卖房子(_02);


  return 0;

}



—————————自定义排序———————————————

#include <stdio.h>


int czCompare1(int num1,int num2) { return num1 - num2; }


int czCompare2(int num1,int num2) { return num2 - num1; }


void sort(int nums[],int length, int (*compare)(int,int)) {


 for (int i =0; i < length - 1; i++) {

   for (int j =0; j < length - i - 1; j++) {


     if (compare(nums[j], nums[j + 1]) > 0) {


       int temp = nums[j];

        nums[j] = nums[j +1];

        nums[j +1] = temp;

      }

    }

  }

}


int main(int argc,const char *argv[]) {


 int nums[] = {1, -2,4, -1234123434, -2321,0};


  // sort(nums, 8, czCompare1);

  sort(nums, 8czCompare2);


  return 0;

}



———————内存泄露 野指针—————————————————

#include <stdio.h>

#include <stdlib.h>


int main(int argc,const char *argv[]) {


  // while(1);

  /*

  int *p;


  for (int i = 0; i < 200; i++) {

      p = malloc(1024 * 1024);

      // 不断的申请内存,但是又不去释放那么内存会变得非常的大,

  而且无法再使用这段内存

      // 那么内存就有可能无故的被占用,其他的程序也无法访问这段内存


      // free(p);

  }


  while (1) {


  }

   */


  //    int *p;   // p  值为什么是 NULL

  //    // p 到底指向的是什么?

 //

  //    scanf("%d", p);

 //

 //

  //    // p 不知道指向的是谁


 int *p = malloc(4);

 scanf("%d", p);

 free(p);


 printf("%p\n", p);


  //内存已经被回收但是 p依旧指向这个内存容易造成使用非法的内存数据


 scanf("%d", p);


  // 野指针

  // 声明指针变量后,初始化为 NULL    int *p = NULL

  // 使用 free 回收内存后一定要设置变量为 NULL


  // if(p == NULL)


  return 0;

}




————————结构体————————————————

定义一个结构体

        struct  结构体类型的名字 {

            // 成员

            int age;

            char name[10];

            ...

        };

    结构体类型的定义应该写在哪里呢?一般写成全局的实际开发中,常常写在头文件中


    如何使用

    1, 先利用结构体类型定义该类型的变量

        struct 结构体类型名    变量名;

    2, 初始化(先定义再初始化)

        变量名.成员名 =;

    3, 使用结构体成员

        结构体成员的时候与直接使用成员类型的变量的方法一模一样



 1, 声明结构体类型

        先声明类型再定义变量

        声明了类型的同时,定义变量

            struct 结构体类型名 {


                // 成员


            } 变量名1, 变量名1, ..., 变量名N;




        声明匿名类型的同时,定义变量

            struct {

                // 成员


            } 变量1, 变量2, ..., 变量n;


    2, 声明结构体类型变量的同时进行初始化

            struct 结构体名  变量名 = { 按照定义的顺序排列数据即可 };


使用结构体变量作为结构体成员的结构体变量


结构体不允许是自己的成员但是使用结构体指针可以作为自己的成员


// 结构体作为函数参数语法

//  返回类型   函数名 (struct  结构类型名   形式参数名) { ... }



——————改良初始化化结构体变量的方法——————————————————


#include <stdio.h>

#include <string.h>


// 定义的结构

struct Score {

    

   int chineseScore;

   int mathScore;

   int englishScore;

    

};


struct Student {

   char name[20];

   int age;

   char gender;

    

    // 分数

   struct Score score;

};



structScore initScore(int cScore,int mScore, int eScore) {

    

   struct Score score;


    score.chineseScore = cScore;

    score.mathScore = mScore;

    score.englishScore = eScore;

    

   return score;

}



structStudent initStudent(char *name,int age, char gender,int cScore, int mScore,inteScore) {

    

   struct Student stu;

    

   strcpy(stu.name, name);

    stu.age = age;

    stu.gender = gender;

   

    stu.score =initScore(cScore, mScore, eScore);

    

    

    // struct Student stu1 = { name, age, gender , .... };

    

    

   return stu;

}




void printScore(structScore score) {


    printf("chinese = %d\n", score.chineseScore);

   printf("math = %d\n", score.mathScore);

    printf("english = %d\n", score.englishScore);

}


void printStudent(structStudent stu) {


   printf("name = %s\n", stu.name);

   printf("age = %d\n", stu.age);

   printf("gender = %s\n", stu.gender =='f' ? "" :"");

    

   printScore(stu.score);

}



int main(int argc,const char * argv[]) {

    

    

   struct Student s1 =initStudent("张晓艺",10'm'908590);

    

   struct Student s2 =initStudent("李狗蛋",3'f'1008045);

    

    

    

    

    printStudent(s1);

    

    

    printf("==============\n");

    

    printStudent(s2);

    

    

   return 0;

}







————————————————————————



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值