目录

  • 一、函数是什么
  • 二、C语言中函数的分类
    • 1、如何学会使用库函数
      • 1.1、strcpy
      • 1.2、memset
    • 2、自定义函数
      • 2.1、与库函数的区别
      • 2.2、写一个函数可以找出两个整数的最大值
      • 2.3、写一个函数可以交换两个整形变量的内容
        • 无函数
        • err 传值
        • 正确写法 传址
  • 三、函数参数
    • 1、实际参数
    • 2、形式参数
  • 四、函数调用
    • 传值、传址
  • 五、练习
    • 1、写一个函数判断一个数是不是素数
    • 2、写一个函数判断是不是闰年
    • 3、写一个函数 实现一个整数有序数组的二分查找
    • 4、写一个函数 每调用一次这个函数 就会将num的值增加一次
  • 六、函数的嵌套调用和链式访问
    • 1、函数可以嵌套调用,但不能嵌套定义
    • 2、链式访问
    • 3、打印什么
  • 七、函数的声明和定义
    • 1、函数声明add.h
    • 2、函数实现add.c
    • 3、引头文件test.c
    • 4、引用头文件问题
    • 5、#pragma once
    • 6、分快去写的好处:
      • 多人协作
      • 封装和隐藏
  • 八、函数递归
    • 1、练习1 - 接受一个整型值(无符号),按照顺序打印它的每一位
      • 分析:
    • 2、递归的两个必要条件
    • 3、练习2 - 编写函数不允许创建临时变量,求字符串的长度
      • 变量求:
      • 用函数,还是有临时变量count
      • 函数递归解决
        • 分析:
    • 4、递归与迭代
      • 4.1、练习3 - 求n的阶乘(不考虑溢出)
        • 用循环
        • 递归求
          • 分析:
      • 4.2、练习4 - 求第n个斐波那契数
        • 用递归求
        • 迭代(循环)
          • 分析:
    • 5、什么时候用递归
      • 汉诺塔
  • 九、分支与循环getchar补充
    • 1、getchar
    • 2、getchar读取密码
      • 2.1、缓冲区
      • 2.2、getchar清理\n
      • 2.3、清除缓冲区
    • 3、ch = getchar()) != EOF
  • 十、练习
    • 1、能把函数处理结果的二个数据返回给主调函数
      • 1.1、return 2个值(err)
      • 1.2、形参用数组
      • 1.3、形参用2个指针
      • 1.4、用2个全局变量
    • 2、复合语句定义的变量在本函数范围内有效
    • 3、实现一个函数,打印乘法口诀表,口诀表的行数和列数自己指定
    • 4、==字符串逆序==
      • 4.1、用函数循环
      • 4.2、递归版本
        • 分析:
    • 5、计算一个数的每位之和
    • 6、递归实现n的k次方

一、函数是什么

一个大型程序中的某部分代码 由一个或多个语句块组成
负责完成某项特定任务 具有独立性
一般会有输入参数和返回值 提供对过程的分装和细节的隐藏



二、C语言中函数的分类

  1. 库函数
  2. 自定义函数

1、如何学会使用库函数

cplusplus

1.1、strcpy

#include <stdio.h>
#include <string.h>int main()
{char arr1[20] = { 0 }; // 目标空间char arr2[] = "hello";strcpy(arr1, arr2);printf("%s\n", arr1);return 0;
}
#include <stdio.h>
#include <string.h>int main()
{char arr1[20] = "xxxxxxxxx"; // 目标空间char arr2[] = "hello";char* ret = strcpy(arr1, arr2);printf("%s\n", arr1); // hello printf("%s\n", ret); // hello// \0 字符串的结束标志return 0;
}

1.2、memset

#include <stdio.h>#include <string.h>// memset
int main()
{char arr[] = "hello bit";char* ret = (char*)memset(arr, 'x', 5);printf("%s\n", ret); // xxxxx bitreturn 0;
}

