C语言-基础入门-学习笔记(7):函数与文件

C语言-基础入门-学习笔记(7):函数与文件

一. 多文件的程序

当程序规模大、逻辑繁杂时,需要借助更高一层的模块单元:文件。使用文件来组织程序可以提高程序的结构性,使各个功能的模块更为清晰。

1.文件的类型

C程序文件可以分为.c文件和.h文件,其实.c文件称为源文件;.h文件称为头文件。
每一个函数模块都有一个函数声明作为模块接口,类似地,也应当为源文件模块提供一个文件接口。头文件的作用就是提供源文件的接口。要使用某个源文件中的内容时,只需包含其相应的头文件内容即可。

头文件一般包括:
(1)类型声明:

typedef int32_t;

(2)函数声明:

void hello_world(void);

(3)常量定义:

#define ARRAY_SIZE 50
const int MAX_256

<>用来包含系统自带的头文件,系统自带指的是不是你写的,是编译器或者库函数或者操作系统提供的头文件。
""用来包含项目目录中的头文件,这些一般是我们自己写的。

2.组织结构

当程序功能增多,需要将程序划分成多个功能独立的模块,将各个模块封装在一个函数内。一般会称这个超大的程序为“工程”,其中包含很多的.c文件和.h文件。
范例1

/*file1.h*/
#ifndef FILE1_H
#define FILE1_H

#endif

/*file1.c*/
#include <stdio.h>
#include "file1.h"
#include "file2.h"
#include "file3.h"

int main(void){
	hello_world();
	hello_china();
	hello_beijing();

	return 0;
}

/*file2.h*/
#ifndef FILE2_H
#define FILE2_H

void hello_world(void);

#endif

/*file2.c*/
#include <stdio.h>
#include "file2.h"

void hello_world(void){
	printf("Hello,world!\n");
}

/*file3.h*/
#ifndef FILE3_H
#define FILE3_H

void hello_china(void);
void hello_beijing(void);

#endif

/*file3.c*/
#include <stdio.h>
#include "file3.h"

void hello_china(void){
	printf("Hello,china!\n");
}

void hello_beijing(void){
	printf("Hello,Beijing!\n");
}

在这里插入图片描述
在这里插入图片描述

二. 函数的调用

1.嵌套调用

由于C语言规定函数不能定义在函数体内,即不能嵌套定义。但是可以通过在函数中调用函数来实现函数的嵌套。在main中调用函数就是函数的嵌套调用,因为main函数也是函数。

范例2

#include <stdio.h>

void func_1(const int x,const int y){
	printf("Enter func_1():\n");
	printf("\tAction 1.\n");
	printf("Exit func_1():\n");
}

void func_2(const int x,const int y){
	printf("Enter func_2():\n");
	printf("\tAction 2.\n");
	
	func_1(x,y);

	printf("\tAction 3.\n");
	printf("Exit func_2():\n");
}

int main(void){
	int x = 0;
	int y = 0;

	printf("Enter main()\n");
	printf("\tAction 4.\n");

	func_2(x,y);

	printf("\tAction 5.\n");
	printf("Exit main()\n");

	return 0;
}

在这里插入图片描述

2.递归调用

对函数本身进行调用,即函数的递归调用。

1.直接递归调用
直接递归调用就是在函数内部调用函数本身。

void func(void){
	操作1func();
	操作2}

进入func函数后,先执行操作1,再调用func函数。可以吧这个被调用的函数看做是func函数的一个副本,内容与其本身完全一致。以此循环……

2.间接递归调用
当一个函数A调用了另一个函数B,而B函数中又调用了C函数,C函数中又调用了D函数……直到某一个函数又重新调用了函数A,构成一个循环调用的结构。

void fun1(void){
	操作1func2();
	操作2}
void fun2(void){
	操作3func1();
	操作4}

递归需要有边界条件、递归控制段和递归返回段。当边界条件不满足时,递归控制。当边界条件满足时,递归返回。

范例3

//计算数列1到n的和
#include <stdio.h>

int func_sum(const int n){
	if(0 == n)
		return 0;
	else
		return n + func_sum(n-1);
}

int main(void){
	int data = 0;

	printf("Please input a number (greater than 2):");
	scanf("%d",&data);

	printf("1+2+····+%d = %d\n",data,func_sum(data));

	return 0;
}

在这里插入图片描述

范例4

//将输入的十进制数以二进制数形式输出
#include <stdio.h>

void dec_bin(const int x){
	if(x/2 > 0){
		dec_bin(x/2);
		printf("%d",x%2);
	}
	else
		printf("%d",x);
}

int main(void){
	int data = 0;

	printf("Please input a number:");
	scanf("%d",&data);

	printf("The %d's binary mode is : ",data);

	dec_bin(data);
	printf("\n");

	return 0;
}

在这里插入图片描述
范例5

//使用折半法在升序数组中递归查找目标数
#include <stdio.h>

#define SIZE 10

