10讲学会C语言之第八讲:递归与宏定义


前言

大家好,我是卷卷。首先恭喜大家坚持到现在,你们已经翻越了函数,数组,指针这“三座大山”,后面的内容就比较轻松了。本节课的主题是递归与宏定义,主要有以下几个部分:递归的概念,汉诺塔问题,长度单位转换,作业。(讨论q群号744931080,教程资源在群内)


一、递归的概念

把n的阶乘以递归方式进行定义:在这里插入图片描述
求n!可以在(n-1)!的基础上再乘上n。如果把求n!写成函数fact(n),则fact(n)的实现依赖于fact(n-1)。这是fact函数的定义:在这里插入图片描述
可以看到fact(n)调用了fact(n-1)。这种函数自己调用自己的方式称作递归调用。特别注意:必须要有递归出口,否则函数永远在调用,永远没有结果,计算机最终也会宕机。通过fact函数,我们能更进一步地了解递归的含义,即递归包括递推与回归两个过程。求n!,必须知道(n-1)!,求(n-1)!,必须知道(n-2)!,以此类推。一直递推到n=1为止,此时出现函数出口,所以立即向上层返回1,开始回归。通过一层层地往上传递,最终就得到了(n-1)!,返回n*(n-1)!即可。注意:一般递归出口放在函数体头部。

二、汉诺塔问题

例1:汉诺塔(Hanoi)问题源于一个古老的印度传说,后改成了一个游戏,游戏规则如下:有三根柱子A,B,C,A上放了n个大小不等的盘子,小盘在大盘上面。现要将A的盘子移到B上,必须满足如下条件:
(1)一次只能移动一个盘子
(2)小盘不能放在大盘下面
分析:首先如果只有1个盘子,直接移动即可。假设n大于1,则先将n-1个盘子从A移到C,再将第n个盘子从A移到B,最后将C上的n-1个盘子移到B。那么n-1个盘子如何移动呢?程序是给出解决问题的规律或方法,而不是一次次的具体展开。因此,不必关心具体n-1个盘子如何搬,只需将n个盘子简化为n-1个盘子的问题,n-1个盘子简化为n-2个盘子的问题……上述思想可设计出如下算法(伪代码):

hanoi(n个盘,A移到B){
	if(n==1)
		直接将A移到B;
	else{
		hanoi(n-1个盘,A移到C);
		直接将n号盘从A移到B;
		hanoi(n-1个盘,C移到B)
	} 
}

显然,递归出口是if的情况,递归式是else的情况。在C程序中,可用打印函数输出A移到B的信息来模拟盘子的移动。本题的重点是递归调用。代码:

#include<stdio.h>
void hanoi(int n,char src,char dest,char mid);
int main(){
	int n;
	printf("请输入盘子数:");
	scanf("%d",&n);
	printf("%c->%c的步骤如下:\n",'a','b');
	hanoi(n,'a','b','c');
	return 0;
}
void hanoi(int n,char src,char dest,char mid){
	//src->dest,中间经过mid 
	if(n==1){
		printf("%c->%c\n",src,dest);
		return;
	}
	hanoi(n-1,src,mid,dest);//src->mid,中间经过dest
	printf("%c->%c\n",src,dest);
	hanoi(n-1,mid,dest,src);//mid->dest,中间经过src
}

hanoi函数中,src是源,dest是目的地,mid是中间过程。意思是从src传送到dest,中间要经过mid。如果只有一个盘子,直接输出src到dest即可。如果大于一个盘子,需要将A的n-1个盘子,先从src移到mid,然后将第n号盘子从src直接移到dest,最后将剩余的n-1个盘子从mid移到dest。主函数就不用多说了。我们来验证一下:在这里插入图片描述
这就是本题的运行结果了。汉诺塔的结果有一个规律,n 个盘子有2^n - 1种步骤,相信大家已经对递归有所了解了。递归的好处是比较简洁直观,但是由于递归调用的过程需要暂时保存,以便于返回,所以会消耗比较多的内存空间。迭代无需消耗额外内存,但是没有递归直观。

