C语言中函数与数据传递

一、回调函数

可以通过函数指针的方式把一个函数注入到另一个函数里,这种注射的函数叫做回调函数,例如

#include<stdio.h>
int add(int a,int b){
        return a+b;
}
int text(int a,int(*p)(int c,int d)){//将add函数注入到text函数中
        return a+p(5,6);
}
int main(int argc,const char*argv[]){
        int ret=text(5,add);//5+(5+6)
        printf("%d\n",ret);//16
        return 0;
}

二、函数间数据传递

1、值传递

单向传递,将实参传递给形参使用,改变形参时不会影响实参值

2、地址传递

双向传递,在函数中修改形参值,会影响实参

注:也就是说,假设我们写一个两个数交换位置的函数,如果用值传递的方式,那么主函数中的数值不会发生改变,但是用地址传递就可以改变其内容,例如

#include<stdio.h>
void change(int a,int b){//值传递
    int t;
    t=a;
    a=b;
    b=t;
}
void change1(int *a,int *b){//地址传递
    int t;
    t=*a;
    *a=*b;
    *b=t;
}
int main(void){
    int x=5,y=10;
    change(x,y);
    printf("x=%d y=%d\n",x,y);//x=5,y=10,不会改变
    change1(&x,&y);
    printf("x=%d y=%d\n",x,y);//x=10,y=5,会被改变
    return 0
}

3、数组传递

和地址传递一样,参数中存在数组定义,它会认为是指针,可以用来实现双向数据传递,例如

#include<stdio.h>
#include<stdlib.h>//rand()、srand()函数所需头文件
#include<time.h>//time函数所需头文件
void create(int arr[],int size){
    int num=0;
    for(num=0;num<=size-1;num++){
        arr[num]=rand()%36+1;//取1~36的随机数
    }
}
int main(void){
    int arr[7]={0};
    int num=0;
    srand(time(0));//生成随机数
    create(arr,7);
    for(num=0;num<7;num++)
        printf("%d ",arr[num]);//会打印出放到数组中的随机数
    printf("\n");
    return 0;
}

 也可以将地址当做返回值传回给调用函数,例如:

 4、无类型指针当作形参使用
可以让调用函数向被调用函数开放任意类型的存储区,例如:

#include<stdio.h>
void(const void *p_v,int type){
    if(!type){
        printf("%c\n",*(char*)p_v);//以char的类型访问
    }
    else if(type==1){
        printf("%d\n",*(int*)p_v);//以int的类型访问
    }
}
int main(void){
    char ch='e';
    int val=56;
    print(&ch,0);
    print(&val,1);
    return 0;
}

这里涉及到强制转换,(数据类型*)指针或者是(数据类型)变量,进行强制转换,例如上述的void*我理解就是不去访问地址,(char*)强转后表示以char的方式去访问该地址;

比如float a=3.14;当我printf("%d",(int)a);将会输出3,将a强转成int类型了

5、调用函数的存储区地址可以做返回值传递

使用时注意生命周期,例如:

#include<stdio.h>
int *read(void){
        static int val=0;//静态局部变量的声明周期符合要求,如果不加static,val存储区在程序结束 
                         //后就会被释放,主函数无法找到存储区中的数值了
        printf("请输入一个数:\n");
        scanf("%d",&val);
        return &val;
}
int main(void){
        int *p_val=read();
        printf("%d\n",*p_val);
        return 0;
}

三、递归函数

c语言中函数自己可以调用自己,这样的函数就是递归函数

使用递归函数解决问题时,一般是一个复杂的问题可以使用一种方法不停地进行分解,分解以后问题比之前更简单

编写步骤:

①编写语句解决分解之后的每个小问题;

②递归调用语句之前编写分支解决不可分解的情况以保证函数可以结束

例如用递归函数来显示费氏数列:

     费氏数列:  1        1        2        3        5        8       13      21......

     编号:         0        1        2        3        4        5        6        7......

 注:加static是为了延长生命周期,这样递归函数每次调用自己的时候前面算过存在数组内的值就不需要重新计算,不加static时每次调用都会重新申请数组,因此当给出的数比较大时,计算会非常慢。

综合一下,写个带结构体的函数,并且运用动态分配;

函数1从键盘得到一个水平长方形位置,把它记录在动态分配内存里,最后把位置传递给调用函数

函数2从调用函数得到水平长方形位置,计算中心点并记录在动态分配的内存里在传递给调用函数

 四、常用的一些函数与string族函数

头文件<string.h>

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

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

功能:将一串字符串的内容拷贝到另一个数组里面,会覆盖原来的内容

参数:

dest:源字符数组地址

