[在此处输入文章标题]
宏
知识点
功能:宏可在预编译时将程序中某些内容直接替换,没有优先级
带参宏:
带参宏与普通函数的比较:
1.带参宏不必指定参数类型,而函数只能传递某个类型的参数。
2.带参宏在预编译时直接替换,比函数调用更有效率,开销更小。
3.带参宏只适用于较小篇幅的函数,否则会大幅增加程序的长度,使得效率反而降低。
带参宏与内联函数的区别:
宏在预编译时替换,而内联函数在编译时替换,两者都可用于简短的功能函数。
由于宏只替换没有优先级的性质,在使用宏时注意括号的添加
实现
行缓冲
输出行缓冲:
以\n为输出结束标识符,若没有该换行符,则将一直运算至缓冲区填满后或运算结束后一起输出。
输入行缓冲:
以\n为输入结束标识符,若不键入换行符,则一直等待输入。
知识点
1.低精度向高精度转换安全:float->double
高精度直接截断
2.小范围转换至大范围:->unsigned,char->int
3.输出时也会进行类型转换,若int类型用%u输出,则将转换为unsigned类型后输出。
0,’0’,’\0’的区别
0是数字零
‘\0’是一个char字符,功能是标志一个字符串的结束,对应的数值是0
‘0’是一个char字符,对应的数值是48
知识点
返回类型函数名(参数)
知识点
int main (int argc,char *argv[])
int表示返回值为int类型,作为程序的入口,返回值给父进程
argc表示参数个数
argv[]表示参数列表
#include<stdio.h>
#include<string.h>
int main(intargc,char *argv[])
{
if(2!=argc)
{
printf("参数错误\n");
return -1;
}
if(!strcmp(argv[1],"1"))
{
printf("是男孩。\n");
}
if(!strcmp(argv[1],"2"))
{
printf("是女孩。\n");
}
return 0;
}
shell是父进程,传参数给main的argv
迭代函数
知识点
利用栈的构建特性实现层层调用
int sum(int a)
{
int i = 1, sum =0;
if (a > 0)
{
for (i=1;i<=a; i++)
{
sum+= i;
}
}
return sum;
}
int main(void)
{
int a = 100;
printf("%d内的数的和?%d.\n",a, sum(a));
return 0;
}
递归函数
#include <stdio.h>
int jiecheng(int a)
{
if(a<=0)
{
printf("输入错误。\n");
return-1;
}
if(a==1)
{
return1;
}
returna*jiecheng(a-1);
}
int main(void)
{
intret=jiecheng(5);
printf("ret=%d\n",ret);
return0;
}
实现
输出fibo数列的指定位
#include <stdio.h>
int fibo(int num)
{
if(1==num)
{
return1;
}
if(2==num)
{
return1;
}
returnfibo(num-1)+fibo(num-2);
}
int main(void)
{
intnum;
while(1)
{
printf("输入要计算的fibo数的项数\n");
scanf("%d",&num);
if(num==0)
{
break;
}
printf("%d项fibo数的值为:%d\n",num,fibo(num));
}
return0;
}
其他函数
实例
1.strcmp函数
功能:可以man3看到strcmp函数的返回值,字符串a小于b则返回为负数,等于则返回零,大于则返回正数。由此可见函数返回值的定义、传递和表达。
2.printf函数
功能:查看printf函数的参数传递,可以发现,printf函数参数由右向左传递
实践
#include<stdio.h>
floatadd(float a,float b);
floatjian(float a,float b);
floatcheng(float a,float b);
floatchu(float a,float b);
intmain(void)
{
float a,b,ret;
printf("请输入要计算的数值:\n");
scanf("%f %f",&a,&b);
char ch=0;
printf("请输入运算符:\n");
do
{
scanf("%c",&ch);
}while(ch=='\n');
switch(ch)
{
case '+' :
ret=add(a,b);
break;
case '-' :
ret=jian(a,b);
break;
case '*' :
ret=cheng(a,b);
break;
case '/' :
ret=chu(a,b);
break;
default :
printf("error\n");
break;
}
printf("%f%c%f=%f\n",a,ch,b,ret);
return 0;
}
float add(floata,float b)
{
float c=a+b;
return c;
}
floatjian(float a,float b)
{
float c=a-b;
return c;
}
floatcheng(float a,float b)
{
float c=a*b;
return c;
}
floatchu(float a,float b)
{
if(b==0)
{
printf("除数不能为零.\n");
return -1;
}
float c=a/b;
return c;
}
知识点
标准格式要求:函数的声明在main之前,末尾需要加分号,定义在函数之后
2.编写函数,计算数字二进制形式中1的个数
知识点
计算机使用补码存储,本题即为计算补码中1的个数
正数的补码是原码本身,负数的补码是反码加一
正数位移后补零,负数位移后补一
思路
按位将数字与1相与,若结果不为0则该位为1。考虑到负数位移补1陷入死循环的情况,选择位移相与的1,则该1位移后不为1,而是对应位为1。
#include <stdio.h>
int cnt_num_1(int num)
{
int i=0;
unsigned intj=1;
while(j)
{
if((num&j)!=0)
{
i++;
}
j=j<<1;
}
return i;
}
int main()
{
int a;
printf("统计num中1中出现的次数\n");
scanf("%d",&a);
intret=cnt_num_1(a);
printf("num中1出现的次数为:%d\n",ret);
return 0;
}
2.编写函数,实现memset函数功能
void my_memset(char *p, int c, intlenth)
{
inti = 0;
for(i=0; i<lenth; i++)
{
p[i]= c;
}
// returnp;
}
int main(void)
{
intc=5;
charp[10];
my_memset(p,c, 11);
printf(“%s\np);
}
3.编写函数,实现strcmp函数功能
#include <stdio.h>
int my_strcmp(const char *s1,constchar *s2)
{
while(1)
{
while(*s1==*s2)
{
if((*s1==0)&&(*s2==0))
break;
s1++;
s2++;
}
if(*s1!=*s2)
{
return(*s1>*s2?1:-1);
}
if(*s1==*s2)
return0;
}
}
int main(void)
{
printf("%d\n",my_strcmp("1234","1235"));
return0;
}
5.编辑函数,输入命令显示是否合法
#include<stdio.h>
#include<string.h>
#definels_ "ls"
#definepwd_ "pwd"
#definemkdir_ "mkdir"
#defineNUM 3
#defineCNT 100
//定义全局变量
charbuf[NUM][CNT];
//进行初始化命令
voidinit_command(void)
{
strcpy(buf[0],ls_);
strcpy(buf[1],pwd_);
strcpy(buf[2],mkdir_);
}
intmain(void)
{
//定义一个输入命令的字符数组
char cmd[CNT];
memset(cmd,0,sizeof(cmd));
//调用初始化函数
init_command();
while(1)
{
printf("root@");
scanf("%s",cmd);
int i=0;
for(i=0;i<NUM;i++)
{
if(!strcmp(buf[i],cmd))
{
printf("%s是合法命令:%s.\n",cmd,buf[i]);
break;
}
}
if(i>=3)
printf("%s不是合法字符,请重新输入。\n",cmd);
}
return 0;
}