电商专业学习嵌入式软件开发第六十三天

  • C基础第三天

今天讲的是函数,明天开始讲指针。现在出现在笔记中的代码都是我写不出来的,看了一下这两天的代码量,感觉很是头疼,背下来都有难度。

//static静态局部变量
#include <stdio.h>
int fun(int a)
{
//  const int b = 2;//const代表不能修改后面的值
    static int b = 2;//static会保留上一次的值
    b++;
    return a+b;
}
int main(int argc,char *argv[])
{   
    int i;
    for(i = 0;i < 4;i++)//0,1,2,3
    {
        printf("%d\n",fun(i));
    }
    return 0;
}
//函数递归-阶乘
#include <stdio.h>
long jiecheng(int n)//n = 5
{
    long ret = -1;
    if(n < 0)
        printf("n < 0,input error!\n");
    else if(n == 0||n == 1)
        ret = 1;
    else
        ret = jiecheng(n-1)*n;//jiecheng(4)*5
    return ret;
}
int main(int argc,char *argv[])
{
    int n;
    long y;
    printf("请输入一个数:");
    scanf("%d",&n);
    y = jiecheng(n);
    printf("%d! = %ld\n",n,y);
    return 0;
}
//函数嵌套-阶乘
#include <stdio.h>
int pf(int i)
{
    return i * i;
}
int jc(int a)
{
    int i;
    int s = 1;
    a = pf(a);//函数嵌套
    for(i = 1;i <= a;i++)
    {
        s*=i;
    }
    return s;
}
int main(int argc,char *argv[])
{
    int i;
    int sum = 0;
    for(i = 1;i <= 3;i++)
    {
        sum += jc(i);
    }
    printf("%d\n",sum);
    return 0;
}
//函数嵌套调用-最大值
#include <stdio.h>
int max(int x,int y)
{
    return x > y ? x : y;
}
int add(int x,int y)
{
    return x+y;
}
int main(int argc,char *argv[])
{
    int a,b,c;
    printf("请输入两个数:");
    scanf("%d%d",&a,&b);
    printf("%d\n",max(a,b));//函数实参
//  c = max(a,b);//函数表达式
//  printf("%d\n",c);//函数语句
    c = max(a,add(a,b));
    printf("%d\n",c);//函数语句
    return 0;
}
//函数调用-简易计算器
#if 0
#include <stdio.h>
void add(float x,float y)
{
    printf("x+y = %.2f\n",x+y);
}
void sub(float x,float y)
{
    printf("x-y = %.2f\n",x-y);
}
void mul(float x,float y)
{
    printf("x*y = %.2f\n",x*y);
}
void div(float x,float y)
{
    printf("x/y = %.2f\n",x/y);
}
int main(int argc,char *argv[])
{
    float a,b;
    char c;
    printf("请输算式:");
    scanf("%f%c%f",&a,&c,&b);
    switch(c)   
    {
        case '+':add(a,b);break;
        case '-':sub(a,b);break;
        case '*':mul(a,b);break;
        case '/':div(a,b);break;
        default:printf("input error !\n");
    }
    return 0;
}
#else
#include <stdio.h>
float add(float x,float y)
{
    return x+y;
}
float sub(float x,float y)
{
    return x-y;
}
float mul(float x,float y)
{
    return x*y;
}
float div(float x,float y)
{
    return x/y;
}
int main(int argc,char *argv[])
{
    float a,b,c;
    char d;
    printf("请输算式:");
    scanf("%f%c%f",&a,&d,&b);
    switch(d)   
    {
        case '+':c = add(a,b);break;
        case '-':c = sub(a,b);break;
        case '*':c = mul(a,b);break;
        case '/':c = div(a,b);break;
        default:printf("input error !\n");
    }
    printf("%.2f\n",c);
    return 0;
}
#endif
//函数调用
#include <stdio.h>
void hello()
{
    printf("hello word\n");
}
void add1()
{
    int a,b;
    printf("请输入a和b的值:");
    scanf("%d%d",&a,&b);
    printf("%d\n",a+b);
}
void add2(int a,int b)
{
    int c = a+b;
    printf("%d\n",c);
}
int add3()
{
    int a,b;
    printf("请输入a和b的值:");
    scanf("%d%d",&a,&b);
    return a+b;
}
int add4(int a,int b)
{
    return a+b;
}
int main(int argc,char *argv[])
{
    hello();
    add2(12,46);

    return 0;
}
//斐波那契数列
#include <stdio.h>
int main()
{
    int n;
    int b[20];
    b[1] = 1;b[2] = 1;
    for(n = 3;n <= 20;n++)
    {
        b[n] = b[n - 1]+b[n - 2];
    }
    for(n = 1;n <= 20;n++)
    {
        printf("%d\n",b[n]);
    }
    return 0;
}

