函数
认识函数
如何创建函数
-
常用函数
-
主函数
int main() { return 0; }
-
-
函数基本组成部分
-
函数返回值类型
-
函数名
-
参数列表
-
函数体
//自己写的函数,函数的组成 函数返回值类型 函数名(参数列表) { 函数体; return 返回值; //返回值: 可以是一个值,可以是一个表达式,因为表达式最终的结果也是一个值,也可以是条件表达式 }
-
-
未定义问题
- 由于函数是自上往下逐步运行的,所以当我们自己定义的函数写在了主函数下面就会出现函数未定义问题
- 解决办法
- 在主函数上面声明或者函数实现直接写在主函数前面
- 解决办法
- 由于函数是自上往下逐步运行的,所以当我们自己定义的函数写在了主函数下面就会出现函数未定义问题
-
一般设计函数遵循单一性原则,也就是一个函数一个功能
函数调用
-
函数调用:函数名(参数列表);
-
错误调用
void printf() { }
-
返回值类型
-
有返回值:由后面的return的值的类型决定
-
无返回值:void
-
C语言只能返回一种类型数据,不存在返回多个值
-
没有返回值可以存在return
-
可以通过结构体封装多种数据
-
函数调用准则:尽量要实参和形参类型保持一致
-
函数调用的时候所有传参的方式都是赋值的方式,也就是说形参=实参
float print() { return 1.1f; //1.1f是float类型 需要和函数返回值类型保持一致 } int printA() { return 1; } int printInt() { return 12,14,15; //12,14,15是一个逗号表达式,所以返回15 } //没有返回值 void printVoid() { return ; //因为在任何一函数中,遇到return 整个函数结束 }
-
函数调用的过程
#include <stdio.h>
//求字符串可见长度
int mystrlen(char array[])
{
int count = 0;
while (array[count] != '\0')
count++;
return count;
}
//字符串的连接
void mystrcat(char str1[], char str2[])
{
int i = 0;
//先走到第一个字符串最后面
while (str1[i] != '\0')
i++;
int j = 0;
//把第二个字符串赋值到第一个字符串后面
while (str2[j] != '\0')
str1[i++] = str2[j++];
//str1[i++] = str2[j++]
//i=4 j=0
//str1[4]=str2[0];
//str1[5]=str2[1]
}
//字符串的拷贝
//这个问题不需要考虑,str1长度大于str2
void mystrcpy(char str1[], char str2[])
{
int j = 0;
while (str2[j] != '\0')
{
str1[j] = str2[j];
j++;
//str1[0]=str2[0];
//str1[1]=str2[1];
}
str1[j] = '\0';
}
//小写转大写
void myupper(char str[])
{
int i = 0;
while (str[i] != '\0')
{
if (str[i] >= 'a' && str[i] <= 'z')
{
//a-A=str[i]-result
//result=str[i]+'A'-'a';
str[i]+='A' - 'a';
}
i++;
}
}
//大写转小写
void mylower(char str[])
{
int i = 0;
while (str[i] != '\0')
{
if (str[i] >= 'A' && str[i] <= 'Z')
{
//a-A=result-str[i]
//result=str[i]+'A'-'a';
str[i] +='a'-'A';
}
i++;
}
}
int main()
{
char str[] = { "ILoveyou" }; //可见长度不包含\0
printf("%d\n", mystrlen(str));
//first大小一定是大于等于 mystrlen(first)+mystrlen(second)
char first[20] = "str123";
char second[] = "str2";
mystrcat(first, second);
puts(first);
mystrcpy(first, second);
puts(first);
myupper(str);
puts(str);
mylower(str);
puts(str);
return 0;
}
函数参数
-
没有参数
-
没有参数可以什么都不写
-
没有参数可以写一个void
-
参数列表里面加了void是不能传参的
//没有参数的 void print(void){} void printINT(){}
-
-
有参数
-
形式参数(形参)
- 在定义一个函数的时候是形式参数(形参)
-
实际参数(实参)
- 在调用函数的时候是实际参数(实参)
-
什么时候需要传参
- 该函数需要用到调用者所在的函数中的变量的时候,都需要传参
//有参数的 void printAB(int a,int b) //a和b叫做形式参数 { //int a=aa ,int b=bb; int sum=a+b; } int main() { int aa=1; int bb=2; printAB(aa,bb); return 0; }
-
函数参数传参过程
#include <stdio.h>
//所有传参的方式都是参数赋值
int sum(int a, int b)
{
return a + b;
}
int Max(int a, int b)
{
return a > b ? a : b;
}
void modify(int a) //int a=1;
{
a = 1001;
}
int modifyNum()
{
return 1001;
}
//特殊传参方式
//数组专有传参方式
//数组充当函数参数的时候通常都需要带上数组的尺寸
//除了字符串数组之外,可以不需要尺寸
//1.一维数组
//通过子函数打印一维数组
void printArray1D(int array1D[], int arrayNum)
{
for (int i = 0; i < arrayNum; i++)
{
printf("%d\t", array1D[i]);
}
printf("\n");
}
//2.二维数组
//int array[][常量] 并且要和实参的长度一致
void printArray2D(int array[][4], int row, int cols)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < cols; j++)
{
printf("%d\t", array[i][j]);
}
printf("\n");
}
}
int main()
{
int aa = 1;
int bb = 2;
printf("sum=%d\n", sum(aa, bb)); //实际参数
printf("Max=%d\n", Max(aa, bb)); //实参
int cc = 1;
modify(cc); //因为形参是拷贝本,所以不能改变实参的值
printf("%d\n", cc); //打印的还是1
//cc = returnNum(); //通过赋值的修改了cc值
//printf("%d\n", cc);
int array1D[3] = { 1,2,3 };
printArray1D(array1D,3); //传参的时候是数组名
int num1D[10] = { 1,2,3,4,5,6,7,8,9,10 };
printArray1D(num1D, 10);
int array2D[3][4] = { 1,2,3,4,1,2,3,4,1,2,3,4 };
printArray2D(array2D, 3, 4);
return 0;
}
函数返回值
-
函数返回值是函数调用后唯一产物,也就是函数调用的表达式代表的值
int main() { int aa=1; int bb=2; int result=returnNum(aa,bb); //returnNum(aa,bb)代表a+b 表达式的值 printf("%d\n",returnNum(aa,bb)); printf("%d\n",result); return 0; }
-
什么时候需要返回值
-
在调用者函数中需要用到调用函数处理结果的时候
int returnNum(int a,int b) { return a+b; }
-
-
函数返回值返回的是上面东西由写代码的人决定
函数返回值类型和函数返回值应用
#include <stdio.h>
//声明语法
void print();
//没有返回值的:一般用来做效果类的处理(打印,绘制过程等)
void makeMenu()
{
printf("-------------------\n");
printf("\t0.退出系统\n");
printf("\t1.录入系统\n");
printf("\t2.修改\n");
printf("-------------------\n");
}
int returnInt()
{
int num = 0;
printf("input a num:");
scanf_s("%d", &num);
return num;
}
//求和
int Sum(int a, int b)
{
return a + b;
}
//求大小
int Compare(int a, int b)
{
return a > b;
}
//当类型不一致的时候的处理
// warning C4244: “return”: 从“float”转换到“int”,可能丢失数据
//以函数返回值类型 做类型转换
//1.11f 转换为int 类型
int returnFloat()
{
int temp = 0; //局部
return 1.11f;
}
//不要返回值局部变量的地址
int main()
{
print(); //函数通常描述一个功能,可以重复使用
print();
float num = returnFloat();
return 0;
}
void print()
{
printf("ADSF\n");
printf("dsafcd\n");
printf("RTGFDFG\n");
printf("ADSFsdafd\n");
printf("SFDHerfg\n");
}
函数应用——汉诺塔问题
-
递归调用
#include <stdio.h> int move(int n, int x, int y, int z) { if (n == 1) printf("%c--->%c\n", x, z); else { move(n - 1, x, z, y); printf("%c--->%c\n", x, z); move(n - 1, y, x, z); } } int main() { int h; printf("请输入数值:\n"); scanf_s("%d", &h); printf("\n汉诺塔移动如下:%2d级:\n", h); move(h, 'a', 'b', 'c'); return 0; }