C语言基础(函数篇)

函数

定义: 一个可以完成特定功能的代码模块

三要素: 功能、参数、返回值

定义格式

存储类型 数据类型 函数名(参数列表) // 形参

{

        函数体; // 功能

        return 返回值; // 返回值

}

函数调用

1) 没有返回值:直接调用:函数名(参数列表) // 实参

2) 有返回值:如果需要接收返回值,就要定义一个与返回值类型相同的变量接收,如果不需要接收返回值,就可以直接调用函数

函数特点

函数不调用不执行,函数调用多次就会执行多次

定义函数时会出现以下几种情况

1)有参数:函数名后的小括号需要按照定义变量的方式定义参数,调用时函数名后的小括号也要传递相应个数和类型的参数

2)没有参数:参数列表可以省略,也可以用 void,调用时也不需要写参数

3)有返回值:要根据返回值的数据类型定义函数的数据类型,在函数体内部 return 返回值

4)没有返回值:数据类型为 void,函数内部没有 return 返回值

5)定义子函数时可以直接定义在主函数的上面,如果定义在主函数下面需要提前声明函数

声明函数: 数据类型 函数名(参数列表); // 形参

参数的分类

形参:定义函数时写在小括号内的参数,用来接收实参的传值

实参:函数调用时写在小括号的内容,用来给形参传递值

注意:形参的个数与实参的个数一一对应(数据类型也要对应)

函数的传参

值传递

单向传递(实参--->形参)修改形参的值 实参不会发生变化

地址传递

双向传递 修改形参的值 实参会发生变化

地址传递本质是一个值传递

#include <stdio.h>
int fun(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
int main(int argc, char const *argv[])
{
    int a = 10, b = 20;
    fun(&a, &b);
    printf("%d %d\n", a, b);
    return 0;
}
数组传递

数组传参传递的为数组首元素的地址

数组中各元素在内存中连续存放

#include<stdio.h>
void fun(int *p,int n)
{
    for(int i=0;i<n;i++)
    {
        printf("%d ",p[i]);
    }
    printf("\n");
}
int main(int argc, char const *argv[])
{
    int arr[3]={1,2,3};
    fun(arr,3);
    return 0;
}

开辟堆区空间(动态内存开辟)

为什么存在动态内存开辟

<1>在技术方面,普通的空间申请,都是在全局或者栈区,全局一般不太建议大量使用,而栈空间有限,那么如果一个应用需要大量的内存空间的时候,需要通过申请堆空间来支持基本业务。

<2>在应用方面,程序员很难一次预估好自己总共需要花费多大的空间。想想之前我们定义的所有数组,因为其语法约束,我们必须得明确"指出"空间大小.但是如果用动态内存申请(malloc)因为 malloc 是函数,而函数就可以传参,也就意味着,我们可以通过具体的情况,对需要的内存大小进行动态计算,进而在传参申请,提供了很大的灵活性。

需要手动开辟空间,手动释放、如果只开辟不释放,所用的空间会越来越少

开辟 (malloc)

#include <stdlib.h>

void *malloc(size_t size);

功能:在堆区开辟空间

参数:size:开辟空间的大小(单位:字节)

返回值: 成功:返回开辟空间的首地址

失败:NULL // 为什么出现开辟失败,它没有足够大的空间了

释放 (free)

#include <stdlib.h>

void free(void *ptr);

功能:释放堆区空间

参数:ptr:堆区空间的首地址

返回值:无

#include<stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
    // 可以这么开辟 malloc(40);
    // 也可以这么开辟 malloc(size(int)*10);
    int *p = (int *)malloc(sizeof(int) * 10);
    if (p == NULL)
    {
        printf("开辟失败!\n");
        return -1;
    }
    printf("开辟成功!\n");
    // 在此去书写一些功能
    for (int i = 0; i < 9; i++)
    {
        scanf("%d", &p[i]);
    }
    for (int i = 0; i < 9; i++)
    {
        printf("%d\n", p[i]);
    }
    // 空间使用完成之后,记得释放
    free(p);
    p = NULL;
    return 0;
}

注意:

  • 手动开辟堆区空间,要注意内存泄漏
  • 使用完堆区空间后要及时释放空间 指针要及时置空

string 函数族

strcpy

#include <string.h>

char *strcpy(char *dest, const char *src);

功能:实现字符串复制

参数:char *dest:目标字符串首地址

const char *src:原字符串首地址

返回值:目标字符串首地址

#include <stdio.h> 
#include <string.h> 
int main(int argc, char const *argv[]) 
{ 
    char s[32] = "hello"; 
    char c[32] = "world"; 
    strcpy(s, c); // 将 c 复制到 s 里面
    printf("%s\n", s); // world 
    return 0; 
} 
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    char s[32] = "hello";
    char c[32] = "wor";
    strcpy(s, c);      // 复制包括 \0
    printf("%s\n", s); // wor
    return 0;
}

#include <string.h>

char *strncpy(char *dest, const char *src, size_t n);

功能:实现字符串复制

参数:char *dest:目标字符串首地址

const char *src:原字符串首地址

size_t n:复制字符个数

返回值:目标字符串首地址

#include <stdio.h> 
#include <string.h> 
int main(int argc, char const *argv[]) 
{ 
    char s[32] = "hello"; 
    char c[32] = "world"; 
    strncpy(s, c, 3); // 这样就是把 wor 复制过去 
    printf("%s\n", s); // worlo 
    return 0; 
}

strlen

#include <string.h>

size_t strlen(const char *s);

功能:计算字符串的实际长度