1、什么是函数,为什么要使用函数?
函数是完成特定任务的独立代码单元;
降低复杂性,避免重复代码段,限制了改动带来的影响,隐含顺序,改进性能,
进行集中控制,隐含数据结构,隐含指针操作,隐含全局变量。
2、C语言函数的几种分类
从函数定义角度分类:库函数(#include<stdio.h>) 用户自定义函数(#include "add.h")
按有无返回值分类: 有返回值函数和无返回值函数
从主调函数和被调函数之间数据传送的角度分类:有参函数和无参函数
库函数从功能的角度分类:字符型分类函数、转换函数、目录路径函数、诊断函数、图形函数、输入输出函数、接口函数、字符串函数、内存管理函数、数学函数、日期和时间函数、进程控制函数等。

3、函数定义的一般形式
1、无参函数的定义形式
类型标识符 函数名()
{
声明部分
语句
}

 例、void Hello()
 {
 printf("hello world\n");
 }

2、有参函数的定义形式
类型标识符 函数名(形式参数列表)
{
声明部分
语句
}

例、int max(int a,int b,int c)    //max 是一个整型函数,返回值是一个整数,形参a、b均为整型量。
 {
 int maxx=0;
 if (a>b)
 maxx=a;
 else
 maxx=b;

 if (max>c)
 return maxx;
 else
 return c;
 }

 我们可以直接在main函数中调用以上两个函数

 int main(int argc, char const *argv[])
 {
 int m=4,n=5,c=6;
 int d=0;
 d=max(m,n,c)
 printf("%d\n",d);
 return 0;
 }

4、形式参数和实际参数
1、形参出现在函数定义中,在整个函数体内都可以使用,离开该函数则不能使用(如31行中的,a、b);
2、实参出现在主调函数中,进入被调函数中也不能使用(如43行的m、n),实参可以是常量、变量、表达式、函数等,
3、在进行函数调用时,都必须具有确定的值,以便把值传给形参;
4、实参和形参在数量上、类型上、顺序上应严格一致,否则会报错(类型不匹配)
5、函数调用中发生的数据传送是单向的,只能把实参的值传送给形参,在函数调用过程中,形参的值发生改变,实参的值不改变

例、
#include <stdio.h>
void text(int n ); //函数的声明
void text(int n)       //函数的定义
{
int i;
for (i = n-1; i > 0; i--)
{
n=n+i;
}
printf("函数中的n=%d\n",n);
}

int    main(int argc, char const *argv[])
{
int n;
printf("请输入一个数:");
scanf("%d",&n);
text(n);           //函数的调用
printf("原来的n=%d\n",n);
return 0;
}

5、函数的返回值
函数的返回值只能通过return语句返回主调函数
return 语句的一般形式为:
return 表达式;或 return (表达式);
1、该语句的功能是计算表达式的值,并返回给主调函数,函数中允许多个return语句,但是每次调用函数只能有一个return语句
被执行,每次调用只能有一个返回值。
2、函数值的类型和函数定义中的函数类型应该保持一致,如果不一致,以函数类型为准
3、无返回值的函数,可以明确定义为"空类型",类型说明符为"void"

6、函数的调用
在程序中是通过对函数的调用来执行函数体的
C语言中函数调用的一般形式
函数名 (实际参数表) //无参函数则无实际参数,如果有多个参数则用逗号隔开
函数调用的几种方式:
1、函数表达式:z=max(x,y);//一个赋值表达式,函数作为表达式的一项出现,这种方式要求函数是有返回值的
2、函数语句:printf("%d",a);scanf("%d",&b);//函数调用的一般形式加上分号构成语句;
3、函数实参:printf("%d\n",max(x,y)); 函数作为另一个函数调用的实际参数出现;

计算数组元素的和
int sum(int *a,int n)
{
int sum=0;
int i;
for (i = 0; i < n; ++i)
{
sum+=a[i];
}
return sum;
}

int main(int argc, char const *argv[])
{
int a[10]={1,2,3,4,5,6,7,8,9,10};
int s=0;
s=sum(a,10);
printf("累加结果为:%d\n",s );
return 0;
}
 交换两个数的值
 void swap(int x,int y)
 {
 int t=0;
 t=x;
 x=y;
 y=t;
 // printf("在函数中x=%d,y=%d\n",x,y);
 }
 void swap2(int *x,int *y)
 {
 int t=0;
 t=*x;
 *x=*y;
 *y=t;
 }
 int main(int argc, char const *argv[])
 {
 int a=3,b=8;
 int *p,*q;
 p=&a;
 q=&b;
 printf("交换前a=%d,b=%d\n",a,b);
 swap(a,b);
 swap2(p,q);
 printf("交换后a=%d,b=%d\n",a,b );
 return 0;
 }
 int main(int argc, char const *argv[])
 {
 int x=3,y=5,t=0;
 printf("交换前x=%d,y=%d\n",x,y );
 t=x;
 x=y;
 y=t;
 printf("交换后x=%d,y=%d\n",x,y );
 return 0;
 }

被调函数的声明和函数原型:
在主调函数中调用某函数之前应对该被调函数进行声明,这于使用变量之前对变量进行变量说明是一样的。目的是使辨析系统知道 被调函数的返回值类型。
其一般形式为
类型说明符 被调函数名(类型 形参,类型 形参,......);
或者
类型说明符 被调函数名(类型,类型.........);

C语言中规定以下几种情况可以省去声明;
1:被调函数的返回值是整型或字符型,可以不对被调函数声明;
2:被调函数声明在主调函数之前
3:在所有函数之前预先说明了各个函数的类型
4:对库函数的调用不需要再做说明,但是必须把该函数的头文件用include命令包含。

函数的嵌套调用:
C语言不允许嵌套定义函数,但是允许在一个函数的定义中出现另一个函数。这样就出现了函数函数嵌套调用。
计算 s=(22)!+(33)!

函数的递归调用:
一个函数在它的主体中调用他的自身称为递归调用。这种函数称为递归函数。
执行的过程中将反复调用自身,每调用一次都进入新的一层。

int f(int x)
{
    int y;
    z=f(y);
    return z;
}

这是一个递归函数,但是运行该函数将无休止的调用其自身。
为了防止递归函数无休止的进行,必须在函数内有终止递归的手段,常用的方法是加条件判断,满足条件之后就不再递归逐层退出。

long jiecheng(int n)
{
    long ret = -1;
    if(n<0)
        printf("n<0,input error\n");
    else if(n==0||n==1)
        ret = 1;
    else
        ret = jiecheng(n-1)*n;
}
int main()
{
    int n;
    long y;
    printf("input a intrager number:\n");
    scanf("%d",&n);
    y=jicheng(n);
    printf("%d!=%ld\n",n,y);
    return 0;
}

数组作为函数的参数
数组可以作为函数的参数使用,进行数据传送。数组作为函数参数有两种形式,一种是把数组元素作为实参使用;另一种是把数组名作为函数的形参和实参使用。
判断一个整型数组中个元素的值,如果大于0,则输出该值,否则输出0,
1:数组元素作为实际参数时,数组元素的类型和函数形参的类型保持一致,这时数组元素是一个普通变量。
数组名作为函数参数时,要求形参和实参都必须是类型相同的。
2:数组元素做函数参数时,形参和实参是由编译器分配的两个不同的内存单元,在函数调用时发生的值传递是把实参变量赋予形参变量。
在用数组名做函数参数时,不是进行值传送,即不是把参数组的每一个元素的值都赋予形参组的各个元素。因为实际形参数组并不存在,编译数组并不为形参数组分配内存。数组名就是数组的首地址,。数组做函数参数时说进行的传送只是地址的传送,也就是说把实参数组的首地址赋给形参数组名,形参数组名取得改首地址后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有一段空间。

局部变量和全局变量:形参只有在被调用期间才被分配单元,调用结束立即释放,形参只有在函数内才是有效的,离开函数之后不能在继续使用。这种变量有效性的范围称为变量的作用域。

C语言中的变量按照其作用域范围可分为局部变量和全局变量。
局部变量也称为内部变量,局部变量是在函数内定义的,其作用域仅限于函数内,离开该函数后再使用这种变量是非法的。
注意:
1:主函数中定义的变量也只能在主函数中使用
2:形参变量是属于被调函数的局部变量,实参变量属于主调函数
3:允许在不同的函数中使用相同的变量名;
4:在复合语句中定义的变量,作用域仅限于复合语句中。

全局变量也称为外部变量,它是在函数外部定义的;他不从属于哪个函数,他属于一个程序源文件。其作用域是整个源程序。

局部变量会屏蔽全局变量。

变量的存储类别:
动态存储方式与静态存储方式
从变量值的生存期来划分可分为,静态存储方式和动态存储方式。
静态存储方式是指在程序运行期间分配固定的存储空间的方式。
动态存储方式是在程序运行期间根据需要进行动态分配存储空间的方式。
用户存储空间可以分为三部分:
(1)程序区
(2)静态数据区
(3)动态数据区
全局变量存储在静态数据区,程序开始时分配,结束时释放,占据固定单元。
动态存储区存放以下数据:
函数形参,
自动变量(未加static修饰的局部变量),
函数调用的现场保护和返回地址。

static声明局部变量
有时希望函数中的局部变量的值在函数调用后不消失而保留原值,这使就指定局部变量为“静态局部变量”,用关键字static声明。

对静态局部变量的说明:
局部变量属于静态存储类别,在静态存储区内分配单元,整个程序运行期间都不释放。
静态局部变量在编译时赋值,只赋值一次;
不赋初值的话,编译器默认符0;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容