013-结构体-C语言笔记

学习目录

1.【掌握】返回指针的函数

2.【掌握】指向函数的指针

3.【掌握】结构体的声明

4.【掌握】结构体与数组

5.【掌握】结构体与指针

6.【掌握】结构体的嵌套

7.【掌握】结构体与函数

一、返回指针的函数

指针作为函数的返回值

指针是可以作为函数的返回值的,不能返回局部变量的指针,因为当函数执行结束后指针变量就释放了。如果我们真的需要返回一个指针变量,那就要保证我们的函数执行完毕之后,指针指向的变量仍然存储在内存之中。那我们可以将变量创建在堆空间中,使用malloc或者calloc申请空间。或者直接声明为全局变量或者用static修饰的局部变量。

如果函数需要返回一个字符串,我们可以返回(char *)类型字符串,不要使用字符数组,因为字符数组在函数执行结束后,就释放了。而使用(char *)声明的字符串是存储在数据段的,直到程序执行结束才会释放。

 
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <stdlib.h>
 
char*getWeekDay(intday){
    return"星期N";//返回的是字符串在数据段(常量区)中的地址
}
intmain(){
    char*weekDay=getWeekDay(2);
    return0;
}

二、指向函数的指针

程序在运行的时候,函数是存储在内存(代码段)之中的,存储函数的空间肯定也是有地址的,所以我们可以用指针指向函数。

语法:返回值类型 (*指针名)([参数列表]);

注意:

1.函数的地址就是函数名。

2.指向函数的指针变量,本质上还是一个变量,那么我们就可以声明、赋值给另外一个同类型的指针变量使用。

无参无返回值

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
voidtestFunction(){
    printf("这是一个无参无返回值的函数\n");
}
intmain(intargc,constchar*argv[]){
    
    //指针指向函数
    void(*pFunction)()=testFunction;//存储没有返回值没有参数的地址,函数名就是函数的地址
    //指针调用函数
    (*pFunction)();
    pFunction();//简写
    
    return0;
}

有参有返回值

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
 
intgetSum(intnum1,intnum2){
    returnnum1+num2;
}
intmain(intargc,constchar*argv[]){
    
    //指针指向函数,参数列表可以省略
    int(*pFunction)()=getSum;
    
    //指针调用函数
    intsum=pFunction(10,12);
    
    printf("sum = %d\n",sum);
    return0;
}

应用场景:多种方式对字符串数组进行排序

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <stdio.h>
#include <string.h>
 
/**
*  对字符串进行各种排序
*
*  @param countries 需要被排序的字符串数组
*  @param length    字符串数组的长度
*  @param pCompare  指向控制排序方式的函数指针
*/
voidsort(char*countries[],intlength,int(*pCompare)()){
    for(inti=0;i<length;i++){
        for(intj=0;j<length-1-i;j++){
            //调用比较字符串的函数进行比较
            intres=pCompare(countries[j],countries[j+1]);
            if(res>0){
                //交换位置
                char*temp=countries[j];
                countries[j]=countries[j+1];
                countries[j+1]=temp;
            }
        }
    }
}
 
/**
*  比较字符串大小
*
*  @param str1 第一个字符串
*  @param str2 第二个字符串
*
*  @return 第一个大字符串大返回正数,第二个字符串大返回负数,相同返回0
*/
intcompare(char*str1,char*str2){
    return(int)strcmp(str1,str2);
}
 
/**
*  比较字符串的长度
*
*  @param str1 第一个字符串
*  @param str2 第二个字符串
*
*  @return 第一个字符串大返回1,第二个字符串大返回-1,相同返回0
*/
intcompare1(char*str1,char*str2){
    unsignedlonglen1=strlen(str1);
    unsignedlonglen2=strlen(str2);
    if(len1>len2){
        return1;
    }elseif(len1<len2){
        return-1;
    }
    return0;
}
 
