C-函数的由浅入深

1.函数的定义
数据类型 函数名 (【数据类型 形参名,数据类型 形参名, …】)
2.函数的传参
值传递
地址传递
全局变量
3.函数的调用
嵌套调用
递归
4.函数与数组
5.函数与指针
指针函数
函数指针
函数指针数组

函数的定义

#include<stdio.h>
#include<stdlib.h>

int main(int argc,char *argv[])
//argc 是计算一共传递参数的个数
//argv 字符指针数组的首地址   输入参数都会保存在这个字符数组里面,最后一个元素是NULL (存放char * 类型的数组)
{
	printf("argc = %d\n",argc);
	//for(i = 0;i<argc;i++)
	for(i = 0;argc[i] != NULL;i++)//等价于上述表达式
		puts(argv[i]);
	printf("hello!\n");//返回值 长度7
	return 0;//当没有返回值时,默认返回最后一条语句的返回值
}
#include<stdio.h>
#include<stdlib.h>
/*
void print_value(void)
{
	printf("hello world!\n");
	return ;
}

int main()
{
	print_value();
	return 0;
}
*/
void print_value(void);
int main()
{
	print_value();
	return 0;
}
void print_value(void)
{
	printf("hello world!\n");
	return ;
}
//main函数是主调函数,其它被调函数需要写在主调函数上方实现,或者在上方声明才能在下方实现

一个进程的返回状态是给他的父进程看的

值传递

#include<stdio.h>
#include<stdlib.h>

int print_value(int a,int b)
{
	printf("%d %d\n",a,b);
	return 0;
}

int main()
{
	int i=3, j=5;
	print_value(i,j);
	return 0;
}

地址传递 (间接引用)

#include<stdio.h>
#include<stdlib.h>

void swap(int *p,int *q)
{
	int tmp;
	tmp =*p;
	*p = *q;
	*q = tmp;
}

int main()
{
	int i=3, j=5;
	
	swap(&i,&j);
	printf("i = %d,j = %d\n",i,j);
	return 0;
}

嵌套调用

#include<stdio.h>
#include<stdlib.h>

max(int a,int b,int c)
{
	int tmp;
	tmp = a > b ? a : b;
	return tmp > c ? tmp : c;
}
min(int a, int b,int c)
{
	int tmp;
	tmp = a < b ? a : b;
	return tmp < c ? tmp : c;
}
dist(int a,int b,int c)
{
	return max(a,b,c) - min(a,b,c);
}
int main()
{
	int a=3,b=5,c=10;
	int res;
	res =  dist(a,b,c)
	printf("res = %d\n",res);
	return 0;
}

递归 一个函数嵌套的调用自己

#include<stdio.h>
#include<stdlib.h>

void c(void)
{
	printf("[%s]begin!\n",__FUNCTION__);
	printf("[%s]end!\n",__FUNCTION__);
}
void b(void)
{
	printf("[%s]begin!\n",__FUNCTION__);
	printf("[%s]call c()!\n",__FUNCTION__);
	c();
	printf("[%s]c() returned!\n",__FUNCTION__);
	printf("[%s]end!\n",__FUNCTION__);
}
void a(void)
{
	printf("[%s]begin!\n",__FUNCTION__);
	printf("[%s]call b()!\n",__FUNCTION__);
	b();
	printf("[%s]b() returned!\n",__FUNCTION__);
	printf("[%s]end!\n",__FUNCTION__);
}
int main()
{
	printf("[%s]begin!\n",__FUNCTION__);
	printf("[%s]call a()!\n",__FUNCTION__);
	a();
	printf("[%s]a() returned!\n",__FUNCTION__);
	printf("[%s]end!\n",__FUNCTION__);
	return 0;
}
[main]begin!
[main]call a()!
[a]begin!
[a]call b()!
[b]begin!
[b]call c()!
[c]begin!
[c]end!
[b]c() returned!
[b]end!
[a]b() returned!
[a]end!
[main]a() returned!
[main]end!

递归解决阶乘和斐波那契数列
递归 能够抽象出来一个类似公式的递推
汉诺塔 / 二叉树 /阶乘 /斐波那契数列

#include<stdio.h>
#include<stdlib.h>

int func(int n)
{
	if(n<0)
		return -1;
	if(n == 0 || n ==1)
		return 1;
	return n * func(n-1);//一层一层的压栈 出栈
}