例2:编写递归函数reverse(int n)实现将整数n逆序输出。分析:我们知道迭代版的算法是每次循环输出n%10,即n的最低位,然后通过n/=10砍掉最低位。根据题目,要先输出最低位,所以首先要输出最低位,即n%10。由于递归是最底层的先处理,所以当位数大于1时,更高位必须通过层层调用来输出,也就是以递归方式输出。即reverse(n/10);砍到只剩1位时可以直接输出,所以只剩1位的情况就是递归出口。代码:

void reverse(int n){
	if(n<10){
		printf("%d\n",n);
		return;
	}//递归出口 
	printf("%d",n%10);//最低位 
	reverse(n/10);//更高位 
}

如果是个位数,直接输出即可,这段代码就作为递归出口。如果不是个位数,先输出最低位,然后再用递归调用的形式输出其余更高位。我在前面讲过,递归分为两个过程,递推与回归。递推的过程由于需要保留每一步的操作,从而需要消耗一定的内存空间,准确地来说是栈空间。栈是一种后进先出的数据结构,后进来的数据最先被弹出。所以这就和我们平时使用计算机一样,如果按ctrl+z,会回退到上一步,其实是弹出了栈顶元素。这就是递归调用的基本特性。

三、长度单位转换

例3:欧美国家长度使用英制单位,如英里、英尺、英寸等,其中1英里=1609米,1英尺=30.48厘米,1英寸=2.54厘米。请编写程序将输入的英里转换成米,英尺和英寸转换成厘米。分析:算法很简单,为了提高编程效率,使用宏定义来表示各长度。定义Mile_to_m位1609,Foot_to_cm为30.48,Inch_to_cm为2.54。本题的重点是宏定义,代码:

#include<stdio.h>
#define Mile_to_m 1609
#define Foot_to_cm 30.48
#define Inch_to_cm 2.54
int main(){
	double foot,inch,mile;
	printf("输入英里,英尺和英寸:");
	scanf("%lf %lf %lf",&mile,&foot,&inch);
	printf("%.2f英里=%.2f米\n",mile,mile*Mile_to_m);
	printf("%.2f英尺=%.2f厘米\n",foot,foot*Foot_to_cm);
	printf("%.2f英寸=%.2f厘米\n",inch,inch*Inch_to_cm);
	return 0;
}

#define就是宏定义,作用是给某段文本起别名。比如第一个宏定义,意思是给1609起了一个别名:Mile_to_m,即用这串字符去替代1609,这样之后都可以使用这个别名了。其它两个宏定义以此类推。你或许会想到全局变量,但是全局变量与宏定义有本质的区别。全局变量首先是一个变量,它有数据类型要求,有指针等等,而宏定义只是单纯的文本替代,这句话是宏定义的核心,它只是单纯的文本替代。其实只要记住宏定义是单纯的文本替代,全局变量是变量,这样就不会搞混了。宏定义还可以定义函数,比如这样:

#define max(a,b) a>b?a:b

意思是传入参数a和b,如果a大于b就返回a,否则就返回b。我们可以来试一下:在这里插入图片描述
这就是宏定义的概念与使用了,我们继续实验:在这里插入图片描述
这就是本题的讲解了。

四、作业

