10.18学习记录

一.函数

1.函数的组成

2.关于GET_MAX()和swap()的区别

第一个函数不需要改变实参,所以不需要传地址,只要返回就行

而第二个函数需要通过地址指针建立实参和形参的联系,在调用函数里通过形参改变实参的值.

举例

1.GET_MAX()

get_max(int x, int y)
{
return(x > y ? x : y);//嵌套访问.
}
int main()//写一个函数求最大值
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("%d\n", get_max(a, b));
return 0;
}

2.SWAP()

错误做法

a和b的值传给了x和y

形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。

所以a和b的值没有变化

正确:

void swap1(int x,int y)
{
int tmp = x;
x = y;
y = tmp;
}
int main()//写一个函数交换a与b的值
{
int a = 10;
int b = 20;
printf("%d %d\n", a, b);
swap1(a, b);
printf("%d %d\n",a,b);
return 0;
}

pa接收了a的地址,他的内存块是a的地址,对pa解引用就是直接通过pa指针找到a的地址,对a进行操作

 void swap2(int *pa,int *pb)//地址传过来用指针接收
{
int tmp = *pa;//解引用操作符,实际对a本身操作
*pa = *pb;
*pb = tmp;
}
int main()
{
int a = 10;
int b = 20;
printf("%d %d\n", a, b);
swap2(&a, &b);//只有传输地址才可以真正改变实参
printf("%d %d\n", a, b);
return 0;
}

只有传输地址才可以真正改变实参

3.函数的参数

1 实际参数(实参):

无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形

参。

2 形式参数(形参):

形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内

存单

这里可以看到 Swap1 函数在调用的时候, x , y 拥有自己的空间,同时拥有了和实参一模一样的内容。

所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝。

4. 函数的调用:

4.1 传值调用

函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。

4.2 传址调用

传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。

这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操

作函数外部的变量。

4.3数组的传地址

数组在传参的时候,传递不是整个数组

// //传递是数组首元素的地址

int binary_search(int arr, int k)//数组在传参的时候,传递不是整个数组
传递是数组首元素的地址
{
int left = 0;
int right = sizeof(arr) / sizeof(arr[0])-1;
while(left <= right)
{
int mid = left + (right - left) / 2;
if (arr[mid] == k)
{
return mid;
     }
else if (arr[mid] > k)
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
return -1;
}
int main()//写一个函数,实现一个整形有序数组的二分查找。错误示范
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 0;
scanf("%d", &k);
int a=binary_search(arr, k);
if (-1 == a)
{
printf("没找到\n");
}
else
{
printf("下标是%d", a);
}

}

正确

int binary_search(int arr[], int k, int sz)//数组在传参的时候,传递不是整个数组
传递是数组首元素的地址
{
    int left = 0;
    int right = sz - 1;
    while (left <= right)
    {
        int mid = left + (right - left) / 2;
        if (arr[mid] == k)
        {
            return mid;
        }
        else if (arr[mid] > k)
        {
            right = mid - 1;
        }
        else
        {
            left = mid + 1;
        }
    }
    return -1;
}
int main()//写一个函数,实现一个整形有序数组的二分查找。正确示范
{
    int arr[] = {1,2,3,4,5,6,7,8,9,10 };
    int k = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    scanf("%d", &k);
    int a = binary_search(arr, k,sz);
    if (-1 == a)
    {
        printf("没找到\n");
    }
    else
    {
        printf("下标是%d", a);
    }
    return 0;
}

5. 函数的嵌套调用和链式访问

函数可以嵌套调用,但是不能嵌套定义。

5.2 链式访问

把一个函数的返回值作为另外一个函数的参数。

注:printf函数的返回值是打印在屏幕上字符的个数

int binary_search(int arr[], int k, int sz)//数组在传参的时候,传递不是整个数组
传递是数组首元素的地址
{
    int left = 0;
    int right = sz - 1;
    while (left <= right)
    {
        int mid = left + (right - left) / 2;
        if (arr[mid] == k)
        {
            return mid;
        }
        else if (arr[mid] > k)
        {
            right = mid - 1;
        }
        else
        {
            left = mid + 1;
        }
    }
    return -1;
}
int main()//写一个函数,实现一个整形有序数组的二分查找。正确示范
{
    int arr[] = {1,2,3,4,5,6,7,8,9,10 };
    int k = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    scanf("%d", &k);
    int a = binary_search(arr, k,sz);
    if (-1 == a)
    {
        printf("没找到\n");
    }
    else
    {
        printf("下标是%d", a);
    }
    return 0;
}

6.学会创建和引用静态库

1.创建份文件

第一步.分文件 .c

函数主体

第二步,头文件 .h

函数声明

第三步,主函数引用

#include"add.h"
int main()//创造份文件
{
int a = 0;
int b = 1;
printf("%d",add(a,b));
return 0;
}

2.创造静态库并学会引用

可以使用但是看不到源码

第一步在另一个项目创建函数(要有头文件和源文件的函数)

第二步变成静态库

第三步.找到.lib文件和.h文件并复制到需要的项目路径中

第四步,导入静态库并引入头文件

8.递归函数

1 什么是递归?

程序调用自身的编程技巧称为递归( recursion)。

递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接

调用自身的

一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,

递归策略

只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。

2 递归的两个必要条件

存在限制条件,当满足这个限制条件的时候,递归便不再继续。

每次递归调用之后越来越接近这个限制条件

3.练习

1.接受一个整型值(无符号),按照顺序打印它的每一位。

例如:

输入:1234,输出 1 2 3 4

void print(int a)
{
printf("%d", a % 10);
if (a > 9)
{
print(a / 10);//12
}
}
int main()//接受一个整型值(无符号),按照顺序打印它的每一位。
{
unsigned int n = 0;
scanf("%d", &n);
print(n);
return 0;
}

编写函数不允许创建临时变量,求字符串的长度。

int  my_strlen(char* ch)//因为元素是字符,所以用字符指针接收
{

if ((*ch) == '\0')
return 0;
else
return 1 + my_strlen(ch + 1);
}
int main()//编写函数不允许创建临时变量.求字符串长度
{
char ch[] = "abcd";
int str= * ch;
int len = my_strlen(ch);//数组传给函数的时候是第一个元素的地址
printf("%d", len);
return 0;
}

练习3.求 n的阶乘

int factorial(int n)
{
 if(n <= 1)
 return 1;
 else
 return n * factorial(n-1);
}

练习4.求斐波那契数列

int fib(int n)
{
 if (n <= 2)         
 return 1;
    else
    return fib(n - 1) + fib(n - 2);
}

注意.会重复计算

设一个全局变量count

所以用递归的方式可能会栈溢出  stack overflow

int fib(int n)
{
int x = 2;
int a = 1;
int b = 1;
int c = 1;
while (x < n)//3
{
c = a + b;//2//3
a = b;//1//2
b = c;//2
x++;//2
}
return c;
}

(8条消息) 汉诺塔——经典递归问题(c语言实现)_小钟hhh的博客-CSDN博客_汉诺塔递归算法c语言

(8条消息) 详解青蛙跳台阶的递归问题_RanieMiss的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值