递归
递归是指在函数的定义中使用函数自身的方法,简言之就是自我调用。
1 2 3 4 5 6
| void recursion(){ recursion(); } int main(){ recursion(); }
|
Note:使用递归要注意需要有跳出循环的条件,比如阶乘、斐波那契数列等常用到递归。
1 2 3 4 5 6 7 8 9 10 11
| #include <stdio.h> double factorial(unsigned int i){ if(i <= 1){ return 1; } return i * factorial(i-1); } void main(){ int i = 15; printf("%d 的阶乘为 %f \n",i,factorial(i)); }
|
Fibonaci斐波那契数列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <stdio.h> int fibonaci(int i){ if(i==0){ return 0; } if(i ==1){ return 1; } return fibonaci(i-1)+fibonaci(i-2); } void main(){ int i; for(i = 0;i<10;i++){ printf("%d\t\n",fibonaci(i)); } }
|
可变参数
多数编程语言中都会有可变参数的函数形式
1 2 3 4 5 6 7 8 9 10 11
| int func(int,...){ . . . } void main(){ func(1,2,3); func(1,2,3,4); }
|
注:使用可变参数函数,需要导入stdarg.h
头文件,其中定义了相关的宏和函数步骤:
- 定义一个可变参数函数,最后一个参数为
...
省略号,前面一个参数总是int
表示参数的个数
- 函数中创建一个
va_list
类型变量,该类型定义在stdarg.h
中
- 使用int参数和va_start宏来初始化va_list变量为一个参数列表
- 使用va_arg宏和va_list变量来访问参数列表中的每个项
- 使用va_end来清理赋予va_list变量的内存
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <stdio.h> #include <stdarg.h> double average(int num,...){ va_list valist; double sum = 0.0; int i; va_start(valist,num); for(i=0; i<num;i++){ sum+=va_arg(valist,int); } va_end(valist); return sum/num; } int main(){ printf("Average of 2,3,4,5 = %f \n",average(4,2,3,4,5)); printf("Average of 5,10,15 = %f \n",average(3,5,10,15)); }
|
内存管理
C语言为内存的分配和管理提供了几个函数stdlib.h
文件中
1 2 3 4 5 6 7 8 9 10
| #include <stdio.h> #include <stdlib.h> void *calloc(int num,int size); void fress(void *address); void *malloc(int num); void *realloc(void *address,int newsize);
|
编程时,若预先知道数组大小,便容易定义char name[100]
若不确定数组大小,则可以用指针来指向未定义所需内存大小的字符,后期动态分配内存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include <stdio.h> #include <stdlib.h> #include <string.h> int main(){ char name[100]; char *description; strcpy(name,"Hello C"); description = malloc(200 * sizeof(char)); if(description == NULL){ fprintf(stderr,"Error,不能分配所需内存\n"); }else{ strcpy(description,"Hello C ,非常不错的编程语言\n"); } printf("Name = %s \n",name); printf("Description:%s \n",description); }
|
程序退出时,会自动释放内存,但是依然建议在不需要内存时候,手动调用free()
函数释放内存。也可以通过realloc()
调整内存大小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include <stdio.h> #include <stdlib.h> #include <string.h> int main(){ char name[100]; char *description; strcpy(name,"Boby"); description = calloc(30,sizeof(char)); if(description == NULL){ fprintf(stderr,"错了,又没有分配好内存\n"); }else { strcpy(description,"Boby,你好啊\n"); } description = realloc(description,100*sizeof(char)); if(description == NULL){ fprintf(stderr,"好吧,又错了,内存没有调整正确\n";) }else{ strcat(description,"Boby,你在哪儿啊\n"); } printf("Name = %s \n",name); printf("description : %s \n",description); free(description); }
|
命令行参数
执行程序时,可以从命令行传值给C程序,这类值称为命令行参数,当其需要从外部控制程序时候,这类参数就很重要了。
命令行参数,是使用main()
函数参数来处理,其中argc
是传入参数的个数,argv[]
是一个指针数组,指向传递给程序的每个参数。
1 2 3 4 5 6 7 8 9 10
| #include <stdio.h> int main(int argc,char *argv[]){ if(argc == 2){ printf("传递来的参数是%s\n",argv[1]); }else if(argc > 2){ printf("传递来了许多参数\n"); }else{ printf("只有一个参数\n"); } }
|
Note:需要说明的是argv[0]
存储程序的名字,argv[1]
才是第一个参数的指针,*argv[n]
是最后一个参数,如果没有任何参数,argc就是1,传递一个参数,argc就是2;
多个命令行参数之间用空格分隔,多是参数本身带有空格,那就放在""
或''
之内
1 2 3
| $ gcc test.c $ ./test.out argument1,argument2 $ ./test.out argument1,"argument with blank"
|