int main()
{
	int n;
	int res;
	scanf("%d",&n);
	res = func(n);
	printf("%d! = %d\n",n,res);
	
	return 0;
}
#include<stdio.h>
#include<stdlib.h>

int fib(int n)
{
	if(n<1)
		return -1;
	if(n ==1 ||n ==2)//已知条件
		return 1;
	return fib(n-1) + fib(n-2);//公式
}


int main()
{
	int n;
	int res;
	scanf("%d",&n);	
	
	res = fib(n);
	printf("fib[%d] = %d\n",n,res);
	
	return 0;
}

函数与一维数组

#include<stdio.h>
#include<stdlib.h>
/*
int a[N] = {1,2,3,4,5,6};
int *p = a;//一维数组 a和p除了一个常量一个变量 其他等价
传参形式--->a   		*a  		 a[0] 		 &a[3] 		 p[i] 		 p		  *p 		 p+1
					*(a+0)
函数形参-->int *     int 		 int 		int * 		 int		 int * 	  int 		 int *
*/

/*方法一
void print_arr(int *p,int n)
{
	int i;
	printf("%s:%d\n",__FUNCTION__,sizeof(p));  
	for(i =0;i < n;i++)
		printf("%d ",*(p+i));
	printf("\n");
}
*/
void print_arr(int p[],int n)//int p[] 形参和定义的时候是不一样的  可以理解一个 [] 等价于一个 *
{
	int i;
	printf("%s:%d\n",__FUNCTION__,sizeof(p));  
	for(i =0;i < n;i++)
		printf("%d ",*(p+i));
	printf("\n");
}
void func(int *p,int n)
{
	int i = 0,m,j,tmp;
	m = (n-1)/2;
	for(; i<= m;i++)
	{
		j = n-1-i;
		tmp = p[i];
		p[i] = p[j];
		p[j] = tmp;
	}
	
}

int main(int argc,char **argv)
//int main(int argc,char *argv[])
{
	int a[] = {1,3,5,7,9};
	
	printf("%s:%d\n",__FUNCTION__,sizeof(a));
	
	print_arr(a,sizeof(a)/sizeof(*a));//一维数组传参是传递了数组的起始位置,因此还需要告诉数组的长度
	
	func(a,sizeof(a)/sizeof(*a));//逆序数组
	
	print_arr(a,sizeof(a)/sizeof(*a));
	return 0;
}

函数和二维数组

#include<stdio.h>
#include<stdlib.h>
#define M 3
#define N 4
/*
int a[M][N]= {...};
int *p = *a;
int (*q)[N] = a;//数组指针  指向数组的指针  q 也可以称行指针

main传参	  -->  a[i][j]    *(a+i)+j		a[i]+j		p[i] 		*p		q[i][j]		*q 			q 				P+3		q+2
																						*(q+0)

函数定义形参接收-->  int 	  int *			int *		int			int		int 		int *		int (*)[N]		int *		int (*)[N]	
*/