src:要拷贝进去的字符串

n:要拷贝进去的个数

返回值:返回拷贝完后的字符串地址
 

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

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

功能:把一串字符串的内容追加到另一个字符串末尾,注意数组空间要能装下合并后的字符串

参数:

dest:源字符串

src:要追加的字符串

n:代表要追加的个数(没有n就将src都追加进去)

返回值:返回一个指向结果字符串的地址

int strcmp(const char *s1, const char *s2);

int strncmp(const char *s1, const char *s2, size_t n);

功能:比较两个字符串的大小

参数:

s1、s2:两个字符串

n:限定比较前几个字符,

”hello“和”world“比较,先是h与w比较,w大,后面的就不用比较了

”hello“和”heall“比较,h相等e相等,l大于a,前面大,但如果n等于2,那么只比较前两个字符,则相等

返回值:  1 前面大

                -1 后面大

                 0 一样大

 char *strstr(const char *haystack, const char *needle);

功能:从一个字符串里找一个字符串的位置

参数:显而易见两个字符串

返回值:找到的第一个字符的位置,找不到返回NULL

例如char *p_ch=str("abcdef","cd");   printf("%s\n",p_ch);//显示cdef

void *memset(void *s, int c, size_t n);//把一组连续字符类型存储区的前n个设置成同一个字符参数c

void bzero(void *s, size_t n);//把一组连续字符类型存储去的前n个设置成0;

头文件<stdlib.h>

int atoi(const char *nptr);//把字符串开头整数部分转换成整数类型

double atof(const char *nptr);//把字符串开头部分浮点数转换为浮点数类型

#include<stdio.h>
#include<stdlib.h>
int main(void){
        int val=0;
        double dval=0.0;
        val=atoi("35jsdh");
        dval=atof("25.99fslg");
        printf("val是%d\n,dval是%lg\n",val,dval);//结果是35和25.99
        return 0;
}

头文件<stdio.h>

int sscanf(const char *str, const char *format, ...);//从字符串里获得数字记录到存储区

int sprintf(char *str, const char *format, ...);//数字转换成字符串记录到字符数组

#include<stdio.h>
#include<string.h>
int main(void){
        char arr[20]={0};
        int val=0;
        float fval=0.0f;
        char ch=0;
        sprintf(arr,"%d%g%c\n",40,6.4f,'t');
        printf("%s",arr);//406.4t
        sscanf("a556.3","%c%d%g",&ch,&val,&fval);
        printf("%g%d%c\n",fval,val,ch);//0.3 556 w
        return 0;
}

           

          

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于C语言的单链表,可以通过函数指针传递数据函数指针是一个指向函数的指针变量,可以用来动态地调用函数。通过函数指针,我们可以将单链表数据传递给其他函数进行处理。 下面是一个简单的示例代码,演示了如何使用函数指针传递单链表的数据: ```c #include <stdio.h> #include <stdlib.h> // 定义单链表结构体 struct Node { int data; struct Node* next; }; // 定义一个函数指针类型,用于处理单链表数据 typedef void (*DataHandler)(int); // 遍历单链表,并将数据通过函数指针进行处理 void processLinkedList(struct Node* head, DataHandler handler) { struct Node* current = head; while (current != NULL) { // 调用函数指针来处理当前节点的数据 handler(current->data); current = current->next; } } // 打印单链表节点的数据 void printData(int data) { printf("%d ", data); } int main() { // 创建一个简单的单链表 struct Node* node1 = (struct Node*)malloc(sizeof(struct Node)); struct Node* node2 = (struct Node*)malloc(sizeof(struct Node)); struct Node* node3 = (struct Node*)malloc(sizeof(struct Node)); node1->data = 1; node2->data = 2; node3->data = 3; node1->next = node2; node2->next = node3; node3->next = NULL; // 通过函数指针打印单链表数据 processLinkedList(node1, printData); // 释放内存 free(node1); free(node2); free(node3); return 0; } ``` 在上面的代码,我们定义了一个函数指针类型 `DataHandler`,它接受一个 `int` 类型的参数并返回 `void`。然后,我们定义了一个函数 `processLinkedList`,它接受一个单链表的头结点和一个函数指针作为参数,遍历单链表并通过函数指针来处理每个节点的数据。 在 `main` 函数,我们创建了一个简单的单链表,并通过调用 `processLinkedList` 函数来打印单链表数据。`printData` 函数传递给 `processLinkedList` 函数作为函数指针参数,用于打印节点的数据。 输出结果将会是:1 2 3,表示成功地通过函数指针打印了单链表数据。 希望这个示例能帮助到你理解如何使用函数指针传递单链表的数据。如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值