intmain(intargc,constchar*argv[]){
    char*countries[]={
        "fldjfljfaf",
        "fdahfiyyyyfh",
        "aadjflui",
        "jabfaf"
    };
    
    //计算字符串数组长度
    intlength=sizeof(countries)/sizeof(char*);
    
    //传入字符串数组,数组长度,指向函数的指针。按字符串大小排序
    sort(countries,length,compare);
    
    //传入字符串数组,数组长度,指向函数的指针。按字符串长度排序
    sort(countries,length,compare1);
    
    //遍历打印字符串
    for(inti=0;i<length;i++){
        printf("%s\n",countries[i]);
    }
    
    return0;
}

三、结构体的声明

在实际应用中,我们通常需要由不同类型的数据来构成一个整体,比如学生信息这个整体可以由姓名、年龄、身高等数据构成,这些数据都具有不同的数据类型,姓名可以是字符指针类型,年龄可以是整型,身高可以是浮点型。C语言提供了一种构造类型来解决这个问题,由程序员自己声明多个数据类型组成一个整体当做一种新的数据类型,这个玩意就是结构体。结构体里的声明的多个数据类型变量叫做结构体的成员。

声明结构体类型语法:

struct 类型名 {

数据类型1 成员名1;

数据类型2 成员名2;

..........

};

声明结构体变量语法:struct 类型名 变量名;

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//声明类型的同时声明变量
structStudent{
    char*name;
    intage;
    floatheigth;
}stu,stu1;//可以同时声明多个变量
 
//匿名结构体。声明类型的同时声明变量,可以省略类型名,但是这种方法不能再次声明新的变量了
struct{
    char*name;
    intage;
    floatheigth;
}stu,stu1;//也可以同时声明多个变量
 
//声明类型,再声明变量
structStudent{
    char*name;
    intage;
    floatheigth;
};
structStudentstu1,stu2;//变量名是stu1,stu2.可以同时声明多个变量
structStudentstu2;//变量名是stu3

为结构体变量中的成员赋值

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
 
intmain(intargc,constchar*argv[]){
    //声明一个结构体Student1
    structStudent1{
        char*name;
        intage;
        floatheigth;
    };
    structStudentstu1;
    stu1.name="zhoujianfeng";//单独为变量的每个成员赋值
    stu1.age=18;
    stu1.heigth=1.9f;
    
    //声明一个结构体Student2
    structStudent2{
        char*name;
        intage;
        floatheigth;
    };
    structStudentstu2={"zhoujianfeng",18,1.9f};//声明变量的同时初始化
    structStudentstu3={"zhoujianfeng",18};//初始化部分
    structStudentstu4={.age=18};//指定成员初始化
    structStudentstu5=stu2;//将stu2赋值给stu5
    
    return0;
}

使用结构体注意:

1.这个新声明的结构体也是一个数据类型,由程序员自己声明的新类型,所以可以声明这个结构体类型的变量。

2.定义在大括号之中的变量,叫新类型的成员。必须要先声明结构体类型,再声明结构体变量。

3.结构体类型名首字母大写,并且结构体末尾需要加分号,

4.声明一个结构体变量没有初始化,成员的值是垃圾值,如果声明的同时初始化了部分,其他成员初始化为0。

5.相同类型的结构体变量是可以相互赋值的,赋值是将原结构体中的每一个成员的值挨个拷贝给目标结构体变量。

6.结构体变量名,直接代表整个结构体变量。在外面学习到的所有数据类型中,只有数组名、函数名才代表他们的地址。其他都是代表变量本身

四、结构体与数组

语法:struct 结构体类型名 数组名[长度];

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
 
intmain(intargc,constchar*argv[]){
    structStudent{
        char*name;
        intage;
        intscore;
    };
    
    //stuArray数组的每一个元素的类型是一个struct Student结构体类型
    structStudentstuArray[]={
        {"小明",19,99},
        {"小芳",19,99},
        {"小东",18,20}
    };
    
    //单独初始化一个元素,需要做类型强转,不然编译器不知道赋值给数组还是结构体
    stuArray[0]=(structStudent){"小明",19,100};
    
    //数组长度 = 数组占的总字节数  /  每个元素占的字节数
    intlength=sizeof(stuArray)/sizeof(structStudent);
    
    //遍历数组,打印3个学生的信息
    for(inti=0;i<length;i++){
        printf("%s %d %d\n",stuArray[i].name,stuArray[i].age,stuArray[i].score);
    }
    
    return0;
}

