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

  • C第六天

老师早上过来就带着我们回顾了昨天学的指针,问题还真不是一般的大,主要因素是我们连最基础的内容都没记住,做了几个练习巩固之后老师就开始给我们讲函数,也讲到了递归,并且留了一道要求以递归方法解答的题目。原本就不熟练的指针现在又加上函数,难度真不是一般的大,搞得头都大了。

#include <stdio.h>
void main()
{
    int a[4][5]={{1,2,3,4,5},
            {6,7,8,9,10},
            {11,12,13,14,15},
            {16,17,18}};
    printf("a=%p\n&a[0][0]=%p\n&a[1][0]=%p\na+1=%p\n",a,&a[0][0],&a[1][0],a+1);
    int (*p)[5]=a;//p == a
    printf("p=%p\np+1=%p\n",p,p+1);
    printf("*p=%p\n*p+1=%p\n&a[0][0]=%p\n&a[0][1]=%p\n*a=%p\n*a+1=%p\n",*p,*p+1,&a[0][0],&a[0][1],*a,*a+1);
    printf("**a=%d\n*(*a+1)=%d\n",**a,*(*a+1));
    printf("&*a=%p\n&*a+1=%p\n",&*a,&*a+1);
}
/*
a:数组名a表示数组的首元素的地址,作为一个指针,指向的对象是数组的元素,当a+1时,指针跨过一个所指向对象的长度,一维int数组的元素是单个的int型值,二维数组的元素是它的每一行。不过二维数组中a表示首行的地址,指向第一行第一个元素的位置,a+1表示第二行的地址,表示指向第二行第一个元素的位置。
4.二维数组名a表示一个行指针,指向的对象第一行,指针停留的位置是第一行的第一个元素。加颗"*",可以让一个行指针变成列指针,即*a,变成了指向一列的指针,指向第一列,*a+1指向第二列,即第一行的第二个元素
5.一个列指针前面加颗"*",如**a,就表示成这个列指针所指向对象的值,即第一行第一列的元素的值。int a[5],一维数组名a就可以看做是一个列指针,a+1偏过一个元素即一列,加颗"*"即得到了指向的元素的值。
6.一个列指针前面加个"&"就变回为行指针。
  int a[5], a:指向数组中每个元素(列),
        &a:指向整个数组(行)
*/

函数:把一些能够实现一定功能的指令封装成一个指令集,即模块,当需要使用这些指令的时候,直接通过调用该模块的名字就能够实现。

例:
#include <stdio.h>
void Print()
{
    printf("xxx\n");
}
void main()
{
    Print();
}

函数的定义:
格式:

函数的返回值类型  函数名(函数参数类型 参数名1,参数类型 参数名2 ...)
{
    语句;
}

例:

void Print(int a,int b)
{
    printf("a:%d b:%d\n",a,b);
}

注:1.函数如果没有返回一个值出去,那么在定义函数的时候,函数的返回值类型就是void ,如果有返回值,返回值通过return 抛出去,返回的值是什么类型,在定义函数的时候函数返回值类型就写相应的类型。

#include <stdio.h>
//定义一个函数,没有返回值,不带参数的函数
void Func()
{
    printf("xxx\n");
}
void main()
{
    Func();//函数的调用
}
//定义一个函数,有返回值的
int Func()//函数返回的值是什么类型,就写什么类型
{
    int a=5;
    printf("a=%d\n",a);
    return a;
}
void main()
{
    int b=0;
    b=Func();
    printf("b=%d\n",b);
}
//定义一个函数,有参数传入,有返回值输出
int Func(int a,int b)
{
    printf("a=%d b=%d\n",a,b);
    return 1;
}
void main()
{
    int c=1,d=2,e;
    e=Func(c,d);//   int a=c, int b=d;
    printf("e=%d\n",e);
}
/*
注:1.通常取的函数名字第一个字符大写.
    2.定义函数的时候函数如果有返回值,返回什么类型的值,函数返回值类型就写什么,如果没有返回值,就写void,在函数里面可以不写return,也可以只写一个return.
    3.定义函数的时候函数的参数列表中各参数用逗号分割,原则上可以有无限个参数,但通常不要超过3个。
    4.函数可以没有返回值,但是最多只能返回一个值。
*/

函数必须先定义再使用,如果使用在定义的前面,那么就必须在使用之前先声明函数的存在。
声明语句:直接把函数定义的第一句话抄过去就可以,记得加个分号";" .

#include <stdio.h>
/*void Func();
void main()
{
    Func();
}
void Func()
{
    printf("xxx\n");
}*/
//函数的声明
int Func(int a,int b);
//int Func(int,int); 声明的时候参数名可以不写
void main()
{
    //函数的调用
    int c=Func(1,2);//int a=1,int b=2
    printf("c=%d\n",c);
}
//函数的定义
int Func(int a,int b)
{
    printf("a=%d b=%d\n",a,b);
    return a;
}

1.怎么向一个函数传递一个变量的地址。

