递归递归是一种编程思想,但是在实际的开发中除特定场景外,尽量不要使用递归使用递归求解阶乘#include<stdio.h>intfact(int);intfact(inti){longres=1L;//计算结果if(i>0){res=i*fact(i-1);}returnres;}intmain(void){longres=fact(30);printf("res=%ld",res);//输出long类型return0;}汉罗塔汉罗塔的C语言实现#include<stdio.h>voidhanoi(intn,charx,chary,charz);voidhanoi(intn,charx,chary,charz){if(n==1){printf("%c-->%c\n",x,z);}else{hanoi(n-1,x,z,y);printf("%c-->%c\n",x,z);hanoi(n-1,y,x,z);}}intmain(){intn;printf("请输入层数:");scanf("%d",&n);hanoi(n,'X','Y','Z');return0;快速排序#include<stdio.h>voidquick_sort(intarray[],intleft,intright);voidquick_sort(intarray[],intleft,intright){inti=left,j=right;//左右索引intpivot;//中间基准变量inttemp;//替换元素的临时变量pivot=array[(right+left)/2];while(i<=j){//遍历右边的小while(array[i]<pivot){i++;};//遍历左边的大while(array[j]>pivot){j--;};//左右大小交换if(i<=j){temp=array[i];array[i]=array[j];array[j]=temp;i++;j--;};}if(left<j){quick_sort(array,left,j);}if(i<right){quick_sort(array,i,right);}}intmain(void){intarray[]={33,12,4,8,45,56,78,9,56};//待排序数组intlength;length=sizeof(array)/sizeof(array[0]);//数组长度数组占用长度/其中一个元素长度quick_sort(array,0,length-1);for(intk=0;k<length;++k){printf("%d",array[k]);}putchar("\n");return0;}快速排序原理
局部变量局部变量只在那一个代码块能访问。#include<stdio.h>intmain(){inti=520;for(inti=0;i<3;i++){printf("for内部i:%d\n",i);};printf("外部的i%d",i);return0;}全局变量全局变量在程序启动就会创建,直到程序结束才会被销毁,所以会一直占用内存。在实际使用中,尽量避免使用全局变量,在维护时,会改一点而牵全身#include<stdio.h>intcount=0;//这就是全局变量inta(){returncount++;}intb(){returncount++;}intc(){returncount++;}intmain(){a();b();c();printf("count=%d",count);return0;}extern关键字当全局变量没有在开头定义,但在前面又需要使用,这时就需要使用extern了。#include<stdio.h>inta(){externcount;returncount++;}intcount=0;//这就是全局变量intb(){returncount++;}intc(){returncount++;}intmain(){a();b();c();printf("count=%d",count);return0;}
指针函数格式:返回类型*函数名(参数列表);不要返回局部变量的指针举个例子#include<stdio.h>char*get_Word(chars);char*get_Word(chars){charstr[]="Apple";//函数内的局部变量switch(s){case'A':returnstr;//无法返回这个strcase'B':return"Bad";case'C':return"Cat";default:return"None";}}intmain(){chari;printf("请输入一个字母:");scanf("%s",&i);printf("%s\n",get_Word(i));return0;}函数指针定义格式:返回值(*名称)(参数类型);#include<stdio.h>intsquare(intnum);intsquare(intnum){returnnum*num;}intmain(){intnum;int(*fp)(int);//定义函数指针printf("输入一个数字:");scanf("%d",&num);fp=square;printf("%d*%d=%d\n",num,num,(*fp)(num));printf("%d*%d=%d\n",num,num,*fp(num));return0;}头脑风暴涉及知识&实现功能涉及知识把函数指针作为函数的返回值。实现功能用户输入一个式子(1+5),自动判断符号,进行相应的运算。代码说明声明函数intadd(int,int);//加法函数intsub(int,int);//减法函数int(*select(char))(int,int);//符号选择,返回相应的计算函数intcalc(int(*)(int,int),int,int);//计算函数,传入一个函数指针,以及两个数字函数方法//加法函数intadd(intnum1,intnum2){returnnum1+num2;}//减法函数intsub(intnum1,intnum2){returnnum1-num2;}//符号选择int(*select(charop))(int,int){switch(op){case'+':returnadd;case'-':returnsub;}}//计算函数intcalc(int(*fp)(int,int),intnum1,intnum2){return(*fp)(num1,num2);}使用#include<stdio.h>intmain(){intnum1=0,num2=0;charop;int(*fp)(int,int);//接收函数指针printf("输入一个式子(1+1):");scanf("%d%c%d",&num1,&op,&num2);fp=select(op);//符号选择,返回函数指针printf("%d%c%d=%d",num1,op,num2,calc(fp,num1,num2));return0;}
函数传值如果函数只是传入变量值(不是数组),那么传入变量值的作用域只有该函数内部。#include<stdio.h>voidswap(intx,inty);voidswap(intx,inty){inttmp;//存储临时变量printf("swap传入值交换前x=%d,y=%d\n",x,y);tmp=x;x=y;y=tmp;printf("swap传入值交换后x=%d,y=%d\n",x,y);}intmain(){intx=111,y=222;printf("main传入指针互换前x=%d,y=%d\n",x,y);swap(x,y);printf("main传入指针互换后x=%d,y=%d\n",x,y);return0;}函数传址(指针)函数如果传入指针(地址),在函数内部改变指针,外部会跟着改变。#include<stdio.h>voidswapzz(int*x,int*y);/**交换数字*/voidswapzz(int*x,int*y){printf("swap传入指针交换前x=%d,y=%d\n",*x,*y);inttmp;tmp=*x;*x=*y;*y=tmp;printf("swap传入指针交换后x=%d,y=%d\n",*x,*y);}intmain(){intx=111,y=222;printf("main传入指针互换前x=%d,y=%d\n",x,y);swapzz(&x,&y);printf("main传入指针互换后x=%d,y=%d\n",x,y);return0;}函数传入数组函数传入数组,本质是传入一个指针。#include<stdio.h>voidget_arr(intarr[3]);voidget_arr(intarr[3]){inti;arr[1]=520;printf("get_arr方法内");for(i=0;i<3;i++){printf("%d",arr[i]);};}intmain(){intarr[3]={1,2,3};get_arr(arr);inti;printf("\nmain方法内");for(i=0;i<3;i++){printf("%d",arr[i]);}return0;}
函数定义格式返回类型函数名(参数类型参数变量){函数方法体}//定义函数intsum_num(intnum){intres=1;returnres;}函数使用#include<stdio.h>//首先声明函数(有些版本C语言,可以不用)intsum_num(intnum);//定义函数intsum_num(intnum){intres=1;//循环阶乘for(num;num>1;num--)res=num*res;returnres;}intmain(){intnum=10;//使用函数intres=sum_num(num);printf("%d的阶乘结果:%d\n",num,res);return0;}函数的可变参数使用可变参数需要引入:#include<stdarg.h>#需要#include<stdarg.h>头文件里面的这几个东西-va_list-va_start-va_arg-va_end定义可变参数之前的intnum,是可变参数的总长度一般这是实现原理#include<stdio.h>#include<stdarg.h>//声明函数intsum_num(intnum,...);//定义可变参数的函数intsum_num(intnum,...){/*该函数实现可变函数的值相加。*/inti,sum=0;va_listvap;//定义接收可变参数的列表va_start(vap,num);//开辟接收可变参数的空间num是可变参数的个数//利用循环取出可变参数for(i=0;i<num;i++){sum+=va_arg(vap,int);//判断参数逻辑}//关闭空间va_end(vap);returnsum;}intmain(){intres=sum_num(5,1,2,3,4,5);printf("相加结果:%d\n",res);}
常量常量一般这样定义://不加分号#defineLOVE520#defineA'a'#definePI3.14const修饰的指针变量const靠近谁就锁定谁,靠近*p,就锁定*p。intnum=520;intconst*p=##//锁定*p为只读,p能变int*constp=##//锁定p为只读,*p能变const修饰的指针变量有三种常见情况地址值能变,值不能变#include<stdio.h>intmain(){intnum=520;intconst*p=##//锁定*p为只读,p可变printf("p=%d\n",*p);//解引用指针变量,获取值p=(constint*)1314;//等价于p=1314;重新赋值printf("p=%d\n",p);return0;}地址值不能变,值能变#include<stdio.h>intmain(){intnum=520;int*constp=##//锁定p为只读,*p可变printf("p=%d%p\n",*p,p);//解引用指针变量,获取值*p=1314;//重新赋值printf("p=%d%p\n",*p,p);return0;}地址值&值都不能变实际中很少用到intmain(){intnum=520;constint*constp=##//锁定p、*p为只读return0;}
void指针viod指针称为通用指针,就是可以指向任意类型的数据,就是任意类型的指针都可以赋值给void指针。#include<stdio.h>intmain(){//声明不同类型的变量inti=123;char*c="ABC";//声明void指针void*v;v=i;//把int类型数据赋值给void类型数据printf("%d\n",(int*)v);v=c;//把char类型数据赋值给void类型数据printf("%s\n",(char*)v);return0;}NULL指针NULL用于给指针和对象,指向一个不被使用的地址,避免出现野指针(没有初始化的指针,而出现的随机值);而\0表示字符串的结尾。#include<stdio.h>intmain(){int*a;//野指针int*b=NULL;//作为指针变量初始化printf("%d\n",a);printf("%d\n",b);return0;}
问题在使用CLion编写C项目时,一个项目下如果包含多个C文件里有main函数,就会出现以下报错出现问题的原因在CMakeLists.txt文件里,所有包含main函数C文件,都共用了这个a,所有就会起冲突。解决使‘CMakeLists.txt’文件能自动给main函数文件起不同的名字,就完美解决CMakeLists.txt文件内容#遍历项目根目录下所有的.cpp文件file(GLOBfiles*.c*/*.c)foreach(file${files})string(REGEXREPLACE".+/(.+)\\..*""\\0"exe${file})add_executable(${exe}${file})message(\\\\--\src/${exe}.cpp\will\be\compiled\to\bin/${exe})endforeach()技巧#如果你只需要根目录下的test文件夹的所有.c文件file(GLOBfilestest/*.c)#如果你只有两层目录的话file(GLOBfiles*.c*/*.c)#同理,三层的话file(GLOBfiles*.c*/*.c*/*/*.c)#官方提供了一种递归的方法#这样在运行框会多一个CMakeCXXCompilerId,不过无伤大雅file(GLOB_RECURSEfiles*.c)
说明安装Win环境下运行C程序官网安装包地址:https://www.jetbrains.com/clion/download/other.htmlCLion2020.1地址:https://pan.bigdataboy.cn/#/s/vZsD破解包:https://pan.bigdataboy.cn/#/s/mYSB最好配合2020.1使用MinGW下载地址:https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/安装&配置正常下载安装CLion(最好是2020.1版本)配置MinGW下载MinGW网址:https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/进入后,不要直接点下载,往下拉,下载压缩包下载完成解压到某个目录配置CLion第一次安装CLion,会弹出如下窗口配置MinGW在CLion内配置MinGW安装完成破解使用时间拖入插件再次打开查看过期时间
指针数组就是一个数组,其中的元素是指针变量。#include<stdio.h>intmain(){inta=1;intb=2;intc=3;//指针数组放入指针变量int*iarr[3]={&a,&b,&c};//循环打印inti;for(i=0;i<3;i++){printf("%d\n",*iarr[i]);}return0;}数组指针数组指针是一个指针,它指向的是一个数组。#include<stdio.h>intmain(){//声明一个数组inttemp[5]={1,2,3,4,5};//指向数组指针int(*p)[5]=&temp;//遍历打印inti;for(i=0;i<5;i++){//打印内存地址printf("%p\n",*p+i);//访问数组地址值//打印地址的变量printf("%d\n",*(*p+i));//访问数组地址值获取地址值变量}return0;}
引入内存如何存放变量内存中不存放变量,存放的是一堆十六位进制的地址值,编译器就会把这些地址值与相应变量对应起来。指针通常所说的指针,就是地址的意思,C语言中有专门存放指针的变量类型—指针变量.跟普通变量不同,指针变量存放的是地址值,所以一个地址是占4个字节的空间指针变量的类型是所存变量的类型定义指针变量定义指针变量跟普通变量十分相似,只是中间多了一个星号(*)//不推荐定义未初始化的指针变量,不然可能产生意想不到的Bug。(未定义就会随机分配地址,这很危险)//使用指针变量一定要初始化char*pc;int*pi;取地址运算符和取值运算符如需要获取某个变量的地址,就需要使用取地址运算(&)这里(*)表示定义指针变量charc='A';//取地址值赋值给指针变量char*pc=&c;如果需要访问指针变量指向的数据,可以使用取值运算符(*)这里(*)表示获取指针变量指向的值。//打印出的原本的值printf("i=%d\n",*pi);//%p打印指针变量的地址值printf("*pi=%p\n",*pi);代码#include<stdio.h>intmain(){//定义变量charc='A';inti=123;//获取地址赋值给指针变量char*pc=&c;int*pi=&i;//打印原本变量printf("c=%c\n",*pc);printf("i=%d\n",*pi);//打印地址值printf("*pc=%p\n",&pc);printf("*pi=%p\n",&pi);return0;}