递归的本质:将大任务拆成处理逻辑完全相同的子任务,不断缩小处理范围,直至结束。 即递归函数调用自身,完成更小的子任务。注意,递归也需要有明确的结束条件,即处理完不能再次拆解的子任务后停止。
能使用递归的程序一般都能通过使用循环来解决,但是在合适的情况下递归有更好的可读性,但是也可能导致性能开销的变大(递归需要进行大量的函数调用),所以并不存在谁能替代谁,而是在合适的时机选择合适的方式来处理,这就需要丰富的编程经验了。
递归的典型运用场景:
汉诺塔、二分查找等等。
书上有用斐波拉切数列举例,但个人觉得斐波拉切数列用递归实现简单是简单,可是重复进行的工作太多了,并不是一个好的算法
F(n) = F(n-1) + F(n-2); F(1)=F(0) = 1;
非常明显的可以用递归来处理。(但是请想一下,里面是否存在大量的多次重复计算F(i)?)
C语言的I/O
I/O是计算器非常重要的组成部分,而和大多数现代编程语言一样,C语言自身并不支持输入输出操作,这部分的处理都是有标准库函数提供的。
I/O流:
概念上,所有基于字符的输入/输出操作都是“流”方式的,输入一个字符,添加到流尾部,而从流头部获取数据。(FIFO)
C语言的标准输入输出流分别是stdin(输入)、stdout(输出)
putchar和getchar:
它们每次只处理1个字符(字符对应的ASCII码值),putchar输出和getchar输入.
格式化I/O
支持各种数据类型的printf和scanf
printf的功能是将格式化的文本输出至输出流中,通过该函数,我们可以将程序中产生的各种数字嵌入ASCII文本中,混合打印输出。因此,printf必须具备将各种类型转换为ASCII码的能力。
函数原型
int printf ( const char * format, ... );
int scanf( const char * format, ... ); //后续参数是指针类型
format是格式串包含要输出的文本和“转换规范”,后面是不定长的参数列表(有几个需要格式化的值,这里就有几个参数)
format形式大致为"output %d,%c,%s"(以符号%为前缀,后面跟着的字符代表被转换的数据类型,这种就是"转换规范”),具体不同的字符代表的类型这里不详细说了。
scanf采用与printf相同的格式串及转换规范的定义。不同的是scanf后续参数必须是指针(因为要为变量赋值,所以需要将变量所处内存地址告诉scanf)
文件I/O
fprintf和fcanf是printf和scanf的通用版本,其关联的文件要由调用者显示给出(printf和scanf操作的是两个特殊文件stdin和stdout)
int fprintf(FILE *stream, const char *format, ...)
int fscanf(FILE *stream, const char *format,...); //变成参数为指针类型
和printf、scanf不同的是,需要通过指定FILE来显示的给出将要操作的文件。