C语言基础知识之四

递归

C语言的特点之一就是允许函数的递归调用。
递归前进段,使问题不断缩小。
但栈的空间有限,递归消耗内存大
(1)递归法求斐波那契,引用递归最失败的例子,可能会导致栈溢出

int Fabonacci(int n)
{
    int f1=1;
    int f2=2;
    int f3=1;
    if(n==0||n==1)
    {
        return 1;
    }
    return Fabonacci(n-1)+Fabonacci(n-2);//1.递归
    //2.循环法
        //for(int i=2;i<n;i++)
        //{
        //  f3=f1+f2;
        //  f1=f2;
        //  f2=f3;
        //}
        //return f3;
}
int main()
{
    printf("%d ",Fabonacci(4));
    return 0;
}

(2)汉诺塔问题

int count=0;//全局变量
void Move(char x,char y)
{
    printf("%c->%c\n",x,y);
    count++;
}
void Hanio(int n,char a,char b,char c)
{
    if(n==1)
    {
        Move(a,c);
    }
    else
    {
        Hanio(n-1,a,c,b);//把n-1个盘子从a通过c全部挪到b上
        Move(a,c);//把a上最后一个盘子挪到c上
        Hanio(n-1,b,a,c);//***
    }
}

int main()
{
    Hanio(5,'A','B','C');
    printf("%d\n",count);//输出移动的次数
    return 0;
}

尾递归转为非递归,如上面斐波那契数列中递归法转为循环法

内存的动态分配

1.malloc
原型:void * malloc(unsigned int size);
注:形参size的类型定为无符号整型(不允许为负数),此函数返回的指针指向该分配域的开头位置。
若内存空间不足,则返回空指针NULL
例:int * arr=(int *)malloc(n * sizeof(int));
2.calloc
原型:void * calloc(unsigned n,unsigned size);
用calloc函数可以为一维数组开辟动态存储空间,n为数组元素的个数,size为每个元素的长度。
注:n与size的位置可互换,并且每一个元素自动初始化为0.
例:int * p=(int *)calloc(10,sizeof(int));
3.free
原型:void free(void *p);
作用是释放指针变量p所指向的动态空间,使这部分空间能被其他变量使用。p应该是最近一次调用calloc或malloc函数时得到的返回值。
注:如果没有释放内存,则会发生内存泄露,释放内存时会找首位置所包含的信息,来确定所要释放内存空间的大小。
例:free(p);
(1)内存泄露被回收的三种情况:程序退出、重启、关机,此时所有内存都会被回收。
(2)free的崩溃问题:
a.数组越界(篡改尾数据)
如:

void Fun(int *arr)
{
     int * arr=(int *) malloc(10*sizeof(int));

    for(int i=0;i<=10;i++)
    {
        arr[i]=0;
        printf("%d ",arr[i]);
    }
        //free(arr);

}

如果没有free,只是单纯的打印arr的值,C语言不会检查自己是否越界。因为越界的地址暂时没有用到,如果越界的地址被已内存占用,而再使用的话,程序就会崩溃。
加上free之后,运行程序程序会崩溃。
b.移动了指针
如:

int * p=(int * )malloc(10*sizeof(int));
       ......
       p++;

malloc函数的返回值才可以用来释放内存,p移动之后p的值已经不是申请的地址的返回值了,所以free会崩溃
c.重复释放内存

free(p);  //1.
free(p);  //2.此时的p是野指针

free 释放函数时,实际是malloc给指针一个合法的地址,并且该地址指向一个合法的内存空间。free之后,这部分内存空间可以重新被其他变量使用,但free后的指针仍然存在,其值还是刚刚分配的内存空间的地址,并不是0(NULL).因此上面free 1.并不能使p置NULL,而需要手动设置p=NULL
4.realloc
原型:void * realloc(void * p,unsigned int size);
可以同realloc改变内存空间的大小,进行重新分配。【一般对内存紧缩,即改小内存没有用】
例:p=(int * )realloc(p,20*sizeof(int));
等价于:

int * q=(int * )malloc(20*sizeof(int));//申请20个内存单元
for(int i=0;i<10;i++)
{
     q[i]=p[i];//把p的内容搬到q
}
free(p);//释放10单元内存的变量p
p=q;//更新q的地址依旧为p
p=NULL;//使p为空(NULL)
free(q);//即free(NULL);

判断一个字符是否是字母,数字,不用字符函数和字符串函数,不用字符集

1.判断一个字符是否是16进制数

#include<stdio.h>
#include<string.h>
bool Myisxdigit(char ch);
{
  char chars[]="0123456789abcdefABCDEF";
  for(int i=0;i<strlen(chars);i++)
  {
    if(ch == chars[i])
     {
        return true;
     }
  }
  return false;
}

int main()
{
 if(Myisxdigit(r))
  {
    printf("true");
  }
 else
  {
    printf("false");
  }
return 0;
}

2.判断一个字符是否是字母

bool Myisalpha(char ch);
{
char chars[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for(int i=0;i<strlen(chars))
 {
   if(ch == char[i])
     {
        return true;
     }
 }
     return false;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值