五、结构体与指针

结构体变量也是一个变量,那么这个结构体变量一定是有内存地址的,所以我们就可以搞个指针指向这个结构体变量。然后我们就可以通过指针间接操作结构体变量。

语法:struct 结构体类型名 *指针名;

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
 
structStudent{
    char*name;
    intage;
    intscore;
};
intmain(intargc,constchar*argv[]){
    
    //初始化变量
    structStudentstu={"静静",19,100};
    
    //p指针指向stu变量
    structStudent*p=&stu;
    
    //第一种方式
    (*p).name="芳芳";
    (*p).age=18;
    (*p).score=99;
    
    //第二种方式
    p->name="东东";
    p->age=18;
    p->score=99;
    
    printf("%s %d %d\n",p->name,p->age,p->score);
    return0;
}

六、结构体的嵌套

我们在为结构体写成员的时候,发现某个成员也是一个需要多个数据组成一个整体的数据,这个时候我们就可以使用结构体嵌套。在结构体内声明另一个结构体类型的变量作为成员来使用。

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
 
//日期结构体类型
structDate{
    intyear;
    intmonth;
    intday;
};
 
//人结构体类型
structPerson{
    char*name;
    intage;
    structDatebirthday;
};
 
intmain(intargc,constchar*argv[]){
    //创建一个人并赋值
    structPersonzhouJianFeng={"周剑峰",23,{2015,9,18}};
//    struct Person zhouJianFeng = {"周剑峰",23,2015,9,18};//可以成员的省略大括号
    
    //打印出这个人的信息
    printf("姓名:%s\n年龄:%d\n生日:%d年%d月%d日\n",zhouJianFeng.name,zhouJianFeng.age,zhouJianFeng.birthday.year,zhouJianFeng.birthday.month,zhouJianFeng.birthday.day);
    return0;
}

七、结构体与函数

结构体作为函数的参数

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
 
//人结构体类型
structPerson{
    char*name;
    intage;
};
 
voidtest(structPerson*stu){
    stu->name="周剑峰";
    stu->age=18;
}
intmain(){
    
    structPersonzhou={"静静",19};
    test(&zhou);//调用函数,传入地址
    
    printf("%s %d\n",zhou.name,zhou.age);
    return0;
}

结构体作为函数的返回值

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
 
//人结构体类型
structPerson{
    char*name;
    intage;
};
 
structPersongetStu(){
    structPersonstu={"静静",19};
    returnstu;//是返回一个变量的值
}
intmain(){
    
    structPersonstu=getStu();
    printf("%s %d\n",stu.name,stu.age);
    return0;
}

