petard  

第 11 章 函数

11.7 递归函数

​ ——相当于俄罗斯套娃;一个程序未执行结束会挂起,相当于堆栈

一个函数在函数体内又调用了本身,我们称为递归调用,这样的函数就是递归函数。
递归函数成功执行需满足以下两个条件:
(1)必须有一个明显的结束条件。
(2)必须有一个趋近于结束条件的趋势。

注: 用于循环不好实现的,条件比较分散的情况

eg:分析阶乘的过程

#include <stdio.h>
/**********************************************************************
 * 递归案例
 * 1. 计算某个数字阶乘
**********************************************************************/

// 定义函数 计算某个数字的阶乘
int factorial(int n)
{
    if (n <= 1)
    {
        return 1;
    }
    return n * factorial(n-1);
}


int main()
{
    
    printf("10的阶乘:%d \n", factorial(10));
    printf("5的阶乘:%d \n", factorial(5));
    printf("3的阶乘:%d \n", factorial(3));
    /* 
        factorial(3) 开始调用  条件不成立 return 3 * factorial(2)
            factorial(2) 开始调用 条件不成立 return 2 * factorial(1)
                factorial(1) 开始调用 条件成立
                factorial(1) 结束调用 return 1
            factorial(2) 结束调用 return 2 * 1
        factorial(3) 结束调用 return 3 * 2
     */
    
    return 0;
}

11.8 常用系统函数

① 字符串函数

标准库头文件 <string.h>

strlen(str)	返回str的长度,类型是 size_t
strcpy(str1,str2)	将 str2 中的字符串复制到str1中	——(给字符数组重新赋值,得用strcpy(给字符一个一个替换))

strcat(str1,str2)	将 str2 中的字符串追加到 str1 后面

注:相比于 sizeof,strlen() 不会把字符串结束标记计算在内,也就是说strlen() 只计算结束标识符之前的内容

标准库头文件 <stdio.h>

sprintf(),用于将格式化数据写入字符串。	——这个比较常用
相比于 printf(),多了一个参数,第一个参数是要【写入的字符串】,后面参数与 printf() 一致。
简单地讲,sprintf() 是【将内容写入字符串】而不是输出。

sscanf(),用于从一个字符串中按照指定的格式提取数据。
相比于 scanf(),多了一个参数,第一个参数是要【提取数据的字符串】,后面参数与 scanf() 一致。
简单地讲,sscanf() 是【从字符串中提取数据】而不是从用户输入提取数据。

② 日期时间函数

标准库头文件 <time.h>

time(&变量)	【获取当前日期】赋值到变量中,该变量需是 time_t 类型
ctime(&时间值)	【将时间戳转为字符串】并返回,时间值需是 time_t 类型
difftime(时间值1,时间值2)	【返回两个时间值的差】,返回值是 double 类型,时间值需是 time_t 类型

注:time() 函数获取的是当前日期时间的时间戳(unix时间戳)(从1970年1月1日0时0分0秒[UNIX纪年]到指定日期时间的秒数

③ 数学计算函数

标准库头文件 <stdio.h>

sqrt(x)		计算平方根
cbrt(x)		计算立方根
pow(x,y)	计算x的y次方
fabs(x)		计算x的绝对值
ceil(x)		向上取整	——让数字变大
floor(x)	向下取整
round(x)	四舍五入取整	——不区分正负,只看四五数字
trunc(c)	截断小数部分	——(正数变小,负数变大)

注:以上函数返回的都是 double 类型

第 12 章 指针 pointer

12.1 指针基础

1. 如果一个变量专门用来存放内存地址,则它称为指针变量,通常简称为指针。
	指针变量的数据类型为:数据类型 *
	声明:数据类型 *指针变量名
	
2. 内存地址
   在32位系统中,内存地址通常是32位二进制数字,即4个字节
   在64位系统中,内存地址通常是64位二进制数字,即8个字节
   
3. 取地址运算符 &
   通过 & 可以将某个变量的地址获取
   如果需要使用 printf 输出一个内存地址,可以使用占位符 %p
   
4. 取值运算符(解引用运算符) *
   可以【获取指针所指向的数据】

12.2 指针运算

① 指针加减整数

指针+n: 地址向后移动n个数据类型大小	——(增加)
		给指针加1,相当于加一个数据类型的字节(一个数组类型的字节,俗称一个元素)
				
指针-n: 地址向前移动n个数据类型大小

② 指针自增自减

​ —— 可以遍历数组,不过循环结束后,指针越界

自增:指针向后移动1个数据类型大小
自减:指针先前移动1个数据类型大小

③ 同类型指针相减

得:相差的元素个数(相差的字节数/数据类型大小)【单位都是字节】
后面地址减前面地址得到正数,前面地址减后面地址得到负数

④ 指针比较大小

后面的地址比前面的地址大(地址编号从前向后的)

​ 不同类型的指针,也可以比大小

12.3 指针和数组

① 数组名

可以把数组名当做是【存储了首元素地址的常量】。

指向首元素指针 和 数组名 的相同点 :

  • 都是存储着首元素地址的常量

  • 都可以解引用

  • 都可以加减整数

  • 指向首元素指针可以像数组名一样使用

指向首元素指针 和 数组名 的不同点 :

  • 数组名不能自增自减
  • 数组名不能重新赋值
  • sizeof 数组名获取的是整个数组的存储大小

② 指针数组


③ 数组指针


④ 字符指针


总结:

数据类型 sizeof 计算结果 +1 的值 * 取值(解引用) 能否重新赋值(可变性)
数组名 元素类型[] 整个数组的存储长度 下一个元素地址 首元素的值
指向首元素指针 元素类型* 地址的存储长度 下一个元素地址 首元素的值
数组指针
posted on 2024-04-09 19:49  岌岌无名  阅读(9)  评论(0编辑  收藏  举报