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 多文件编程
在Windows的VS、Qt等软件中可以用方法二,但是在Linux中只能用第一种方法避免重复调用
创建多个项目的方法:在解决方案中点击添加,新建项目,然后创建项目,就可以吧多个项目放在一个解决方案中了。
调用的头文件和源文件最好起一样的名字,这样后面方便查看。
在cmd中编译的时候,gcc -o hello.exe 01main.c 02fun.c 02fun.h head.h,这些源文件头文件都可以写在一起,编译器会自动识别哪一个是主函数。
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 到这里为宏定义结束的标志位