void print_arr(int *p,int n)
{
	int i;
	for(i =0;i<n;i++)
	{
		printf(%4d ",p[i]);//此时,把二维数组当成大的一维数组
	}
	printf("\n");
}

void print_arr1(int (*p)[N],int m,int n)
//void print_arr1(int p[][N],int m,int n)
{
	int i,j;
	printf("sizeof(p) = %d\n",sizeof(p));//8
	
	for(i =0;i<m;i++)
	{
		for(j = 0;j<n;j++)
			printf("%4d ",*(*(p+i)+j));
			//printf("%4d ",p[i][j]);
		printf("\n")
	}
}

float average_score(int *p,int n)
{
	int i;
	float sum =0;
	for(i = 0;i<n;i++)
		sum += p[i];
	return sum/n;
}

void find_num(int (*p)[N],int num)
{
	int i;
	for(i = 0;i < N; i++)
		printf("",*(*(p+num)+i));
	printf("\n");
}

int main()
{
	
	int a[M][N] = {1,2,3,4,5,6,7,8,9,10,11,12};

	print_arr(*a,M*N);
	//print_arr(&a[0][0],M*N); //*a  a[0]  *(a+0)  行指针转换成列指针
	
	printf("sizeof(a) = %d\n",sizeof(a));//48
	print_arr1(a,M,N);//同样需要传递行列数
	
	float ave;
	ave = average_score(*a,M*N);//此时,需求 不需要区分行列 所以按照一个大的一维数组处理
	printf("ave = %f ",ave);

	int num = 0;
	find_num(a,num);
	return 0;
}

函数与字符数组

#include<stdio.h>
#include<stdlib.h>

char *mystrcpy(char *dest,const char *src)
{	
	char *ret = dest;
	if(dest! = NULL && src != NULL)
		while((*dest++ = *src++) != '\0');
	return ret;
}
char *mystrncpy(char *dest,const char *src,size_t n)
{	
	int i;
	for(i = 0;i < n && (dest[i] = src[i]); i++)
		;
	for(;i <n;i++)
		dest[i] = '\0';
	return dest;
}

int main()
{
	char str1[]="helloworld";
	char str2[128];
	mystrcpy(str2,str1);
	mystrncpy(str2,str1,5);
	
	puts(str2);
	return 0;
}

函数与指针关系的详细剖析

指针函数:一个函数的返回值是指针
返回值 * 函数名(形参)
如:int *fun(int);

#if 0
void find_num(int (*p)[N],int num)
{
	int i;
	for(i = 0;i < N; i++)
		printf("",*(*(p+num)+i));
	printf("\n");
}
#endif
int *find_num(int (*p)[N],int num)//函数的功能越简单越好 和其他函数减少依赖关系
{
	if(num > M-1)
		return NULL;
	return *(p + num);
}

函数指针:指向函数的指针 指向和函数指针相同类型的函数
类型 (*指针名)(形参)
如:int (*p)(int);

#include<stdio.h>
#include<stdlib.h>


int add(int a, int b)//函数名是一段代码所关联的入口地址
{
	return a+ b;
}
int sub(int a,in b)
{
	return a-b;
}



int main()
{
	int a = 3, b = 5;
	int ret;
	int (*p)(int,int);//别忘记括号   指向函数的指针 指向和函数指针相同类型的函数  并通过指针调用函数
	int (*q)(int,int);//int (int,int) (*q)
	p = add;
	q = sub;
	
	//ret = add(a,b);
	ret = p(a,b);
	
	printf("%d\n",ret);
	return 0;
}

函数指针数组:
类型 (*数组名【下标】) (形参)
如:int (*arr[N])(int); 数组中的N个元素 都是指向函数的指针

#include<stdio.h>
#include<stdlib.h>


int add(int a, int b)//函数名是一段代码所关联的入口地址
{
	return a+ b;
}
int sub(int a,in b)
{
	return a-b;
}

int main()
{
	int a = 3, b = 5,i;
	int ret;
	//int (*p)(int,int);
	//int (*q)(int,int);
	int (*funcp[2])(int,int);// int (int,int)  *funcp[2];
	//p = add;
	//q = sub;
	funcp[0] = add;
	funcp[1] =sub;
	
	//ret = add(a,b);
	//ret = p(a,b);
	for(i = 0;i<2;i++)
	{
		ret = funcp[i](a,b);
		printf("%d\n",ret);
	}
	//printf("%d\n",ret);
	return 0;
}

p59反复看

  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本资源是压缩包形式的, 里面包含 本书,里面是pdf格式的, 带书签目录,本书是完整版的。 资源都是我自己用过的,不骗大家。 本书作者: 肖俊宇 吴为胜; 出版社: 电子工业出版社 内容简介: 《由浅入深学C++:基础、进阶与必做300题(含DVD光盘1张)》是C++语言的入门教程,较为系统地介绍了C++语言的基础内容。本书共分为3篇22章,详细介绍了C++语言的基础知识、面向对象、标准模块、底层开发和综合案例。本书循序渐进地讲述了C++的基础知识、C++程序的组成及其开发过程、C++程序中的数据、表达式和语句、控制程序流程、数组与字符串、指针与引用、使用函数函数模板、错误和异常处理、宏和预编译、面向对象的开发、封装、继承、多态、类模板、文件流、标准模板库STL和编程实践等内容。 《由浅入深学C++:基础、进阶与必做300题(含DVD光盘1张)》涉及面广,从基本知识到高级内容和核心概念,再到综合案例,几乎涉及C++开发的所有重要知识。本书适合所有想全面学习C++开发技术的人员阅读,尤其适合没有编程基础的C++语言初学者作为入门教程,也可作为大、中院校师生和培训班的教材,对于C++语言开发爱好者,本书也有较大的参考价值。 章节目录: 第1篇 C++基础篇 第1章 C++概述 1 1.1 引言 1 1.1.1 C++的历史沿革 1 1.1.2 入门C++ 2 1.1.3 编程思想的转变 3 1.2 C++概述 4 1.2.1 C++的特征 5 1.2.2 C与C++的比较 5 1.2.3 C++的应用领域 6 1.3 C++源程序的组成 6 1.3.1 基本组成元素 7 1.3.2 标识符 8 1.3.3 保留字 8 1.3.4 符号 8 1.4 C++集成开发环境——DEV-C++ 9 1.4.1 选择C++编译器 9 1.4.2 安装DEV-C++ 10 1.4.3 DEV-C++ IDE简介 11 1.5 第一个C++程序——Hello World 11 1.5.1 创建源程序 11 1.5.2 编译运行 13 1.6 小结 14 1.7 习题 14 第2章 变量与数据类型 18 2.1 常量和变量 18 2.1.1 常量 18 2.1.2 变量 21 2.1.3 变量的定义及赋值 22 2.1.4 变量的应用示例 24 2.2 基本数据类型 25 2.2.1 基本数据类型概述 25 2.2.2 整型数据类型 26 2.2.3 浮点型数据类型 27 2.2.4 字符型数据类型 29 2.2.5 布尔型数据类型 30 2.3 变量的作用域 31 2.4 类型转换 32 2.4.1 隐式转换 32 2.4.2 显式转换 33 2.5 小结 34 2.6 习题 34 第3章 表达式与语句 39 3.1 运算符 39 3.1.1 运算符概述 39 3.1.2 算术运算符 40 3.1.3 自增和自减运算符 42 3.1.4 赋值运算符 43 3.1.5 关系运算符 44 3.1.6 逻辑运算符 45 3.1.7 条件运算符 46 3.1.8 逗号运算符 47 3.1.9 位运算符 48 3.1.10 sizeof运算符 49 3.2 运算符的优先级和结合性 50 3.3 表达式 51 3.4 语句 53 3.4.1 空格的作用 53 3.4.2 语句块 54 3.4.3 赋值语句 55 3.4.4 空语句 56 3.5 小结 57 3.6 习题 57 第4章 流程控制结构之顺序结构 63 4.1 程序流程图 63 4.2 表达式语句 64 4.3 格式化输入/输出 65 4.3.1 标准输入流cin 65 4.3.2 标准输出流cout 66 4.3.3 输出流cerr和clog 68 4.4 格式控制函数 69 4.5 格式控制符 71 4.5.1 控制不同进制的输出 72 4.5.2 控制输出宽度 72 4.5.3 控制输出精度 73 4.6 顺序结构综合应用 74 4.7 小结 75 4.8 习题 75
学习C语言是编程初学者的重要一步,也是进阶学习其他编程语言的基础。要掌握C语言,需要从浅入深学习基础知识,并进行进阶训练,其中必须做的是解答300题。 首先,对于C语言的学习,初学者应该从最基础的语法规则开始学习。了解如何声明变量、定义函数、运算符的使用等等,这些是C语言的基础知识。通过学习这些基础知识,可以编写简单的程序并理解其运行原理。 进一步学习C语言,需要了解更多高级的概念和技术。比如,掌握指针的使用,可以更加灵活地处理内存,提高程序的效率。学习结构体和联合体,可以对数据进行更好的组织和管理。学习动态内存分配,可以灵活地申请和释放内存。此外,还可以学习文件操作、位运算等进阶知识。 在学习C语言的过程中,必做300题是非常重要的训练。这些题目包含了各种难度和类型的编程问题,通过解答这些题目,可以不断地巩固和提升自己的编程能力。这些题目可以涉及到基本的算法数据结构,也可以包含一些实际开发中常见的问题。解答这些题目需要运用所学的知识,并通过不断的实践和思考来提高解决问题的能力。 总之,学习C语言是一个由浅入深的过程,需要逐步掌握基础知识并进行进阶训练。通过必做300题,可以不断提高自己的编程能力,为将来更深入的学习和开发打下坚实的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值