void print_array(int array[SIZE]){
	int i = 0;

	printf("The data in array:\n");
	for(i=0;i<SIZE;i++){
		printf("%4d",array[i]);
	}
}

int find(const int array[SIZE],
		 const int low,
		 const int high,
		 const int target){
	int pos = 0;

	if(low > high)
		return -1;

	pos = (low +high) / 2;

	if(target > array[pos]){
		return find(array,pos+1,high,target);
	}
	else if(target<array[pos]){
		return find(array,low,pos-1,target);
	}
	else{
		return pos;
	}
}

int main(){
	int array[SIZE] = {
		1,2,3,4,5,6,7,8,9,10
	};

	int p = 0;
	int target = 0;

	print_array(array);

	printf("\nPlease input a data: ");
	scanf("%d",&target);

	p = find(array,0,SIZE-1,target);

	if(-1 == p)
		printf("Can't find %d in this array.\n",target);
	else
		printf("%d is the %dth(st/nd) element.\n",target,p+1);

	return 0;
}

在这里插入图片描述

三. 外部函数与内部函数

关键字extern和static可以用来声明函数的类型,使用extern声明的函数为外部函数,使用static声明的函数为内部函数。

1.外部函数

使用extern声明函数的形式如下:
extern 返回值类型 函数名(形参列表);

在没有定义某函数的源文件里使用extern声明该函数,便可以在这个文件内使用该函数。
在函数定义的函数声明中使用关键字extern,那么该函数就允许被其他文件的函数使用。

使用了extern声明函数后,就可以不用预处理命令#include。

int func(void);
extern int func(void);

2.内部函数

使用关键字static声明该函数的作用,是为了限定该对象只能在本文件中使用。 使用static声明的函数一般为文件模块的专用函数。
使用static声明函数的形式如下:
static 返回值类型 函数名(形参列表);
static的优势在于多人写同一个工程时,每个人在自己的源代码中编程,只要将专用函数声明为内部函数,便可不必担心函数名是否与其他人相同。

//file1.c
extern void func_2(void);

int main(void){
	func_2();
}
//file2.c
static void func_2(void){
}

这种情况下由于func_2函数被定义为file2.c文件的内部函数,因此不能被file1.c文件进行调用。

范例6

//file1.c文件
#include <stdio.h>

extern void func_2(void);
extern void func_3(void);

void print_OK(void){
	printf("file1.c is OK.\n");
}

int main(void){
	print_OK();

	func_2();
	func_3();

	return 0;
}

//file2.c文件
#include <stdio.h>

static void print_OK(void){
	printf("file2.c is OK.\n");
}

extern void func_2(void){
	print_OK();
}

//file3.c文件
#include <stdio.h>

static void print_OK(void){
	printf("file3.c is OK.\n");
}

extern void func_3(void){
	print_OK();
}

在这里插入图片描述

练习1

//将范例5的递归函数使用循环结构来实现
#include <stdio.h>

#define SIZE 10

void print_array(int array[SIZE]){
	int i = 0;

	printf("The data in array:\n");
	for(i=0;i<SIZE;i++){
		printf("%4d",array[i]);
	}
}

int find(const int array[SIZE], const int target){
	int low = 0;
	int high = SIZE - 1;
	int pos = 0;

	while(low <= high){
		pos = (low + high) / 2;

		if(target > array[pos]){
			low = pos + 1;
		}else if(target < array[pos]){
			high = pos - 1;
		}else{
			return pos;
		}
	}
	return -1;
}




int main(){
	int array[SIZE] = {
		1,2,3,4,5,6,7,8,9,10
	};

	int p = 0;
	int target = 0;

	print_array(array);

	printf("\nPlease input a data: ");
	scanf("%d",&target);

	p = find(array,target);

	if(-1 == p)
		printf("Can't find %d in this array.\n",target);
	else
		printf("%d is the %dth(st/nd) element.\n",target,p+1);

	return 0;
}

在这里插入图片描述
练习2

main.c

//将加减乘除4种算法实现在一个文件中,并在另一个文件中的main函数一次调用
#include <stdio.h>
#include <string.h>
#include "file2.h"

int main(void){
	int a = 24;
	int b = 6;

	printf("a + b = %d\n",add(a,b));
	printf("a - b = %d\n",sub(a,b));
	printf("a * b = %d\n",pro(a,b));
	printf("a / b = %d\n",div(a,b));

	return 0;
}

file2.c

#include "file2.h"

int add(const int a,const int b){
	return a + b;
}
int sub(const int a,const int b){
	return a - b;
}
int pro(const int a,const int b){
	return a * b;
}
int div(const int a,const int b){
	return a / b;
}

file2.h

#ifndef FILE2_H
#define FILE2_H

int add(const int a,const int b);
int sub(const int a,const int b);
int pro(const int a,const int b);
int div(const int a,const int b);

#endif

在这里插入图片描述

发布了55 篇原创文章 · 获赞 76 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_42826337/article/details/102775549