013-结构体-C语言笔记的更多相关文章

  1. 006-循环结构(下)-C语言笔记

    006-循环结构(下)-C语言笔记 学习目标 1.[掌握]do-while循环结构 2.[掌握]for循环结构 3.[掌握]嵌套循环 一.do-while循环结构 do-while语法:   1 2 ...

  2. 005-循环结构(上)-C语言笔记

    005-循环结构(上)-C语言笔记 学习目标 1.[掌握]switch-case结构 2.[理解]case语句穿透 3.[理解]Xcode断点调试 4.[理解]while循环结构初体验 5.[掌握]w ...

  3. 01.C语言关于结构体的学习笔记

    我对于学习的C语言的结构体做一个小的学习总结,总结如下: 结构体:structure 结构体是一种用户自己建立的数据类型,由不同类型数据组成的组合型的数据结构.在其他高级语言中称为记录(record) ...

  4. C语言链表结构体(学习笔记)

    #include <stdio.h> #define LENTEST 100 // 采取逐步删除的方法求的素数 //先假设1-100都是素数,然后剔除2的倍数, //3的倍数,直到剔除所有 ...

  5. Go语言学习笔记十: 结构体

    Go语言学习笔记十: 结构体 Go语言的结构体语法和C语言类似.而结构体这个概念就类似高级语言Java中的类. 结构体定义 结构体有两个关键字type和struct,中间夹着一个结构体名称.大括号里面 ...

  6. C语言文件操作 FILE结构体

    内存中的数据都是暂时的,当程序结束时,它们都将丢失.为了永久性的保存大量的数据,C语言提供了对文件的操作. 1.文件和流 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特 ...

  7. c语言_文件操作_FILE结构体解释_涉及对操作系统文件FCB操作的解释_

    1. 文件和流的关系 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特定字节数的地方结束,这个特定的字节数可以存储在系统维护的管理数据结构中.当打开文件时,就建立了和文件 ...

  8. Go语言结构体(struct)

    Go 语言结构体 Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型. 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合. 结构体表示一项记录,比如保存图 ...

  9. c语言_FILE结构体解释及相关操作

    1. 文件和流的关系 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特定字节数的地方结束,这个特定的字节数可以存储在系统维护的管理数据结构中.当打开文件时,就建立了和文件 ...

随机推荐

  1. 【2019HDU多校】第九场1006/HDU6685-Rikka with Coin——位运算打表

    题目链接 题目大意 使用10.20.50.100元面额的硬币能分别组成题目给出的面额,需要最少的硬币个数 分析 一开始队友想用一堆if-else解决问题,然后WA了无数发-- 我想到了一种比较简单的打 ...

  2. 【科创人独家】PingCAP黄东旭:想告诉图灵这个世界现在的样子

    创业是投己所好 科创人:作为技术圈内著名艺术青年,哪个瞬间会让您更开心,完成一段优美的代码或者乐谱?还是得到来自外界的欢呼与掌声? 黄东旭:在创业之前的很长一段时间里,完成一段代码.写完一首好曲子那一 ...

  3. C 2012年笔试题(保)

    1 程序改错 1.1 下面程序段的功能是交换两个字符数组的内容(每个字符串字符数均不超过100)  (8分)   [ 见2012年笔试题1.1] void StrSwap(char *pa,char ...

  4. 深度学习框架Keras与Pytorch对比

    对于许多科学家.工程师和开发人员来说,TensorFlow是他们的第一个深度学习框架.TensorFlow 1.0于2017年2月发布,可以说,它对用户不太友好. 在过去的几年里,两个主要的深度学习库 ...

  5. BUAA_2020_OO_第一单元总结

    三次作业,三次成长 第一次作业--幂函数求导总结 作业思路和心得 第一次作业的要求只有x的指数这样的幂函数加减组成表达式,对表达式进行求导,而且没有格式错误的检查,所以难度感觉还不是很高.不过由于我寒 ...

  6. 面向对象(OO)第一阶段学习总结

    前言:对OO本阶段作业情况说明 本阶段一共完成三次作业,第一次主要是在主方法里面进行编程,也就是和之前C差不多,而随着学习的深入,慢慢了解到面向对象与面向过程的区别.作业的难度也在慢慢增大,后两次都用 ...

  7. [bzoj2547]玩具兵<Spfa+二分+匈牙利算法>

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2547 挺有意思的一道题,这道题可以划分成几个小题....... 题目大意: 三个兵种在一个 ...

  8. ScheduledThreadPoolExecutor之remove方法

    之前用定时任务的线程池,设置了个任务,但是突然今天产品说,某些个操作需要中断某些任务(如果任务还没有执行),使其不能再到点执行了.于是查了API果然有这样一个方法. 一看API,需要移除的是一个Run ...

  9. 通过jsDelivr + github 搭建一个简易图床

    应用场景: 在大型项目里需要很多图片时,不会直接把图片存储在项目文件夹里,也不推荐直接用数据库存储,而是用第三方存储,cdn,也可以自己搭个存储图片的服务器,等等方式,如果时自己练练手,做做博客,写写 ...

  10. C - 饭卡

    电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够).所以大家 ...