1.函数指针的定义
void func() {
printf("hello world!");
}
//func函数名其实是代表函数的入口地址
//如何定义一个指向函数的指针
int myfunc(int a, char b) {
printf("int myfunc(int a, char b)\n");
return 0;
}
void test() {
//1.定义函数类型,通过类型来定义函数指针
typedef int(FUN_TYPE)(int, char);
FUN_TYPE* pFunc = myfunc;
pFunc(10, 'a');
(*pFunc)(20, 'b');
//2.直接定义函数指针类型
typedef int(*FUNC_P)(int, char);
FUNC_P pFunc2 = myfunc;
pFunc2(20, 'd');
//3.直接定义函数指针变量
//把指针转换为函数指针类型写法
int(*pFunc3)(int, char) = (int(*)(int, char))NULL;
pFunc3 = myfunc;
pFunc3(50, 'e');
printf("pFunc3 size:%d\n", sizeof(pFunc3));
}
2.函数指针做函数参数
int con1(int a, int b) {
return a + b;
}
int con2(int a, int b) {
return a + b - 10;
}
int con3(int a, int b) {
return a + b + 10;
}
//使用函数指针就可以将函数作为另一个函数的参数
void doLogic(int(*pFunc)(int, int)) {
int a = 20; int b = 10;
int ret = pFunc(a, b);
printf("ret = %d\n", ret);
}
void test() {
//通过函数指针可以方便地调用编写的规则,不用大幅更改代码
doLogic(con3);
}
void func1() {
printf("func1\n");
}
void func2() {
printf("func2\n");
}
void func3() {
printf("func3\n");
}
void test() {
//函数指针数组
void(*func_array[3])();
func_array[0] = func1;
func_array[1] = func2;
func_array[2] = func3;
for (int i = 0; i < 3; ++i) {
func_array[i]();
}
}
struct Person {
char name[64];
int age;
};
//函数指针做函数参数(回调函数)
void printAllArray(void* arr, int eleSize, int len,void(*print)(void *)) {
//先拿到元素首地址,然后通过函数指针回传给调用函数
char* start = (char*)arr;
for (int i = 0; i < len; ++i) {
//printf("%d\n", start+i*eleSize);//元素首地址
char* eleAddr = start + i * eleSize;
print(eleAddr);
}
}
void myPrint(void* data) {
//data为地址,强转为指定类型后即可输出
int* p = (int*)data;
printf("%d ", *p);
}
void myPrintPerson(void* data) {
struct Person* person = (struct Person*)data;
printf("Name:%s Age:%d\n", person->name, person->age);
}
void test() {
int arr[] = { 1,2,3,4,5 };
printAllArray(arr, sizeof(int), 5, myPrint);
struct Person persons[] = {
{"aaa",10},
{"bbb",20},
{"ccc",30},
{"ddd",40},
};
printAllArray(persons, sizeof(struct Person), 4, myPrintPerson);
}
3.链表的定义
4.静态链表
//链表节点类型定义
struct linkNode {
int data;
struct linkNode* next;
};
void test() {
struct linkNode node1 = { 10,NULL };
struct linkNode node2 = { 20,NULL };
struct linkNode node3 = { 30,NULL };
struct linkNode node4 = { 40,NULL };
struct linkNode node5 = { 50,NULL };
struct linkNode node6 = { 60,NULL };
node1.next = &node2;
node2.next = &node3;
node3.next = &node4;
node4.next = &node5;
node5.next = &node6;
//如何遍历链表
//先定义一个辅助指针变量
struct linkNode* pCur = &node1;
while (pCur != NULL)
{
printf("%d ", pCur->data);;
//指针移动到下一个元素的首地址
pCur = pCur->next;
}
}
5.动态链表的基本操作
初始化、遍历、插入、清空、删除和销毁
//linkList.h
#pragma once
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>//可计算偏移量
#include <stdbool.h>
//为了在C++中能调用C写的函数
#ifdef __cplusplus
extern "C" {
#endif
//定义节点数据类型
struct linkNode {
int data;
struct linkNode* next;
};
//初始化链表
struct linkNode* init_linkList();
//在值为val的位置插入一个新数据newVal
void insertValue(struct linkNode* header, int value, int newVal);
//删除值为val的节点
void removeValue(struct linkNode* header, int value);
//遍历
void forEach(struct linkNode* header);
//销毁
void destroy(struct linkNode* header);
//清空
void clearLinkList(struct linkNode* header);
//链表逆序
void reverse_linkList(struct linkNode* header);
#ifdef __cplusplus
}
#endif
//linkList.c
#define _CRT_SECURE_NO_WARNINGS
#include "linkList.h"
//初始化链表
struct linkNode* init_linkList() {
//创建头结点
struct linkNode* header = malloc(sizeof(struct linkNode));
header->data = -1;
header->next = NULL;
//尾部指针
struct linkNode* pRear = header;
int val = -1;
while (true) {
printf("输入插入的数据:\n");
scanf("%d", &val);
if (val == -1)
break;
//先创建新节点
struct linkNode* newNode = malloc(sizeof(struct linkNode));
newNode->data = val;
newNode->next = NULL;
//新节点插入到链表中
pRear->next = newNode;
//更新尾部指针
pRear = newNode;
}
return header;
}
//在值为val的位置插入一个新数据newVal
void insertValue(struct linkNode* header, int value, int newVal) {
if (NULL == header)
return;
//两个辅助指针变量
struct linkNode* pPrev = header;
struct linkNode* pCur = pPrev->next;
while (pCur != NULL) {
if (pCur->data == value)
break;
//未找到时,继续向后移动
pPrev = pCur;
pCur = pCur->next;
}
#if 0
//如果pCur为空,说明链表中不存在值为value的节点
if (NULL == pCur) {
return;
}
#endif
//先创建新节点
struct linkNode* newNode = malloc(sizeof(struct linkNode));
newNode->data = newVal;
newNode->next = NULL;
//新节点插入到链表中
newNode->next = pCur;
pPrev->next = newNode;
}
//删除值为val的节点
void removeValue(struct linkNode* header, int value) {
if (NULL == header)
return;
//两个辅助指针变量
struct linkNode* pPrev = header;
struct linkNode* pCur = pPrev->next;
while (pCur != NULL) {
if (pCur->data == value) {
break;
}
//移动两个辅助指针
pPrev = pCur;
pCur = pCur->next;
}
//此时已找到节点或者节点不存在
if (NULL == pCur) {
return;
}
//重新建立待删除节点的前驱和后继节点关系
pPrev->next = pCur->next;
free(pCur);
pCur = NULL;
}
//遍历
void forEach(struct linkNode* header) {
if (NULL == header)
return;
//辅助指针变量
struct linkNode* pCur = header->next;
while (pCur != NULL) {
printf("%d ", pCur->data);
pCur = pCur->next;
}
}
//销毁
void destroy(struct linkNode* header) {
if (NULL == header)
return;
//辅助指针变量
struct linkNode* pCur = header->next;
while (pCur != NULL) {
//先保存下当前节点的下一个节点地址
struct linkNode* pNext = pCur->next;
//释放当前节点内存
printf("%d节点被销毁!\n", pCur->data);
free(pCur);
//指针向后移动
pCur = pNext;
}
}
//清空
void clearLinkList(struct linkNode* header) {
if (NULL == header) {
return;
}
//辅助指针变量
struct linkNode* pCur = header->next;
while (pCur != NULL) {
//先保存下当前节点的下一个节点地址
struct linkNode* pNext = pCur->next;
//释放当前节点内存
free(pCur);
//pCur指向下一节点
pCur = pNext;
}
header->next = NULL;
}
//链表逆序
void reverse_linkList(struct linkNode* header) {
if (NULL == header)
return;
struct linkNode* pPrev = NULL;
struct linkNode* pCur = header->next;
struct linkNode* pNext = NULL;
while (pCur != NULL) {
pNext = pCur->next;
pCur->next = pPrev;
pPrev = pCur;
pCur = pNext;
}
header->next = pPrev;
}
//main.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>//可计算偏移量
#include"linkList.h"
void test(){
//初始化链表100 200 666 300 400 500 600
struct linkNode* header = init_linkList();
//打印链表
forEach(header);
//插入数据
printf("\n-------------------\n");
insertValue(header, 300, 666);
//打印链表
forEach(header);
//逆序链表
reverse_linkList(header);
printf("\n---------逆序链表----------\n");
forEach(header);
//清空链表
clearLinkList(header);
printf("\n-------------------\n");
//打印链表
forEach(header);
insertValue(header, 1000, 111);
insertValue(header, 1000, 211);
insertValue(header, 1000, 311);
insertValue(header, 1000, 411);
printf("\n-------------------\n");
//打印链表
forEach(header);
//删除节点
removeValue(header, 311);
printf("\n-------------------\n");
forEach(header);
removeValue(header, 211);
printf("\n-------------------\n");
forEach(header);
//销毁链表
destroy(header);
}
int main(){
test();
return 0;
}