[C++系列] C语言基础 day13 多文件编程,结构体
in C/C++ with 0 comment

[C++系列] C语言基础 day13 多文件编程,结构体

in C/C++ with 0 comment

#多文件编程

多文件编程的时候一个文件里可以包含多个函数,但是一个函数只能属于一个文件

#多文件编程基本步骤:

1,把所有文件分散在多个不同的文件中。(主函数通常单独占一个文件)
2,为每个源文件编写配对的以.h作为扩展名的头文件。(主函数所在的源文件不需要配对头文件)不分配内存的内容都可以写在头文件里。
头文件里至少应该包含配对源文件里所有函数的声明。
3,在每个源文件里使用#include预处理指令包含必要的头文件。(配对头文件是必要头文件,如果源文件里使用了某个头文件里声明的函数则这个头文件也是必要头文件)
4,可以在gcc命令后列出所有源文件路径就可以编译多文件编写的程序。
5,可以把程序的编译过程记录到makefile文件里,然后使用make工具按照makefile文件里记录的过程完成编译工作。
头文件内容应该被包含在预处理指令中,这样可以避免多次编译。第一个预处理指令必须是#ifndef
6,头文件里使用的宏名称必须根据文件名变化得到。

#练习

采用多文件编程的方法编写程序
程序里包含一个函数可以从键盘得到一个整数并把结果传递回调用函数。

add.h

#ifndef        __ADD_H__
#define        __ADD_H__
int add(int,int);
#endif
add.c 

#include"add.h"
int add(int num,int num1){
return num+num1;
}
main.c 

#include<stdio.h>
#include "read.h"
int main()
{
read();
printf("%d\n",num);
return 0;
}
编译方式:

gcc main.c add.c \\或者编写makefile文件,这里不作演示。

注意

###如果希望在A文件里使用B文件里声明的全局变量。就需要在A文件里使用extern 关键字再次声明这个全局变量。
使用extern关键字声明变量的语句通常放在头文件里。

###不可以跨文件使用静态全局变量。

#结构体

C语言可以在一个存储区里记录多个数字,这种存储区的类型叫做结构体类型。这种类型需要先创建然后才能使用。
结构体类型的存储区里包含多个子存储区,每个子存储区用来记录一个数字。
结构体的子存储区类型和以不同,子存储区甚至也可以是结构体类型的存储区。
结构体声明语句可以用来创建结构体类型。
结构体声明语句里需要使用struct关键字。

结构体声明语句里包含多个变量声明语句,它们叫做结构体的成员变量。。每个成员变量代表了结构体的一个子存储区。
成员变量的声明语句不会分配内存,它们只是用来表示子存储区的类型和名称。成员变量不能初始化。

在c语言中的结构体不可以包含函数。
因为结构体声明语句不分配内存,所以这种语句可以写在任何地方,包括头文件里。

可以把结构体作为类型声明变量,这种变量叫做结构体变量。
声明结构体变量的时候应该把struct关键字和结构体名称一起作为类型名称使用。

结构体变量被分配了内存,可以用来记录数字。

typedef关键字可以给一个数据类型起别名,这个别名完全可以替代原来的类型名称。
结构体类型通常会给它起别名。
可以把结构体声明语句和起别名的语句合并成一条语句。这个时候可以省略结构体本身的名称。
结构体变量也应该初始化。
可以像初始化数组一样来初始化结构体变量。

#include<stdio.h>
typedef struct{
     int age;
     float height;
     char name[10];
} sperson;
//typedef struct person sperson;  //一般的结构子变量声明方式
// sperson prson  //简化后的声明方式。
int main(){
     sperson prsn = {20,1.76f,"drop"};
     return 0;
}

#使用结构体

结构体变量通常是不能作为整体使用,一次只能使用其中的某个子存储区

采用以下写法可以表示结构体变量的某个子存储区。
prsn.age
其中prsn是一个结构体变量的名称,age是一个成员变量的名称。

#include<stdio.h>
typedef struct{
     int age;
     float height;
     char name[10];
} person;
int main(){
     person prsn;
     printf("输入年龄:");
     scanf("%d",&(prsn.age));
     printf("输入身高:");
     scanf("%g",&(prsn.height));
     scanf("%*[^\n]");
     scanf("%*c");
     printf("输入名字:");
     scanf("%s",&(prsn.name));
     printf("%d,%g,%s\n",prsn.age,prsn.height,prsn.name);
     return 0;
}

同类型结构体变量之间可以直接赋值。

结构体指针用来记录一个结构体存储区的地址。
当结构体指针和结构体存储区捆绑以后可以使用如下写法通过结构体指针表示子存储区。
p_person -> age
其中p_person是一个结构体指针,age是一个成员变量名称。

#include<stdio.h>
typedef struct{
int age;
float height;
char name[10];
} person;
int main(){
person prsn;
person prsn2;
person *p_person = NULL; //结构体指针
printf("输入年龄:");
scanf("%d",&(prsn.age));
printf("输入身高:");
scanf("%g",&(prsn.height));
printf("输入名字:");
scanf("%s",&(prsn.name));
printf("%d,%g,%s\n",prsn.age,prsn.height,prsn.name);
prsn2 = prsn;
printf("%d,%g,%s\n",prsn2.age,prsn2.height,prsn2.name);
p_person = &prsn;
printf("%d,%g,%s\n",p_person->age,p_person->height,p_person->name);
return 0;
}