memset以字节为单位初始化
//memset( arr,1,5 * sizeof(int) ); // 把前5个整形 20个字节设计成1

2、自定义函数

2.1、与库函数的区别

  1. 与库函数一样 有函数名,返回值,函数参数
  2. 不一样的是这些都是我们自己来设计 有很大的发挥空间

// 函数的组成
// ret_type fun_name(paral, *)
// {
// statement; // 语句项
// }
// 返回类型 函数名 函数参数

2.2、写一个函数可以找出两个整数的最大值

#include <stdio.h>int get_max(int x, int y) // 形式参数
{return (x > y ? x : y);
}int main()
{int a = 0;int b = 0;scanf("%d%d", &a, &b);int max = get_max(a, b); // 实际参数printf("max = %d\n", max);return 0;
}

2.3、写一个函数可以交换两个整形变量的内容

无函数

int main()
{int a = 10;int b = 20;int c = 0;printf("交换前:a=%d b=%d\n", a, b);c = a;a = b;b = c;printf("交换后:a=%d b=%d\n", a, b);return 0;
}

err 传值

void Swap(int x, int y)
{int z = 0;z = x;x = y;y = z;
}int main()
{int a = 10;int b = 20;int c = 0;printf("交换前:a=%d b=%d\n", a, b);Swap(a, b);// 实参a和b 穿给形参x,y时,形参将是实参的一份临时拷贝// 改变实参变量x,y不会影响实参a,bprintf("交换后:a=%d b=%d\n", a, b);return 0;
}

正确写法 传址

void Swap(int* px, int* py)
{int z = 0;z = *px;*px = *py;*py = z;
}int main()
{int a = 10;int b = 20;int c = 0;printf("交换前:a=%d b=%d\n", a, b);// 函数Swap(&a, &b);printf("交换后:a=%d b=%d\n", a, b);return 0;
}


三、函数参数

1、实际参数

实参可以是:常量 变量 表达式 函数

int get_max(int x, int y)
{return (x > y ? x : y);
}int main()
{int a = 0;int b = 0;scanf("%d%d", &a, &b);int max = get_max(a, get_max(3, 5));//int max = get_max(b, 20-1);printf("max = %d\n", max);return 0;
}

2、形式参数

只有在函数调用的过程中才会分配空间
调用完成后销毁 因此形式参数只在函数内有效



四、函数调用

传值、传址

取以上“写一个函数可以交换两个整形变量的内容”的两个Swap例子
Swap1是传值调用,因为形参是实参的一份临时拷贝,对形参的修改不会影响实参,所以不能对a和b进行交换
Swap2是传址调用,函数和函数外的变量可以建立真正的联系

传值调用
// 形参是实参的一份临时拷贝,对形参的修改不会影响实参

传址调用
// 把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式
// 可以让函数和函数外的变量建立真正的联系,也就是函数内部可以直接操作函数外部的变量

void Swap1(int x, int y)
{int z = 0;z = x;x = y;y = z;
}void Swap2(int* px, int* py)
{int z = 0;z = *px;*px = *py;*py = z;
}int main()
{int a = 10;int b = 20;Swap1(a, b); // 传值调用Swap2(&a, &b); // 传址调用return 0;
}


五、练习

1、写一个函数判断一个数是不是素数

#include <stdio.h>
#include <math.h>int is_prime(int n)
{// 试除法// 2 ~ n-1// 2~sqrt(n)int j = 0;for (j = 2; j <= sqrt(n); j++){if (n % j == 0)return 0;}return 1;
}int main()
{int i = 0;int cnt = 0;for (i = 100; i <= 200; i++){if (is_prime(i) == 1){printf("%d ", i);cnt++;}}printf("\ncnt = %d\n", cnt);return 0;
}

2、写一个函数判断是不是闰年

int is_leap_year(int y)
{if ((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)){return 1;}elsereturn 0;
}int main()
{int y = 0;for (y = 1000; y <= 2000; y++){if (is_leap_year(y) == 1){printf("%d ", y);}}
}