参数:s:字符串首地址

返回值:字符串的实际长度

strcat

#include <string.h>

char *strcat(char *dest, const char *src); 将原字符串拼接到目标字符串的后面

功能:用于字符串拼接

参数:char *dest:目标字符串首地址

const char *src:原字符串首地址

返回值:目标字符串首地址

#include <stdio.h> 
#include <string.h> 
int main(int argc, char const *argv[]) 
{ 
    char s1[32] = "hello"; 
    char *s2 = "world"; 
    strcat(s1, s2); 
    printf("%s\n", s1); // helloworld 
    return 0; 
} 

char *strncat(char *dest, const char *src, size_t n); 拼接字符串的前 n 个字符

#include <stdio.h> 
#include <string.h> 
int main(int argc, char const *argv[]) 
{ 
    char s1[32] = "hello"; 
    char *s2 = "world"; 
    strncat(s1, s2, 3); 
    printf("%s\n", s1); // hellowor 
    return 0; 
} 

strcmp

#include <string.h>

int strcmp(const char *s1, const char *s2); 比较两个字符串字符的大小

功能:用于字符串比较

参数:s1、s2 是字符串首地址

返回值: 从字符串首个字符开始比较字符的 ASCII 的大小,如果相等继续向后判断

        正数 s1 > s2

          0    s1 == s2

        负数 s1 < s2

#include <stdio.h> 
#include <string.h> 
int main(int argc, char const *argv[]) 
{ 
char s1[] = "hello"; 
char s2[] = "helloworld"; 
char *s3 = "hqyj"; 
char *s4 = "nihaoshijie"; 
// int ret = strcmp(s1, s2); // s1 < s2 负数 
// int ret = strcmp(s1, s3); // s1 < s3 负数 
// int ret = strcmp(s2, s4); // s2 < s4 负数 
int ret = strcmp(s3, s2); // s3 > s2 正数 
printf("%d\n", ret); 
return 0; 
} 

int strncmp(const char *s1, const char *s2, size_t n); 比较两个字符串前 n 个字符的大小

一般它会用来判断字符串是否相等

if(!strcmp(s1, s2))

{

        printf("相等\n");

}

递归函数

定义:函数自己调用自己

执行过程:

递推阶段:从原问题出发,按递推公式从未知到已知,最终达到终止条件

回归阶段:按递归的终止条件求出结果,逆向逐步带入公式,回到原问题

#include <stdio.h>
void fun(int n)
{
    if (n > 9)
        fun(n / 10);
    printf("%d\n", n % 10);//1 2 3 4
}
int fun1(int m)
{
    if(m==1)
        return 1;
    return m*fun1(m-1);//5*4*3*2*1
}
int main(int argc, char const *argv[])
{
    fun(1234);
    printf("%d\n",fun1(5));//120
    return 0;
}

 函数编程练习

编写一个函数,返回一个字符串中某个字符出现的次数

#include <stdio.h>
void str(char *p, char c)
{
    int i = 0;
    while (*p)
    {
        if (*p == c)
        {
            i++;
        }
        p++;
    }
    printf("%c出现%d次\n", c, i);
}
int main(int argc, char const *argv[])
{
    char s[32], ch;
    printf("input str:\n");
    scanf("%s", s);
    printf("input ch:\n");
    scanf(" %c", &ch);
    str(s, ch);
    return 0;
}

 封装函数:找到数组中最大位置及其下标并输出

#include <stdio.h>
void fun(int s[], int t, int *k)
{
    int max = s[0];
    *k = 0;
    for (int i = 1; i < t; i++)
    {
        if (s[i] > max)
        {
            max = s[i];
            *k = i;
        }
    }
    
}
int main(int argc, char const *argv[])
{
    int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 0, 11}, k;
    fun(a, 10, &k);
    printf("%d %d\n", a[k], k);
    return 0;
}

封装函数:向数组的指定位置插入元素
参数:数组首地址,数组元素个数,插入元素下标,插入元素值

#include<stdio.h>
void insert(int *p,int n,int post,int data)
{
    int i=n;
    while(i>=post)
    {
        p[i]=p[i-1];
        i--;
    }
    p[post]=data;

}
int main(int argc, char const *argv[])
{
    int arr[]={1,2,3,4,5,6};
    int n=sizeof(arr)/sizeof(int);
    n++;
    insert(arr,n,3,10);
    for(int i=0;i<n;i++)
    {
        printf("%d ",arr[i]);
    }
    printf("\n");
    return 0;
}

封装函数:删除数组指定位置的元素
参数:数组的首地址,数组元素的个数,删除元素的下标

#include<stdio.h>
void delete(int *p,int n,int post)
{
    int i=0;
    while(i<n)
    {
        if(i>=post)
        {
            p[i]=p[i+1];
        }
        i++;
    }

}
int main(int argc, char const *argv[])
{
    int arr[]={1,2,3,4,5,6};
    int n=sizeof(arr)/sizeof(int);
    delete(arr,6,2);
    n--;
    for(int i=0;i<n;i++)
    {
        printf("%d ",arr[i]);
    }
    printf("\n");
    return 0;
}

 封装函数:遍历数组,打印数组内容

#include<stdio.h>
void show(int *p,int n)
{
    int i=0;
    while(i<n)
    {
        printf("%d ",p[i]);
        i++;
    }
}
int main(int argc, char const *argv[])
{
    int arr[]={1,2,3,4,5,8};
    int n=sizeof(arr)/sizeof(int);
    show(arr,n);
    printf("\n");
    return 0;
}
  • 17
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值