C函数指针与回调函数、链表

 

函数指针

函数指针是指向函数的指针变量。

通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数。

函数指针可以像一般函数一样,用于调用函数、传递参数。

函数指针变量的声明:

typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型

示例1

#include <stdio.h>
 
int max(int x, int y)
{
    return x > y ? x : y;
}
 
int main(void)
{
    /* p 是函数指针 */
    int (* p)(int, int) = & max; // &可以省略
    int a, b, c, d;
 
    printf("请输入三个数字:");
    scanf("%d %d %d", & a, & b, & c);
    /* 与直接调用函数等价,d = max(max(a, b), c) */
    d = p(p(a, b), c); 
    printf("最大的数字是: %d\n", d);
 
    return 0;
}

执行

请输入三个数字:1 2 3
最大的数字是: 3

回调函数

函数指针作为某个函数的参数

函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。

简单讲:回调函数是由别人的函数执行时调用你实现的函数。

实例2

实例中 populate_array 函数定义了三个参数,其中第三个参数是函数的指针,通过该函数来设置数组的值。

实例中我们定义了回调函数 getNextRandomValue,它返回一个随机值,它作为一个函数指针传递给 populate_array 函数。

populate_array 将调用 10 次回调函数,并将回调函数的返回值赋值给数组。

#include <stdlib.h>  
#include <stdio.h>
 
// 回调函数
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void)){
    for (size_t i=0; i<arraySize; i++)
        array[i] = getNextValue();
}
 
// 获取随机值
int getNextRandomValue(void){
    return rand();
}
 
int main(void){
    int myarray[10];
    populate_array(myarray, 10, getNextRandomValue);
    for(int i = 0; i < 10; i++) {
        printf("%d ", myarray[i]);
    }
    printf("\n");
    return 0;
}

运行

16807 282475249 1622650073 984943658 1144108930 470211272 101027544 1457850878 1458777923 2007237709

链表

typedef struct LNode{
    int          data;
    struct LNode *next;
}LNode,*LinkList;

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct LNode{
    int          data;
    struct LNode *next;
}LNode,*LinkList;
 
LinkList CreateList(int n)
{
    LinkList L,p,q;
    int i;
    L=(LNode*)malloc(sizeof(LNode));
    if(!L)return 0;
    L->next=NULL;
    q=L;
    for(i=1;i<=n;i++)
    {
        p=(LinkList)malloc(sizeof(LNode));
        printf("请输入第%d个元素的值:",i);
        scanf("%d",&(p->data));
        p->next=NULL;
        q->next=p;
        q=p;
    }
    return L;
}
void print(LinkList h)
{
    LinkList p=h->next;
    while(p!=NULL){
        printf("%d ",p->data);
        p=p->next;
    }
}

int main()
{
    LinkList Head=NULL;
    int n;
    
    scanf("%d",&n);
    Head=CreateList(n);
    
    printf("刚刚建立的各个链表元素的值为:\n");
    print(Head);
    
    printf("\n\n");
    system("pause");
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct LNode{
    int data;
    struct LNode *next;
}L;

//创建节点
L *creat_node(int data){
    L *p=malloc(sizeof(L));
    if(NULL==p){
        printf("malloc error!\n");
        return NULL;
    }
    memset(p,0,sizeof(L));
    p->data=data;
    p->next=NULL;
    return p;
}

//尾插法
void tail_insert(L *pH,L *new){
    L *p=pH;
    while(NULL!=p->next){
        p=p->next;
    }
    p->next=new;
}

//打印链表
void print_list(L *pH){
    L *p=pH;
    while(NULL!=p->next){
        p=p->next;
        printf("data=%d\n",p->data);
    }
}

//反向输出链表
void trave_list(L *pH){
    L *p=pH->next;
    L *pBack;
    while(NULL!=p->next) {
        pBack=p->next;
        if(p==pH->next){
            p->next=NULL;
        }else{
            p->next=pH->next;
        }
        pH->next=p;
        p=pBack;
    }
    top_insert(pH,p);
}

//头插法
void top_insert(L *pH,L *new){
    L *p=pH;
    new->next=pH->next;
    pH->next=new;
}

int main(){
    int i,n,j;
    L *head=creat_node(0);
    printf("请输入想要创建节点的个数:");
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        printf("第%d个节点的数据:",i);
        scanf("%d",&j);
        tail_insert(head,creat_node(j));
    }
    printf("***************************\n");
    printf("刚刚创建的链表:\n");
    print_list(head);
    trave_list(head);
    printf("***************************\n");
    printf("反向输出的链表:\n");
    print_list(head);
    return 0;
}
#include <stdio.h>
#include <string.h>
#include <malloc.h>

typedef struct LNode{
    int data ;
    struct LNode *next; // 后继
    struct LNode *prior; // 前驱
}LNode, *LinkList;


LinkList CreateList(int n){
    // p是当前正在声明的链表节点
    // q是前一个已经完成声明的链表节点
    // L是第一个链表元素
    LinkList L,p,q;
    int i;

    // 额外声明一个节点, 保存第一个链表节点
    L = (LNode*)malloc(sizeof(LNode));
    if(!L)
        return 0 ;
    for (i=1; i<=n; i++){
        p = (LinkList)malloc(sizeof(LNode));
        printf("input %dth value.\n",i);
        scanf("%d",&(p->data));
        // 对于第一个链表元素 只需要赋值,其前驱后继都为空,进行保存
        if (i == 1){
            p -> next = NULL;
            p -> prior = NULL;
            L = p ;
            q = p ;
        }
        // 对于后继的链表节点,将其前驱置为q,将q的后继置为p
        else{
            p -> next = NULL ;
            p -> prior = q ;
            q -> next = p;
            q = p;
        }
        // 如果是最后一个链表节点,将其与第一个元素连接。
        if (i == n){
            L -> prior = q ;
            q -> next = L ;
        }
    }
    return q ;
}

void print(LinkList p,int n){
    int i =1 ;
    while (i <= n){
        printf("%d ", p->data);
        if ( p -> prior != NULL) {
            printf("prior = %d\n",p->prior->data);
        }
        p = p -> next;
        i ++ ;
    }
}


int main(){
    LinkList Head = NULL;
    int n ;
    printf("input the length of the linking table.\n");
    scanf("%d",&n);
    Head = CreateList(n);
    printf("the value of link table:\n");
    print(Head,n);
    return 0 ;
}
运行:
请输入想要创建节点的个数:4
第1个节点的数据:1
第2个节点的数据:2
第3个节点的数据:3
第4个节点的数据:4
***************************
刚刚创建的链表:
data=1
data=2
data=3
data=4
***************************
反向输出的链表:
data=4
data=3
data=2
data=1
原创文章 96 获赞 48 访问量 6万+

猜你喜欢

转载自blog.csdn.net/wteruiycbqqvwt/article/details/100994482