3、写一个函数 实现一个整数有序数组的二分查找

int binary_search(int arr[], int k, int sz)
{int left = 0;int right = sz - 1;while (left <= right){int mid = (left + right) / 2;if (arr[mid] < k)left = mid + 1;else if (arr[mid] > k)right = mid - 1;elsereturn mid;}// 找不到return -1; // 0有可能是下标
}int main()
{int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int k = 7;int sz = sizeof(arr) / sizeof(arr[0]);int ret = binary_search(arr, k, sz); // TDD - 测试驱动开发if (ret == -1)printf("找不到\n");elseprintf("找到了,下标是:%d\n", ret);return 0;
}

限制范围 找3找不到

int binary_search(int arr[], int k, int left, int right)
{while (left <= right){int mid = (left + right) / 2;if (arr[mid] < k)left = mid + 1;else if (arr[mid] > k)right = mid - 1;elsereturn mid;}return -1;
}int main()
{int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int k = 3;int sz = sizeof(arr) / sizeof(arr[0]);int ret = binary_search(arr, k, 5, 9);if (ret == -1)printf("找不到\n");elseprintf("找到了,下标是:%d\n", ret);return 0;
}

4、写一个函数 每调用一次这个函数 就会将num的值增加一次

void Add(int* p)
{*p = *p + 1;
}int main()
{int num = 0;Add(&num);printf("%d\n", num); // 1Add(&num);printf("%d\n", num); // 2Add(&num);printf("%d\n", num); // 3return 0;
}
int Add(int* n)
{return n + 1;
}int main()
{int num = 0;num = Add(num);printf("%d\n", num); // 1num = Add(num);printf("%d\n", num); // 2num = Add(num);printf("%d\n", num); // 3return 0;
}


六、函数的嵌套调用和链式访问

1、函数可以嵌套调用,但不能嵌套定义

int main()
{// 函数嵌套定义 - err/*void test(){printf("hehe\n");}*/return 0;
}

2、链式访问

  • 把一个函数的返回值作为另一个函数的参数
int main()
{int len = strlen("abc");printf("%d\n", len);printf("%d\n", strlen("abc")); // 链式访问return 0;
}
int main()
{char arr1[20] = "xxxxxxxxx";char arr2[] = "abc";// strcpy(arr1, arr2);printf("%s\n", strcpy(arr1, arr2));return 0;
}

3、打印什么

#include <stdio.h>int main()
{printf("%d", printf("%d", printf("%d", 43)));return 0;
}

// printf 函数返回的是打印在屏幕上的字符的个数
// 如果发生错误 将返回负数
//
printf("%d", printf("%d", 2)); // 43是2位数
// 43
printf("%d", 1);
// 432
// 4321
// 结果是4321




七、函数的声明和定义

1、函数声明add.h

函数的声明一般出现在函数的使用之前,要满足先声明后使用
函数声明放在头文件里
新建头文件add.h

// add.h#pragma once// 函数的声明
extern int Add(int x, int y);

2、函数实现add.c

函数的实现在对应的.c文件里
新建add.c文件

// add.cint Add(int x, int y)
{int z = x + y;return z;
}

3、引头文件test.c

引用头文件"add.h"
就可以使用了

#include <stdio.h>// 函数的声明一般出现在函数的使用之前,要满足先声明后使用#include "add.h"int main()
{int a = 10;int b = 20;int ret = Add(a, b);printf("%d\n", ret);return 0;
}

4、引用头文件问题

引用头文件"add.h",而不需要引用对应的"add.c":
test.c与add.c经过各自编译后,产生对应的.obj文件,链接产生test.exe可执行程序


5、#pragma once

  • 头文件出现的 #pragma once

    • 它的作用主要是:防止头文件被重复多次引用
    • 等价于:
      #ifndef __ADD_H__
      #define __ADD_H__
      #endif