#练习

*声明一个结构体,这个结构体类型的变量可以用来记录一个点的位置。

typedef struct{
     int x;
     int y;
} point;

声明一个结构体,这个结构体可以记录一个水平长方形的位置。

typedef struct{
     point pt1;
     point pt2;
} rectl;

输入水平长方形的位置,计算它的面积

#include<stdio.h>
typedef struct {
    int row;
    int col;
} point;
typedef struct {
    point pt1;
    point pt2;
}rect;
int main(){
     int area;
    rect rc = {0};
    printf("输入水平长方形的位置:");
    scanf("%d%d%d%d",&(rc.pt1.row),&(rc.pt1.col),&(rc.pt2.cow),&(rc.pt2.col));
    area = (rc.pt1.row-rc.pt2.row)*(rc.pt1,col-rc.pt2.col);
    area = area > 0 ? area : 0 - area;
    printf("水平长方形面积为:%d",area);
    return 0;
}

用结构体指针改写以上程序。

#include<stdio.h>
typedef struct {
    int row;
    int col;
} point;
typedef struct {
    point pt1;
    point pt2;
}rect;
int main(){
    rect rc = {0};
    rect *p_r = &rc;

    printf("输入水平长方形的位置:");
    scanf("%d%d%d%d",&(p_r->pt1.row),&(p_r->pt1.col),&(p_r->pt2.row),&(p_r->pt2.col));
    int area = (p_r->pt1.row-p_r->pt2.row)*(p_r->pt1.col-p_r->pt2.col);
    area = area > 0 ? area : 0 - area;
    printf("面积:%d\n",area);
    return 0;
}

#传递结构体数据

调用函数被调用函数传递数据的时候应该使用结构体指针类型的形式参数。

#include<stdio.h>
typedef struct {
    int row;
    int col;
} pt;
void print(const pt *p_pt){
    printf("点的位置为,%d,%d\n",p_pt->row,p_pt->col);
}
int main(){
    pt pt1;
    printf("输入一个点的位置:");
    scanf("%d%d",&(pt1.row),&(pt1.col));
    print(&pt1);
return 0;
}

声明结构体指针结构参数的时候尽量使用const关键字。

从被调用函数向调用函数传递结构体数据的时候需要使用结构体存储区的地址作为返回值。(这个时候被调用函数需要提供一个结构体指针存储区来存放这个返回值。)

不可以把非静态局部结构体变量的地址作为返回值使用。

#include<stdio.h>
typedef struct {
    int row;
    int col;
} pt;
pt *read(pt *p_pt){
    printf("输入点的位置:");
    scanf("%d%d",&(p_pt->row),&(p_pt->col));
    return p_pt;
}
int main(){
    pt pt1;
    read(&pt1);
    printf("点的位置为,%d,%d\n",pt1.row,pt1.col);
return 0;
}
#include<stdio.h>
typedef struct {
    int row;
    int col;
} pt;
void print(const pt *p_pt){
    printf("点的位置为,%d,%d\n",p_pt->row,p_pt->col);
}
pt *read(pt *p_pt){
    printf("输入点的位置:");
    scanf("%d%d",&(p_pt->row),&(p_pt1->col));
    return p_pt;
}
int main(){
    pt pt1;
    read(&pt1);
    print(&pt1);
return 0;
}

#练习

编写函数,从调用函数得到一个水平长方形的位置,然后把水平长方形的面积传递回调用函数。

#include<stdio.h>
typedef struct {
    int row;
    int col;
} pt;
typedef struct {
    pt pt1;
    pt pt2;
} rect;
int area(const rect *p_r){
    int ret = (p_r->pt1.row-p_r->pt2.row)*(p_r->pt1.col-p_r->pt2.col);
    return ret >= 0 ? ret : 0-ret;
}   
int main(){
    rect rc;
    printf("输入一个水平长方形的位置:");
    scanf("%d%d%d%d",&(rc.pt1.row),&(rc.pt1.col),&(rc.pt2.row),&(rc.pt2.col));
    int num = area(&rc);
    printf("面积是:%d\n",num);
return 0;
}

编写函数计算水平长方形的中心点位置并把结果传递给调用函数。

#include<stdio.h>
typedef struct {
    int row;
    int col;
} pt;
typedef struct {
    pt pt1;
    pt pt2;
} rect;
int area(const rect *p_r){
    int ret = (p_r->pt1.row-p_r->pt2.row)*(p_r->pt1.col-p_r->pt2.col);
    return ret >= 0 ? ret : 0-ret;
}   
pt *location_cent(const rect *p_r,pt *p_pt){
    p_pt->row = (p_r->pt1.row+p_r->pt2.row)/2;   
    p_pt->col = (p_r->pt1.col+p_r->pt2.col)/2;
    return p_pt;
}
int main(){
    rect rc;
    pt pt_cent;
    printf("输入一个水平长方形的位置:");
    scanf("%d%d%d%d",&(rc.pt1.row),&(rc.pt1.col),&(rc.pt2.row),&(rc.pt2.col));
    int num = area(&rc);
    printf("面积是:%d\n",num);
    location_cent(&rc,&pt_cent);
    printf("中心点是:(%d,%d)\n",pt_cent.row,pt_cent.col);
    return 0;
}

预习

* 数据对齐和补齐
* 枚举和联合
* 二级指针
* 函数指针
* 回调函数
Responses