lesson 6 函数


6. 函数

6.1 概述

调用函数时,需要关心5个要素:

  • 头文件:包含指定的头文件
  • 函数名:函数名必须和头文件声明的名字一样
  • 功能:知道函数能干什么以后才能调用
  • 参数:参数类型需要匹配
  • 返回值:根据需要接受返回值

随机数函数需要导入的头文件:#include

#include 
#include 
#include 

int main()
{
	//time_t timer = time(NULL);
	//srand((size_t)timer(NULL));
	//添加随机数种子
	srand((size_t)time(NULL));

	for (int i = 0; i < 10; i++)
	{
		printf("%d\n", rand()%100);//通过取余可以约束随机数范围,%100就是0-99范围内
		
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d\n", rand() % 51 + 50);//范围是50-100
	}

	return 0;
}


输出:

2
37
38
65
76
15
89
33
13
63
52
94
100
80
71
56
90
82
78
51

6.2 函数的定义与使用

在函数调用的过程中传递的参数为实参,有具体的值。

在函数定义的过程中,参数称为形参,在不同函数中变量名可以重名,因为作用域不同

函数调用的过程是将实参传递给形参

函数在调用结束后,会在内存栈区中被销毁,由系统完成

函数返回值只能有一个值,但可以是数组,如果返回类型与return语句中表达式值不一致,则以函数返回类型为准,即函数返回类型决定了返回值的类型。

#include

//返回值类型 函数名(参数列表)
//{}里面叫函数的代码体或者函数体	return要和返回值类型对应
int add(int a, int b)
{
	int sum = a + b;
	return sum;
}
int main()
{
	int a = 10;
	int b = 20;
	int c = add(a, b);//函数调用
	printf("%d\n", c);

	return 0;

}

输出:30

#include

//返回值类型 函数名(参数列表)
//{}里面叫函数的代码体或者函数体	return要和返回值类型对应
int add(int a, int b)
{
	int sum = a + b;
	return sum;
}
int main0201()
{
	int a = 10;
	int b = 20;
	int c = add(a, b);//函数调用
	printf("%d\n", c);

	return 0;

}

void swap(int a, int b) {
	printf("交换前的数据:\n");
	printf("a=%d\n", a);
	printf("b=%d\n", b);
	int temp = a;
	a = b;
	b = temp;

	
}
int main()
{
	int a = 10;
	int b = 20;

	swap(a, b);
	printf("交换后的数据:\n");
	printf("a=%d\n", a);
	printf("b=%d\n", b);
	return 0; 
}

输出:

交换前的数据:
a=10
b=20
交换后的数据:
a=10
b=20

实参变量对形参变量的数据是“值传递”,即单向传递,只能实参传给形参,不能由形参传回给实参

实参和形参是不同的单元,调用结束后形参单元被释放,实参单元仍保留并维持原值。因此,在执行一个被调函数时,形参的值如果发生变化,并不会改变主调函数中实参的值

#include


int my_strcmp(char ch1[],char ch2[])
{
	int i = 0;
	while (ch1[i] == ch2[i])
	{
		//是否到字符串结尾
		if (ch1[i] == '\0')
		{
			return 0;
		}
		i++;
	}
	return ch1[i] > ch2[i] ? 1 : -1;
}
int main()
{
	char ch1[] = "hello";
	char ch2[] = "hello";
	//比较两个字符串,相同返回0,如果不同返回1或-1
	int value = my_strcmp(ch1, ch2);
	if (value == 0)
	{
		printf("两个字符串相同");
	}
	else {
		printf("两个字符串不同");
	}
	

	return 0;
}

输出:

两个字符串相同

6.3 无参函数调用

#include
#include
#include


void fun01()
{
	printf("helloworld\n");
}
int fun02()
{
	return rand() % 10;
	
}
int main()
{
	srand((unsigned int)time(NULL));
	int a= fun02();
	printf("%d\n", a);
	fun01();
	return 0;
}

输出:

2
helloworld

直接函数名,不加括号,是函数的指针地址

6.4 有参函数

void BubbleSort(int arr[],int len)//冒泡排序函数版
{
	for (int i = 0; i < len-1; i++)
	{
		for (int j = 0;  j < len-1-i;  j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}

int main()
{
	int arr[] = { 9,1,8,2,3,5,4,6,10,7 };
	BubbleSort(arr, sizeof(arr) / sizeof(arr[0]));

	for (int i = 0; i < 10; i++)
	{
		printf("%d\t", arr[i]);
	}
	//void c =30//error
	//void类型不可以直接定义数据,但是可以作为函数的返回值,表示没有返回值
}

输出:

1 2 3 4 5 6 7 8 9 10

6.5 函数的声明

函数在主函数之前可以不声明,如果放在主函数之后就必须要提前声明才可以使用

从广义来说,声明包含了定义,即定义是一个特例,所以并非所有的声明都是定义

int b既是声明,又是定义。 extern b则只是声明, 不是定义

#include
#include
#include


//函数声明

extern int add1(int a, int b);//extern可以被省略,可以写成int add1(int , int);
//函数定义
//函数调用

//函数可以多次被声明和调用,但是定义只能一次
int main()
{
	int c=add1(10, 20);
	printf("%d\n", c);
	return 0;
}



int add1(int a,int b)
{
	return a + b;
}

输出:30

#include

void fun02()
{
	printf("hello world\n");
	printf("hello world\n");
	printf("hello world\n");
	
	exit(0);//终止程序执行
	printf("hello world\n");
	return;
	printf("hello world\n");
	printf("hello world\n");
	return 0;
}

int main()
{
	fun02();
	printf("hello world\n");
	printf("hello world\n");
	printf("hello world\n");
	return -1;
	printf("hello world\n");
	return;
}

输出:

hello world
hello world
hello world

6.6 多文件编程

image.png

在Windows的VS、Qt等软件中可以用方法二,但是在Linux中只能用第一种方法避免重复调用

创建多个项目的方法:在解决方案中点击添加,新建项目,然后创建项目,就可以吧多个项目放在一个解决方案中了。

调用的头文件和源文件最好起一样的名字,这样后面方便查看。

在cmd中编译的时候,gcc -o hello.exe 01main.c 02fun.c 02fun.h head.h,这些源文件头文件都可以写在一起,编译器会自动识别哪一个是主函数。

image.png

01main.c

#include 
#include "head.h"//导入自己写的头文件用双引号

int main()
{
    int a = 10;
    int b = 20;
    int c=max(a, b);
    printf("%d\n", c);
}

02fun.c

//函数定义
int max(int a, int b)
{
	return a > b ? a : b;
}

head.h

#pragma once//作用是防止头文件重复包含
#ifndef 1	__02__FUN_H__//如果宏定义没定义

#define __02__FUN_H__


//全局变量的定义
//函数的声明
extern int max(int a, int b);

#endif // !1  到这里为宏定义结束的标志位