// #pragma once#ifndef __ADD_H__
#define __ADD_H__extern int Add(int x, int y);#endif

6、分快去写的好处:

多人协作

封装和隐藏

// add.c和add.h 编译生成一个add.lib文件(点头文件右击属性- 常规- 配置类型改为静态库.lib 在debug里生成一个add.lib文件)
// add.h 和add.lib
// 在test.c里加上#pragma comment(lib, “add.lib”)导入静态库就可以使用



八、函数递归

一个过程或函数在其定义或说明过程中,有直接或间接调用自身的一种方法,多次重复计算,减少了程序的代码量

递归的主要思考方式:把大事化小

1、练习1 - 接受一个整型值(无符号),按照顺序打印它的每一位

#include <stdio.h>void print(unsigned int n)
{if (n > 9){print(n / 10); // 123}printf("%d ", n % 10);
}int main()
{unsigned int num = 0;scanf_s("%u", &num);print(num);return 0;
}

分析:

// 1. 1234>9 1234/10=123 调用print函数
// 2. 123>9 123/10=12 调用print函数
// 3. 12>9 12/10=1 调用print函数
// 4. 1<9 执行printf打印 n%10=1 打印 返回(函数从哪里调用就返回哪里)
// 5. 往下执行printf打印 此时n是12 n%12=2 打印2
// 6. 往下执行printf打印 此时n是123 n%123=3 打印3
// 7. 往下执行printf打印 此时n是1234 n%1234=4 打印4
// 8. 调用完 返回main中print 往下执行 return 0
// 1_2_3_4_


2、递归的两个必要条件

  1. 存在限制条件,当满足这个限制条件时,递归不再继续
  2. 每次递归调用之后,越来越接近这个限制条件

如果没有判断条件 -> 死递归:
每一次函数调用都要在内存中开辟空间
为main print函数各自开辟的空间 - 函数栈帧


3、练习2 - 编写函数不允许创建临时变量,求字符串的长度

变量求:

#include <stdio.h>int main()
{char arr[] = "abcdef";int len = strlen(arr);printf("%d\n", len); // 6return 0;
}

用函数,还是有临时变量count

#include <stdio.h>my_strlen(char* s)
{int count = 0;while (*s != '\0'){count++;s++;}return count;
}int main()
{char arr[] = "abcdef";// 数组名arr是数组首元素的地址 数组每个元素都是char类型 数组首元素也是char类型 数组首元素的地址是char*类型 - char*int len = my_strlen(arr); // 数组名传过去printf("%d\n", len);return 0;
}

函数递归解决

#include <stdio.h>my_strlen(char* s)
{if (*s != '\0'){return 1 + my_strlen(s + 1); // 函数递归}else{return 0;}
}int main()
{char arr[] = "abcdef";int len = my_strlen(arr);printf("%d\n", len);return 0;
}

分析:

// 'a' != '\0' 进入if strlen递归 s+1 bcdef\0
// 'b' != '\0' 进入if strlen递归 s+1 cdef\0
// 'c' != '\0' 进入if strlen递归 s+1 def\0
// 'd' != '\0' 进入if strlen递归 s+1 ef\0
// 'e' != '\0' 进入if strlen递归 s+1 f\0
// 'f' != '\0' 进入if strlen递归 s+1 \0
// '\0' = '\0' 执行else return 0 返回
// return 1 + 0 = 1 返回1
// 1+1=2 返回2
// 1+2=3 返回3
...
// 1+5=6 返回6
// 返回main my_strlen 往下执行
// 往下执行 printf打印6
6


指针不同类型

// 字符指针+1 - 向后跳1个字节
// char *p;
// p+1 -> 向后跳1个字节
//
// 整形指针+1 - 向后跳4个字节
// int *p;
// p+1 -> 向后跳4个字节
//
// 指针加一都是指向下一个元素地址,指针类型不同,跳过的字节也不同


4、递归与迭代

4.1、练习3 - 求n的阶乘(不考虑溢出)

用循环

#include <stdio.h>int Fac(int n)
{int i = 0;int ret =1;for (i = 1; i <= n; i++){ret *= i;}return ret;
}int main()
{int n = 0;scanf_s("%d", &n);int ret = Fac(n);printf("%d\n", ret);return 0;
}

递归求

// 求n的阶乘递归公式:
// n<=1时 Fac(n) = 1
// n>1时 Fac(n) = n*fac(n-1)

#include <stdio.h>int Fac(int n)
{if (n <= 1){return 1;}else{return n * Fac(n - 1);}
}int main()
{int n = 0;scanf_s("%d", &n);int ret = Fac(n);printf("%d\n", ret);return 0;
}
分析:

// 例求3的阶乘 调用Fac函数
// 3>1 else 调用Fac(2)
// 2>1 else 调用Fac(1)
// 1<=1 if return 0 返回1
// 2*1=2 返回2
// 3*2=6 返回6


4.2、练习4 - 求第n个斐波那契数

什么是斐波那契数:
// 1 1 2 3 5 8 13 21 34 55 …
// 前2个数字之和等于第3个数字

// 求第n个斐波那契数递归公式:
// Fib(n)
// 当n<=2时 Fib(n) = 1
// 当n>2时 Fib(n) = Fib(n-1) + Fib(n-2)


用递归求

#include <stdio.h>int count = 0;int Fib(int n)
{// 第三个斐波那契数被重复计算多少次if (n == 3){count++;}if (n <= 2){return 1;}else{return Fib(n - 1) + Fib(n - 2);}
}int main()
{int n = 0;scanf_s("%d", &n);int ret = Fib(n);printf("%d\n", ret);printf("count = %d\n", count);return 0;
}

迭代(循环)

这个问题用函数递归可以使用,但是会很慢。
如果求第50个斐波那契数,需要很长时间才能算出

因为函数递归就是调用自身,多次重复计算,
计算50,就需要49和48;而49需要48和47;48需要47和46…

那么会重复多少次:
定义全局变量count,看看第三个斐波那契数被重复计算多少次
假设求第50个斐波那契数,结果count = 39088169,重复了这么多次,
所以我们要使用更加有效率的方法计算


分析:

// a = 1
// b = 1
// c = a + b
// 求完3
// 把b放进a 把c放进a

#include <stdio.h>int Fib(int n)
{int a = 1;int b = 1;int c = 1;while (n > 2){// 当n=3时 开始计算c = a + b;a = b;b = c;n--;}return c;
}int main()
{int n = 0;scanf_s("%d", &n);int ret = Fib(n);printf("%d\n", ret);return 0;
}

5、什么时候用递归

  1. 当解决一个问题递归和非递归都可以使用,且没有名下那问题,那就可以使用递归
  2. 当解决一个问题写起来很简单,非递归比较复杂,且递归没有明显问题,那就用递归
  3. 如果说用递归解决问题,写起来简单,但是有明显问题,那就不能使用递归,得写出非递归方式来解决

函数递归几个经典题目:
1.汉诺塔问题
2.青蛙跳台问题


汉诺塔

#include <stdio.h>```c
void Move(char pos1, char pos2)
{printf(" %c - %c ", pos1, pos2);
}// N:代表盘子的个数
// pos1:起始位置
// pos2:中转位置
// pos3:目的位置
void Hanoi(int n, char pos1, char pos2, char pos3)
{if (n == 1){Move(pos1, pos3);}else{Hanoi(n - 1, pos1, pos3, pos2);Move(pos1, pos3);Hanoi(n - 1, pos2, pos1, pos3);}
}int main()
{Hanoi(4, 'A', 'B', 'C');return 0;
}


九、分支与循环getchar补充

1、getchar

getchar - 函数 - 从键盘读取字符的(单个字符)

  • getchar 是读取字符,为甚么返回类型是int?
  1. getchar 既然返回的是字符 其实返回的是找私服的ASCII码值 因为ASCII是整数 所以返回int
  2. getchar 在读取结束或失败的时候 会返回EOF
    EOF - end of file -> -1
    -1是整数 而ASCII码范围没有整数

结束代码 -> Ctrl+Z 回车

#include <stdio.h>int main()
{int ch = 0;while ((ch = getchar()) != EOF){putchar(ch);}return 0;
}

2、getchar读取密码

2.1、缓冲区

请确认密码(Y/N):>确认失败

// err
#include <stdio.h>int main()
{char password[20] = { 0 };printf("请输入密码:>");scanf_s("%s", password, 20);printf("请确认密码(Y/N):>");int ch = getchar();if (ch == 'Y'){printf("确认成功\n");}else{printf("确认失败\n");}return 0;
}

输入函数scanf和getchar 首先在缓冲区里看 如果有 就不用键盘输入
缓冲区是空的 键盘输入字符到缓冲区 此时缓冲区有abcdef\n
scanf读取 abcdef
getchar 读取\n


2.2、getchar清理\n

把缓冲区的\n清理掉

#include <stdio.h>int main()
{char password[20] = { 0 };printf("请输入密码:>");scanf_s("%s", password, 20);// 把缓冲区的\n清理掉getchar();printf("请确认密码(Y/N):>");int ch = getchar();if (ch == 'Y'){printf("确认成功\n");}else{printf("确认失败\n");}return 0;
}

一个getchar 只能清除一个\n
如果输入abc def 还是会出现错误“请确认密码(Y/N):>确认失败”
因为scanf只读取到abc 遇到空格就会停止


2.3、清除缓冲区

#include <stdio.h>int main()
{char password[20] = { 0 };printf("请输入密码:>");scanf_s("%s", password, 20);// 把缓冲中的内容int tmp = 0;while (tmp = getchar() != '\n'){;}printf("请确认密码(Y/N):>");int ch = getchar();if (ch == 'Y'){printf("确认成功\n");}else{printf("确认失败\n");}return 0;
}

如果密码有空格,可以使用gets - 直接读一行


3、ch = getchar()) != EOF

// 只打印数字

#include <stdio.h>int main()
{int ch = 0;while ((ch = getchar()) != EOF){if (ch < '0' || ch>'9')continue;putchar(ch);}return 0;
}

十、练习

1、能把函数处理结果的二个数据返回给主调函数

1.1、return 2个值(err)

一个函数只能返回一个结果 return a,b 结果是20 -> 逗号表达式

int test()
{int a = 10;int b = 20;return a, b; // err
}int main()
{int ret = test();printf("%d\n", ret);return 0;
}

1.2、形参用数组

void test(int arr[])
{int a = 10;int b = 20;arr[0] = a;arr[1] = b;
}int main()
{int arr[2] = { 0 };test(arr);printf("%d %d\n", arr[0], arr[1]);return 0;
}

1.3、形参用2个指针

void test(int* px, int* py)
{int a = 10;int b = 20;*px = a;*py = b;
}int main()
{int x = 0;int y = 0;test(&x, &y);printf("%d %d\n", x, y);return 0;
}

1.4、用2个全局变量

int x = 0;
int y = 0;void test()
{int a = 10;int b = 20;x = a;y = b;
}int main()
{test();printf("%d %d\n", x, y);return 0;
}

高内聚低耦合:自己把自己的事情做好,尽量不和别人产生关联


2、复合语句定义的变量在本函数范围内有效

在一个函数内复合语句中定义的变量在本函数范围内有效(复合语句指函数中的成对括号构成的代码)

void test()
{{int a = 10;}printf("a=%d\n", a); // err
}int main()
{return 0;
}

3、实现一个函数,打印乘法口诀表,口诀表的行数和列数自己指定

#include <stdio.h>void print_table(int n)
{int i = 0;for (i = 1; i <= n; i++){int j = 0;for (j = 1; j <= i; j++){printf("%d*%d=%-2d ", i, j, i * j);}printf("\n");}
}int main()
{int n = 0;scanf_s("%d", &n);print_table(n);return 0;
}

4、字符串逆序

要求:
1.递归实现
2.不能使用C函数库中的字符串操作函数

4.1、用函数循环

#include <stdio.h>
#include <string.h>void  reverse_string(char* str)
{// 用指针// char* left = str;// char* right = str + len - 1;// 用下标int len = strlen(str);int left = 0; //'a'int right = len - 1; //'f'while (left < right){char tmp = str[left];str[left] = str[right];str[right] = tmp;left++;right--;}
}int main()
{char arr[20] = "abcdef";//数组名是首元素地址//首元素就是char类型//char*reverse_string(arr);printf("%s\n", arr); // fedcbareturn 0;
}

4.2、递归版本

#include <stdio.h>int my_strlen(char* str)
{// 不能使用库函数 用my_strlen函数计数器求字符串int count = 0;while (*str != '\0'){count++;str++;}return count;
}void  reverse_string(char* str) // char str[]
{int len = my_strlen(str); // 求字符串长度char tmp = str[0]; // *str  把a 放进tmpstr[0] = str[len - 1]; // 把f 放进astr[len - 1] = '\0'; // 将\0 放进fif (my_strlen(str + 1) >= 2) //str+1 指向b 从第二个元素开始reverse_string(str + 1);str[len - 1] = tmp; // 出递归 把tmp 放进\0
}int main()
{char arr[20] = "abcdef";reverse_string(arr);printf("%s\n", arr);return 0;
}

分析:



5、计算一个数的每位之和

(递归实现 非负整数)

#include <stdio.h>int DigitSum(unsigned int n)
{if (n > 9){return DigitSum(n / 10) + n % 10;}else{return n;}
}int main()
{unsigned int num = 1729;int ret = DigitSum(num);printf("%d\n", ret);return 0;
}

6、递归实现n的k次方

// Pow(n, k)
// 当k>0 时 -> n*Pow(n, k-1)
// 当k=0时 -> 1
// 当k<0时 -> 1.0/n^-k -> 1.0/Pow(n, -k)

#include <stdio.h>double Pow(int n, int k)
{if (k > 0)return n * Pow(n, k - 1);else if (k == 0)return 1.0;elsereturn 1.0 / Pow(n, -k);
}int main()
{int n = 2;int k = -3;double ret = Pow(n, k);printf("%lf\n", ret);return 0;
}

【C语言函数】 - 库函数、自定义函数、函数参数、函数调用、嵌套调用链式访问、递归与迭代、缓冲区相关推荐

  1. C语言 函数 (库函数 · 自定义函数 · 函数参数 · 函数调用 · 嵌套调用链式访问 · 递归)

    文章目录: 一.函数是什么? 二.库函数 2.1 为什么要有库函数? 2.2 如何学习库函数? 2.3 我们就以 strcpy( ) 函数,来参照文档自学一下: 2.4 总结: 三.自定义函数 3.1 ...

  2. 【C语言】函数 ---- 函数的嵌套调用和链式访问、函数的声明和定义、变量的声明和定义、函数递归与迭代、递归时的栈溢出问题

    函数 一.函数的嵌套调用和链式访问 1.嵌套调用 2.链式访问 2.1strlen()函数 2.2printf()函数 二.函数的声明和定义 1.函数声明和定义的介绍 2.函数声明和定义的使用 三.变 ...

  3. 用c语言线性表的链式表示实现,数据结构-使用C语言 朱战立第2章线性表的链式表示.ppt...

    数据结构-使用C语言 朱战立第2章线性表的链式表示 * 循环链表(circular linked list) 循环链表是表中最后一个结点的指针指向头结点,使链表构成环状 特点:从表中任一结点出发均可找 ...

  4. 【C 语言】C 语言 函数 详解 ( 函数本质 | 顺序点 | 可变参数 | 函数调用 | 函数活动记录 | 函数设计 ) [ C语言核心概念 ]

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  5. [转]EL函数、自定义EL函数、自定义标签

    EL函数 1.EL函数的作用:操作字符串 2.在JSP页面中要引入EL函数库 <%@ taglib prefix="fn" uri="http://java.sun ...

  6. 自定义条件查询_数据查询不止有vlookup函数,自定义zlookup函数查询操作更高效...

    Excel数据查询,相信大家首先会想到vlookup函数.毋庸置疑vlookup函数在Excel数据查询中作用是非常的强大.但是它也有一些不能实现的数据查询. 如上图所示,我们需要根据人员的出现次数, ...

  7. 8.Hive基础—函数—系统内置函数、常用内置函数、自定义函数、自定义UDF函数、自定义UDTF函数

    本文目录如下: 第8章 函数 8.1 系统内置函数 8.2 常用内置函数 8.2.1 空字段赋值 8.2.2 CASE WHEN THEN ELSE END 8.2.3 行转列 8.2.4 列转行 8 ...

  8. Hive _函数(系统内置函数、自定义函数、自定义UDF函数)

    函数 系统内置函数 1.查看系统自带的函数 show functuions; 2.显示自带的函数的用法 desc function month; 3.详细显示自带的函数的用法 desc functio ...

  9. tp5模板使用php函数,tp5 自定义公共函数,前台模板调用

    最近用tp5做一个cms,在添加模型的时候,选择类型,这类型太多了,如果一个个的去判断显示,能累死人了,干脆写个公共方法, 首先写公共方法用到Common.php,目录project/applicat ...

最新文章

  1. 怎么做网络推广浅析网站如何设置导航栏可以使网站优化更好?
  2. 利用WCF的callback机制开发一个简单的多人游戏模型
  3. Example of how to use both JDK 7 and JDK 8 in one build.--reference
  4. LSTM:《Long Short-Term Memory》的翻译并解读
  5. vue引入包mysql_vue中import引入文件和使用的方式总结
  6. C++中变量使用前一定要初始化
  7. DOCTYPE html PUBLIC 指定了 HTML 文档遵循的文档类型定义
  8. Jerry Wang一篇介绍ABAP调试心得的博客上了SAP社区的首页
  9. 作为相亲大户,程序猿为何普遍单身?
  10. java api es_中间件系列之ElasticSearch-3-Java API操作ES
  11. Pycharm: 设置默认字符编码为 utf-8模版
  12. matlab潮流计算仿真,MATLAB潮流计算仿真
  13. LCD驱动芯片/LCD段式液晶显示驱动芯片-VK0192M/VK0256/B/C技术资料简介
  14. Java语言实现冒泡排序
  15. 经常使用的几种OCR文档扫描工具|无水印|避免智商税
  16. 苹果cookie是打开还是关闭_关闭手机广告的几个操作
  17. bugly怎么读_腾讯Bugly巨坑:使用不当造成UI界面卡死
  18. 【程序员如何买基金 三】场内场外交易的区别
  19. html清除iframe的缓存,如何清除iFrame的缓存?
  20. ElasticSearch7 集群安装和配置

热门文章

  1. concatenate python_python中numpy.concatenate()函数的使用
  2. 如何套用模板绘制生产管理流程图
  3. mean shift 图像分割(一、二、三)
  4. 多线程糗事百科案例(python2)
  5. 【小超_Android】GitHub源码项目整理,希望对大家有帮助
  6. 面向对象设计的六大原则简介
  7. JSP状态管理 及 Cookie实例
  8. BZOJ 3529 数表(莫比乌斯+树状数组)
  9. php中这个向右的箭头怎么理解呢?$db-query
  10. .net对象和比特流的转换(一)