#include <stdio.h>
void Func(int *p)
{
    printf("*p=%d\n",*p);
}
void main()
{
    int a=5;
    Func(&a);//int *p=&a
}

2.怎么向一个函数传一个数组进去。

a.
#include <stdio.h>
void Func(int *p)
{
    printf("%d %d %d %d %d\n",p[0],p[1],p[2],p[3],p[4]);
}
void main()
{
    int a[5]={1,2,3,4,5};
    Func(a);//int *p=a;  p<=>a
}
b.
#include <stdio.h>
void Func(int p[])
{
    printf("%d %d %d %d %d\n",p[0],p[1],p[2],p[3],p[4]);
}
void main()
{
    int a[5]={1,2,3,4,5};
    Func(a);//int *p=a;  p<=>a
}

练习:在主函数中定义2个变量int a=3,b=5.再定义一个子函数,在这个子函数中实现a,b的值交换,并在主函数中调用这个子函数。然后在主函数中输出交换后a,b的值。

#include <stdio.h>
/*  错误写法
void Swap(int x,int y)
{
    int temp;
    temp=x;
    x=y;
    y=temp;
}
void main()
{
    int a=3,b=5;
    Swap(a,b);//int x=a, int y=b;
    printf("a:%d b:%d\n",a,b);
}
*/
void Swap(int *x,int *y)
{
    int temp;
    temp=*x;
    *x=*y;
    *y=temp;
}
void main()
{
    int a=3,b=5;
    Swap(&a,&b);//int *x=&a,int *y=&b;
    printf("a=%d b=%d\n",a,b);
}
//赋值的过程,只是一个值的拷贝

练习:寻找2个数组中的各自的最大值,并实现值的交换,并输出交换后的数组。
例: 1 2 3 4 10
7 8 9 5

#include <stdio.h>
int Find(int *a,int n)
{
    int *p;
    int *max=a;
    for(p=a;p<a+n;p++)
    {
        if(*max<*p)
            max=p;
    }
    return max-a;
}
void Swap(int *x,int *y)
{
    int temp;
    temp=*x;
    *x=*y;
    *y=temp;
}
void main()
{
    //1.分别给2个数组赋值
    int a[10],b[5],*p;
    printf("please input 10 data:");
    for(p=a;p<a+10;p++)
        scanf("%d",p);
    //for(i=0;i<10;i++)
    //  scanf("%d",&a[i]);
    printf("please input 5 data:");
    for(p=b;p<b+5;p++)
        scanf("%d",p);
    //2.找出各自数组中最大值的下标并返回出来
        int i=Find(a,10);
        int j=Find(b,5);
    //交换对应下标号的元素
    Swap(&a[i],&b[j]);
    //输出交换后的2数组
    for(p=a;p<a+10;p++)
        printf("%d ",*p);
    printf("\n");
    for(p=b;p<b+5;p++)
        printf("%d ",*p);
    printf("\n");
}

练习:利用指针,将一个整型数组逆序存放
例: a[0] a[1] a[2] a[3] a[4] a[5]
1 2 3 4 5 6
6 5 4 3 2 1

#include <stdio.h>
void  Inverse(int *a,int n)
{
    int *p,*q,t;
    for(p=a,q=a+n-1;p<q;p++,q--)
    {
        t=*p;
        *p=*q;
        *q=t;
    }
}
void main()
{
    int i,a[10]={1,2,3,4,5,6,7,8,9,10};
    Inverse(a,10);
    for(i=0;i<10;i++)
        printf("%d ",a[i]);
    printf("\n");
}

求任何一个数的阶乘

例:6!
int r=func(6);
func(6)==6*func(5)==6*5*func(4)==6*5*4*func(3)
==6*5*4*3*func(2)==6*5*4*3*2*func(1)
                 ==6*5*4*3*2*1*func(0)
                 ==6*5*4*3*2*1*1==!!!==r
#include <stdio.h>
int Func(int n)
{
    if(n==0)
        return 1;
    else
        return n*Func(n-1);
        //return n*(n-1)*(n-2)*...*func(0)
}
void main()
{
    printf("pleaes input a data:");
    int n;
    scanf("%d",&n);
    int r=Func(n);
    printf("r=%d\n",r);
}
/*
递归函数:自己调用自己的函数。
return的作用:结束当前函数的执行,返回上一层函数继续执行。
*/

练习:有5个小孩坐在一起,问第五个人多少岁,他说,比第四个人大2岁,问第四个人多少岁,他说,比第三个人大2岁,问第三个人多少岁,他说,比第二个人大2岁,问第二个人多少岁,他说,比第一个人大2岁,,问第一个人多少岁,他说,我10岁。
求第5个人多少岁。用递归来做。

#include <stdio.h>
int Age(int n)
{
    if(n==1)
        return 10;
    else
        return Age(n-1)+2;
}
void main()
{
    printf("%d\n",Age(5));
}

*homework:利用递归逆序输出一个字符串。
“abcdefg”
=>gfedcba *

推荐阅读更多精彩内容