作业是3道例题加5道练习题,总共8道题。练习1:在这里插入图片描述
阶乘我想大家已经很熟悉了,因为之前已经做过很多有关阶乘的题,这题就不讲了。练习2:在这里插入图片描述
本题也很简单,按照递归求阶乘的思想即可解决。即要知道n次幂,必须先知道n-1次幂,要知道n-1次幂,必先知道n-2次幂,以此类推。练习3:在这里插入图片描述
这一题就更简单了,因为题目描述就是核心算法,但是要注意注意f(0)=0,f(1)=1,这两个都是递归出口。练习4:在这里插入图片描述
这里需要重点讲一下十进制转二进制的算法,要用除二取余法。比如说十进制数6转二进制,转换过程如下:
6/2=3…0
3/2=1…1
1/2=0…1
上述过程就是每次除以2,得到整数商和余数,再把商除以2,以此类推,直到商为0。最后余数倒上来组合就是二进制,比如这里的110。
这就是除2取余法的基本介绍了,建议本题递归和迭代方式都实现一下,以更好地提升编程能力。最后一道题:在这里插入图片描述
这一题和之前的例题也有一点类似,只要参照之前的例题即可。好了,这就是本讲的全部内容了,我们下讲见!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
目 录 第1章 C语言 8 1.1 什么是局部程序块(local block)? 8 1.2 可以把变量保存在局部程序块中吗? 9 1.3 什么时候用一条switch语句比用多条if语句更好? 9 1.4 switch语句必须包含default分支吗? 10 1.5 switch语句的最后一个分支可以不要break语句吗? 11 1.6 除了在for语句中之外,在哪些情况下还要使用逗号运算符? 11 1.7 怎样才能知道循环是否提前结束了? 13 1.8 goto,longjmp()和setjmp()之间有什么区别? 13 1.9 什么是左值(lvaule)? 15 1.10 数组(array)可以是左值吗? 15 1.11 什么是右值(rvaule)? 16 1.12 运算符的优先级总能保证是“自左至右”或“自右至左”的顺序吗? 17 1.13 ++var和var++有什么区别? 17 1.14 取模运算符(modulus operator)“%”的作用是什么? 17 第2章 变量和数据存储 18 2.1. 变量存储在内存(memory)中的什么地方? 18 2.2. 变量必须初始化吗? 19 2.3. 什么是页抖动(pagethrashing)? 19 2.4. 什么是const指针? 20 2.5. 什么时候应该使用register修饰符?它真的有用吗? 21 2.6. 什么时候应该使用volatile修饰符? 21 2.7. 一个变量可以同时被说明为const和volatile吗? 22 2.8. 什么时候应该使用const修饰符? 23 2.9. 浮点数比较(floating-point comparisons)的可靠性如何? 23 2.10. 怎样判断一个数字型变量可以容纳的最大值? 24 2.11. 对不同类型的变量进行算术运算会有问题吗? 25 2.12. 什么是运算符升级(operatorpromotion)? 25 2.13. 什么时候应该使用类型强制转换(typecast)? 26 2.14. 什么时候不应该使用类型强制转换(typecast)? 27 2.15. 可以在头文件中说明或定义变量吗? 27 2.16. 说明一个变量和定义一个变量有什么区别? 27 2.17. 可以在头文件中说明static变量吗? 28 2.18. 用const说明常量有什么好处? 28 第3章 排序与查找 28 排序 28 查找 29 排序或查找性能? 30 3.1. 哪一种排序方法最方便? 32 3.2. 哪一种排序方法最快? 33 3.3. 对外存(磁盘或磁带)中而不是内存中的数据进行排序称为外部排序。 39 3.4. 1哪一种查找方法最方便? 44 3.5. 1哪一种查找方法最快? 46 3.6. 1什么是哈希查找? 51 3.7. 1怎样对链表进行排序? 53 3.8. 1怎样查找链表中的数据? 53 第4章 数据文件 59 4.1. 当errno为一个非零值时,是否有错误发生? 59 4.2. 什么是流(stream)? 59 4.3. 怎样重定向一个标准流? 60 4.4. 怎样恢复一个重定向了的标准流? 60 4.5. stdout能被强制打印到非屏幕设备上吗? 61 4.6. 文本模式(textmode)和二进制模式(binarymode)有什么区别? 61 4.7. 怎样判断是使用流函数还是使用低级函数? 62 4.8. 怎样列出某个目录下的文件? 62 4.9. 怎样列出一个文件的日期和时间? 63 4.10. 怎样对某个目录下的文件名进行排序? 66 4.11. 怎样判断一个文件的属性? 67 4.12. 怎样查看PATH环境变量? 69 4.13. 怎样打开一个同时能被其它程序修改的文件? 69 4.14. 怎样确保只有你的程序能存取一个文件? 71 4.15. 怎样防止其它程序修改你正在修改的那部分文件内容? 71 4.16. 怎样一次打开20个以上的文件? 72 4.17. 怎样避开"Abort,Retry,Fail”消息? 72 4.18. 怎样读写以逗号分界的本? 74 第5章 编译预处理 76 5.1. 什么是(macro)?怎样使用? 76 5.2. 预处理程序(preprocessor)有什么作用? 77 5.3. 怎样避免多次包含同一个头文件? 79 5.4. 可以用#include指令包含类型名不是".h"的文件吗? 80 5.5. 用#define指令说明常量有什么好处? 80 5.6. 用enum关键字说明常量有什么好处? 81 5.7. 与用#define指令说明常量相比,用enum关键字说明常量有什么好处? 81 5.8. 如何使部分程序在
“新概念C语言”突破了以往任何一种语言教材的旧的模式,将教学内容分为入门篇和提高篇两个篇章。在入门篇中只引进程序设计必要的语法现象,达到快速入门。激发兴趣的目的。在入门篇和提高篇之间插一个强化上机实验周,巩固学习内容。在提高篇中完成完整的语法、算法、程序设计思想等教学目的的学习任务。由于学生对语言已具有了初步的了解并掌握了最基本的语法和程序设计思想,能设计较简单的程序,所以在提高篇的学习中,不论对灵活语法的学习和掌握,还是对程序设计思想的掌握都更加容易,从而可以较容易达到教学目标。 第一部分 入门篇 1 第1章 C语言的产生及其工作流程 3 1.1 C语言的产生 3 1.2 程序和程序设计 3 1.2.1 C程序 3 1.2.2 程序设计 4 习题 4 第2章 C程序设计的初步知识 5 2.1 简单C程序的构成和格式 5 2.2 常量、变量和标识符 6 2.2.1 标识符 6 2.2.2 常量 7 2.2.3 用定义一个符号名的方法来代表一个常量 7 2.2.4 变量 8 2.3 整型数据 8 2.3.1 整型常量 8 2.3.2 整型变量 8 2.4 实型数据 9 2.4.1 实型常量 9 2.4.2 实型变量 9 2.5 字符型数据 10 2.5.1 字符常量 10 2.5.2 字符串常量 11 2.5.3 字符变量 11 2.6 算术表达式 11 2.6.1 基本的算术运算符 11 2.6.2 运算符的优先级、结合性和算术表达式 12 2.6.3 强制类型转换表达式 13 2.7 赋值表达式 13 2.7.1 赋值运算符和赋值表达式 13 2.7.2 赋值运算中的类型转换 14 习题 15 第3章 顺序结构程序 16 3.1 复合语句和空语句 16 3.1.1 复合语句 16 3.1.2 空语句 16 3.2 程序举例 16 习题 17 第4章 选择结构 19 4.1 关系运算和逻辑运算 19 4.1.1 C语言中的逻辑值 19 4.1.2 关系运算符和关系表达式 19 4.1.3 逻辑运算符和逻辑表达式 20 4.2 if语句和用if语句构成的选择结构 21 习题 22 第5章 循环结构 25 5.1 for语句和用for语句构成的循环结构 25 5.1.1 for语句构成的循环结构 25 5.1.2 for循环的执行过程 25 5.1.3 有关for语句的说明 25 5.2 循环结构的嵌套 27 习题 28 第6章 函数 30 6.1 函数的定义和返回值 30 6.1.1 函数定义的语法 30 6.1.2 函数的返回值 30 6.2 函数的调用 32 6.2.1 函数的调用方式 32 6.2.2 函数调用时的语法要求 32 6.3 函数的说明 33 6.3.1 函数说明的形式 33 6.3.2 函数说明的位置 34 6.4 调用函数和被调用函数之间的数据传递 34 6.5 库函数 36 6.6 数据输入输出及常用库函数 37 6.6.1 printf函数(格式输出函数) 37 6.6.2 scanf函数(格式输入函数) 39 6.6.3 调用putchar和getchar函数输出和输入字符 40 6.7 程序举例 41 习题 43 第7章 数组 45 7.1 一维数组的定义和一维数组元素的引用 45 7.1.1 一维数组的定义 45 7.1.2 一维数组元素的引用 46 7.1.3 一维数组的初始化 46 7.1.4 一维数组的定义和数组元素引用举例 47 7.2 函数之间对一维数组和数组元素的引用 47 7.2.1 数组元素做实参 47 7.2.2 数组名做实参 49 7.3 一维数组应用举例 50 7.4 字符数组 53 7.4.1 字符数组的定义 53 7.4.2 字符数组的初始化 54 7.4.3 字符数组的引用 54 7.4.4 字符串与字符串结束标志 55 7.4.5 字符数组的输入输出 56 7.4.6 字符串处理函数 58 7.4.7 字符数组应用举例 60 习题 61 第8章 文件 63 8.1 C语言文件的概念 63 8.2 打开文件 64 8.3 关闭文件 65 8.4 调用getc(fgetc)和putc(fputc)等常用函数进行输入和输出 65 8.5 判断文件结束函数feof 68 习题 69 第二部分 提高篇 71 第9章 算法 73 9.1 算法 73 9.2 结构化程序设计和模块化结构 74 9.2.1 结
C语言是编程语言中的一朵奇葩,虽已垂垂老矣,但却屹立不倒,诞生了数十年,仍然是最流行的编程语言之一。C语言看似简单,却不易吃透,想要运用好,更是需要积淀。本书是一本修炼C程序设计能力的进阶之作,它没有系统地去C语言的语法和编程方法,而是只对C语言中不容易被初学者理解的重点、难点和疑点进行了细致而深入的解读,揭露了C语言中那些鲜为普通开发者所知的秘密,旨在让读者真正掌握C语言,从而编写出更高质量的C程序代码。 全书一共11章:第1章重点阐述了C语言中不易被理解的多个核心概念,很多初学者在理解这些概念时都会存在误区;第2~8章对预处理、选择结构和循环结构的程序设计、数组、指针、数据结构、函数和文件等知识点的核心问题和注意事项进行了解;第9章介绍了调试和异常处理的方法及注意事项;第10章对C语言中的若干容易让开发者误解误用的陷阱知识点进行了剖析;第11章则对所有程序员必须掌握的几种算法进行了详细的解;附录经验性地总结了如何养成良好的编码习惯,这对所有开发者都尤为重要。 本书主要内容:  堆和栈、全局变量和局部变量、生存期和作用域、内部函数和外部函数、指针变量、指针数组和数组指针、指针函数和函数指针、传址和传值、递归和嵌套、结构体和共用体、枚举、位域等较难理解的核心概念的阐述和对比;  预处理中的疑难知识点,包括文件的包含方式、宏定义及其常见错误解析、条件编译指令和#pragma指令的使用等;  if、switch等选择结构语句的使用注意事项和易错点解析;  for、while、do while等循环结构语句的使用注意事项和易错点解析;  循环结构中break、continue、goto、return、exit的区别;  一维数组、二维数组、多维数组、字符数组、动态数组的定义和引用,以及操作数组时的各种常见错误解析;  不同类型的指针之间的区别,以及指针的一般用法和注意事项;  指针与地址、数组、字符串、函数之间的关系,以及指针与指针之间的关系;  枚举类型的使用及注意事项,结构体变量和共用体变量的初始化方法及引用;  传统链表的实现方法和注意事项,以及对传统链表实现方法的颠覆;  与函数参数、变参函数、函数调用、函数指针相关的一些难理解和容易被理解错的知识点解析;  文件和指针的使用原则、技巧和注意事项;  函数调用和异常处理的注意事项和最佳实践;  与strlen、sizeof、const、volatile、void、void*、#define、typedef、realloc、malloc、calloc等相关的一些陷阱知识点的解析;  时间复杂度、冒泡排序法、选择排序法、快速排序法、归并排序法、顺序排序法、二分查找等常用算法的详细解;  良好的编码习惯和编程风格。
1 C语言概述 2 1.1 C语言的发展过程 2 1.2 当代最优秀的程序设计语言 2 1.3 C语言版本 2 1.4 C语言的特点 3 1.5 面向对象的程序设计语言 3 1.6 C和C++ 3 1.7 简单的C程序介绍 4 1.8 输入和输出函数 5 1.9 C源程序的结构特点 6 1.10 书写程序时应遵循的规则 6 1.11 C语言的字符集 6 1.12 C语言词汇 7 1.13 Turbo C 2.0集成开发环境的使用 8 1.13.1 Turbo C 2.0简介和启动 8 1.13.2 Turbo C 2.0集成开发环境 8 1.13.3 File菜单 9 1.13.4 Edit菜单 10 1.13.5 Run菜单 11 1.13.6 Compile菜单 12 1.13.7 Project菜单 13 1.13.8 Options菜单 14 1.13.9 Debug菜单 18 1.13.10 Break/watch菜单 19 1.13.11 Turbo C 2.0的配置文件 20 2 程序的灵魂—算法 1 2.1 算法的概念 1 2.2 简单算法举例 1 2.3 算法的特性 4 2.4 怎样表示一个算法 4 2.4.1 用自然语言表示算法 4 2.4.2 用流程图表示算法 4 2.4.3 三种基本结构和改进的流程图 8 2.4.4 用N-S流程图表示算法 9 2.4.5 用伪代码表示算法 10 2.4.6 用计算机语言表示算法 11 2.5 结构化程序设计方法 11 2 3 数据类型、运算符与表达式 1 3.1 C语言的数据类型 1 3.2 常量与变量 3 3.2.1 常量和符号常量 3 3.2.2 变量 3 3.3 整型数据 4 3.3.1 整型常量的表示方法 4 3.3.2 整型变量 5 3.4 实型数据 7 3.4.1 实型常量的表示方法 7 3.4.2 实型变量 8 3.4.3 实型常数的类型 9 3.5 字符型数据 9 3.5.1 字符常量 9 3.5.2 转义字符 9 3.5.3 字符变量 10 3.5.4 字符数据在内存中的存储形式及使用方法 10 3.5.5 字符串常量 11 3.5.6 符号常量 12 3.6 变量赋初值 12 3.7 各类数值型数据之间的混合运算 13 3.8 算术运算符和算术表达式 14 3.8.1 C运算符简介 14 3.8.2 算术运算符和算术表达式 15 3.9 赋值运算符和赋值表达式 17 3.10 逗号运算符和逗号表达式 18 3.11 小结 19 3.11.1 C的数据类型 19 3.11.2 基本类型的分类及特点 19 3.11.3 常量后缀 19 3.11.4 常量类型 19 3.11.5 数据类型转换 19 3.11.6 运算符优先级和结合性 20 3.11.7 表达式 20 4 最简单的C程序设计—顺序程序设计 1 4.1 C语句概述 1 4.2 赋值语句 3 4.3 数据输入输出的概念及在C语言中的实现 4 4.4 字符数据的输入输出 4 4.4.1 putchar 函数(字符输出函数) 4 4.4.2 getchar函数(键盘输入函数) 5 4.5 格式输入与输出 5 4.5.1 printf函数(格式输出函数) 5 4.5.2 scanf函数(格式输入函数) 8 4.6 顺序结构程序设计举例 12 4 5 分支结构程序 1 5.1 关系运算符和表达式 1 5.1.1 关系运算符及其优先次序 1 5.1.2 关系表达式 1 5.2 逻辑运算符和表达式 2 5.2.1 逻辑运算符极其优先次序 2 5.2.2 逻辑运算的值 3 5.2.3 逻辑表达式 3 5.3 if语句 4 5.3.1 if语句的三种形式 4 5.3.2 if语句的嵌套 7 5.3.3 条件运算符和条件表达式 9 5.4 tch语句 10 5.5 程序举例 11 5 6 循环控制 1 6.1 概述 1 6.2 goto语句以及用goto语句构成循环 1 6.3 while语句 2 6.4 do-while语句 4 6.5 for语句 6 6.6 循环的嵌套 9 6.7 几种循环的比较 9 6.8 break和continue语句 9 6.8.1 break语句 9 6.8.2 continue 语句 10 6.9 程序举例 11 6 7 数组 1 7.1 一维数组的定义和引用 1 7.1.1 一维数组的定义方式 1 7.1.2 一维数组元素的引用 2 7.1.3 一维数组的初始化 4 7.1.4 一维数组程序举例 4 7.2 二维数组的定义和引用 6 7.2.1 二维数组的定义 6 7.2.2 二维数组元素的引用 6 7.2.3 二维数组的初始化 7 7.2.4 二维数组程序举例 9 7.3 字符数组 9 7.3.1 字符数组的定义 9 7.3.2 字符数组的初始化 9 7.3.3 字符数组的引用 10 7.3.4 字符串和字符串结束标志 10 7.3.5 字符数组的输入输出 10 7.3.6 字符串处理函数 12 7.4 程序举例 14 7.5 本章小结 17 8 函 数 1 8.1 概述 1 8.2 函数定义的一般形式 3 8.3 函数的参数和函数的值 4 8.3.1 形式参数和实际参数 4 8.3.2 函数的返回值 5 8.4 函数的调用 6 8.4.1 函数调用的一般形式 6 8.4.2 函数调用的方式 6 8.4.3 被调用函数的声明和函数原型 7 8.5 函数的嵌套调用 8 8.6 函数的递归调用 10 8.7 数组作为函数参数 12 8.8 局部变量和全局变量 17 8.8.1 局部变量 17 8.8.2 全局变量 19 8.9 变量的存储类别 20 8.9.1 动态存储方式与静态动态存储方式 20 8.9.2 auto变量 21 8.9.3 用static声明局部变量 21 8.9.4 register变量 22 8.9.5 用extern声明外部变量 23 9 预处理命令 1 9.1 概述 1 9.2 宏定义 1 9.2.1 无参宏定义 1 9.2.2 带参宏定义 4 9.3 文件包含 8 9.4 条件编译 9 9.5 本章小结 11 10 指针 1 10.1 地址指针的基本概念 1 10.2 变量的指针和指向变量的指针变量 2 10.2.1 定义一个指针变量 3 10.2.2 指针变量的引用 3 10.2.3 指针变量作为函数参数 7 10.2.4 指针变量几个问题的进一步说明 10 10.3 数组指针和指向数组的指针变量 13 10.3.1 指向数组元素的指针 13 10.3.2 通过指针引用数组元素 14 10.3.3 数组名作函数参数 16 10.3.4 指向多维数组的指针和指针变量 22 10.4 字符串的指针指向字符串的针指变量 25 10.4.1 字符串的表示形式 25 10.4.2 使用字符串指针变量与字符数组的区别 28 10.5 函数指针变量 29 10.6 指针型函数 30 10.7 指针数组和指向指针的指针 31 10.7.1 指针数组的概念 31 10.7.2 指向指针的指针 34 10.7.3 main函数的参数 36 10.8 有关指针的数据类型和指针运算的小结 37 10.8.1 有关指针的数据类型的小结 37 10.8.2 指针运算的小结 37 10.8.3 void指针类型 38 11 结构体与共用体 1 11.1 定义一个结构的一般形式 1 11.2 结构类型变量的说明 2 11.3 结构变量成员的表示方法 4 11.4 结构变量的赋值 4 11.5 结构变量的初始化 5 11.6 结构数组的定义 5 11.7 结构指针变量的说明和使用 7 11.7.1 指向结构变量的指针 7 11.7.2 指向结构数组的指针 9 11.7.3 结构指针变量作函数参数 10 11.8 动态存储分配 11 11.9 链表的概念 12 11.10 枚举类型 14 11.10.1 枚举类型的定义和枚举变量的说明 14 11.10.2 枚举类型变量的赋值和使用 15 11.11 类型定义符typedef 16 12 位运算 1 12.1 位运算符C语言提供了六种位运算符: 1 12.1.1 按位与运算 1 12.1.2 按位或运算 2 12.1.3 按位异或运算 2 12.1.4 求反运算 3 12.1.5 左移运算 3 12.1.6 右移运算 3 12.2 位域(位段) 4 12.3 本章小结 6 13 文件 1 13.1 C文件概述 1 13.2 文件指针 2 13.3 文件的打开与关闭 2 13.3.1 文件的打开(fopen函数) 2 13.3.2 文件关闭函数(fclose函数) 4 13.4 文件的读写 4 13.4.1 字符读写函数fgetc和fputc 4 13.4.2 字符串读写函数fgets和fputs 8 13.4.3 数据块读写函数fread和fwtrite 9 13.4.4 格式化读写函数fscanf和fprintf 11 13.5 文件的随机读写 12 13.5.1 文件定位 12 13.5.2 文件的随机读写 13 13.6 文件检测函数 14 13.6.1 文件结束检测函数feof函数 14 13.6.2 读写文件出错检测函数 14 13.6.3 文件出错标志和文件结束标志置0函数 14 13.7 C库文件 14 13.8 本章小结 15
很好用的东西很经典的一本C教程,TKS这算是谭浩强C语言设计比较新的版本了!目录很详细,使用很方便目录 第1章 C语言程序设计的概念  1.1 程序与程序设计语言   1.1.1 计算机与程序   1.1.2 计算机程序设计语言   1.1.3 高级语言程序的开发过程  1.2 C语言及其标准   1.2.1 C语言的出现   1.2.2 C语言的标准  1.3 C语言程序概要   1.3.1 函数   1.3.2 语句   1.3.3 名字与声明   1.3.4 变量及其赋值   1.3.5 算术运算   1.3.6 赋值类运算符的副作用及限制  习题一 第2章 基本数据类型  2.1 基本数据类型的特征   2.1.1 数值的定点表示与浮点表示   2.1.2 整数的有符号类型与无符号类型   2.1.3 类型宽度与取值范围  2.2 数据常量   2.2.1 整型常量   2.2.2 字符类型及其常量   2.2.3 实型常量   2.2.4 符号常量  2.3 数据类型转换   2.3.1 几个概念   2.3.2 数据类型的隐式转换   2.3.3 数据类型的显式转换   2.4 数据的控制台输入与输出   2.4.1 格式化输出函数pIintf()   2.4.2 格式化输入函数scanf()   2.4.3 字符输入/输出函数getchar()与putchar()  习题二 第3章 C语言程序的流程控制  3.1 算法   3.1.1 算法的组成要素与基本性质   3.1.2 算法描述工具   3.1.3 自项向下、逐步细化的算法设计过程  3.2 判断   3.2.1 命题的“真”、“假”与C语言中的逻辑值   3.2.2 关系运算与关系表达式   3.2.3 逻辑运算与逻辑表达式  3.3 选择型程序设计   3.3.1 if...else结构的应用   3.3.2 if.elseif结构的应用   3.3.3 switch结构的应用   3.3.4 条件表达式  3.4 循环型程序设计   3.4.1 迭代与穷举算法   3.4.2 while结构   3.4.3 dowhile结构   3.4.4 for结构   3.4.5 循环结构的中途退出与重复周期的中途结束  习题三 第4章 模块化程序设计  4.1 函数   4.1.1 设计C语言程序就是设计函数   4.1.2 函数结构   4.1.3 函数定义与函数声明   4.1.4 虚实结合与传值调用   4.1.5 递归函数  4.2 变量的存储属性   4.2.1 变量的作用域与生存期   4.2.2 C语言中变量的存储类型   4.2.3 通过const声明将变量存储在只读区  4.3 模块的编译与链接   4.3.1 分别编译   4.3.2 用项目管理多文件程序的编译与链接过程   4.3.3 头文件  4.4 宏定义替换   4.4.1 字符串宏定义及其基本格式   4.4.2 使用需注意的问题   4.4.3 撤销己定义   4.4.4 带参数的宏定义  习题四 第5章 数组  5.1 一维数组   5.1.1 一维数组定义及数组元素引用   5.1.2 数组元素的引用方法   5.1.3 一维数组的初始化   5.1.4 一维数组元素的查找与排序   5.1.5 数组与函数  5.2 字符串   5.2.1 字符数组与字符串   5.2.2 字符串的输入/输出   5.2.3 字符串处理函数  5.3 二维数组与多维数组   5.3.1 二维数组及其定义   5.3.2 二维数组的初始化   5.3.3 向函数传送二维数组   5.3.4 多维数组  习题五 第6章 指针  6.1 指针基础   6.1.1 地址与指针   6.1.2 指针变量及其定义   6.1.3指针变量的引用   6.1.4 指针的移动与比较   6.1.5 指向指针变量的指针与多级指针   6.1.6 指向void类型的指针  6.2 指针与数组   6.2.1 数组元素的指针引用   6.2.2 多字符串的存储与处理   6.2.3 内存的动态分配与动态数组的建立  6.3 指针与函数   6.3.1 指针参数与函数的地址传送调用   6.3.2 带参数的主函数   6.3.3 返回指针值的函数   6.3.4 指向函数的指针  习题六 第7章 用户定制数据类型  7.1 结构体类型基础   7.1.1 结构体类型及其定制   7.1.2 定义结构体类型变量及对变量的初始化   7.1.3 结构体变量的操作   7.1.4 嵌套结构体类型   7.1.5 位段  7.2 结构体数组   7.2.1 结构体数组的定义与初始化   7.2.2 对结构体数

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术卷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值