一、使用C语言写出数组指针,指针数组,函数指针,指针函数的定义和使用示例。

答案链接

二、使用C语言实现一个单向链表,实现初始化节点,增添节点(头插法和尾插法),删除节点,显示节点功能。

#include <stdio.h>
#include <stdlib.h>

// 定义链表节点结构体
struct Node {
    int data;
    struct Node* next;
};

// 初始化节点
struct Node* initNode(int data) {
    struct Node* node = (struct Node*)malloc(sizeof(struct Node));
    if (node == NULL) {
        perror("Failed to allocate memory for node");
        exit(EXIT_FAILURE);
    }
    node->data = data;
    node->next = NULL;
    return node;
}

// 头插法插入节点
void insertAtHead(struct Node** headRef, int data) {
    struct Node* newNode = initNode(data);
    newNode->next = *headRef;
    *headRef = newNode;
}

// 尾插法插入节点
void insertAtTail(struct Node** headRef, int data) {
    struct Node* newNode = initNode(data);
    if (*headRef == NULL) {
        *headRef = newNode;
    } else {
        struct Node* current = *headRef;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = newNode;
    }
}

// 删除指定数值的节点
void deleteNode(struct Node** headRef, int data) {
    struct Node* current = *headRef;
    struct Node* previous = NULL;

    while (current != NULL && current->data != data) {
        previous = current;
        current = current->next;
    }

    if (current != NULL) {
        if (previous == NULL) {
            *headRef = current->next;
        } else {
            previous->next = current->next;
        }
        free(current);
    } else {
        printf("Node with data %d not found\n", data);
    }
}

// 显示链表中的所有节点
void displayList(struct Node* head) {
    struct Node* current = head;
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

// 清空链表
void clearList(struct Node** headRef) {
    struct Node* current = *headRef;
    struct Node* next;

    while (current != NULL) {
        next = current->next;
        free(current);
        current = next;
    }

    *headRef = NULL;
}

// 示例
int main() {
    struct Node* head = NULL;

    // 初始化节点
    insertAtTail(&head, 1);
    insertAtTail(&head, 2);
    insertAtTail(&head, 3);
    insertAtTail(&head, 4);
    insertAtTail(&head, 5);

    // 显示节点
    printf("Original list:\n");
    displayList(head);

    // 头插法插入节点
    insertAtHead(&head, 0);
    printf("List after inserting 0 at head:\n");
    displayList(head);

    // 删除节点
    deleteNode(&head, 3);
    printf("List after deleting node with data 3:\n");
    displayList(head);

    // 清空链表
    clearList(&head);

    return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.

三、写出委托(delegate)的定义,和委托的使用示例

委托(Delegate)是一种在C#中定义方法的类型,它可以用来引用一个或多个方法,并且允许这些方法在运行时动态添加或移除。委托类型定义了方法的签名(返回类型和参数列表),使得委托对象可以引用任何具有兼容签名的方法。

在C#中,委托的定义语法如下:

delegate ReturnType DelegateName(ParameterList);
  • 1.

其中:

  • ReturnType 是委托指向方法的返回类型。
  • DelegateName 是委托类型的名称。
  • ParameterList 是委托指向方法的参数列表。

示例

using System;

// 定义一个委托类型
delegate void Operation(int x, int y);

// 定义一个包含委托的类
class MathOperations
{
    // 方法1:加法操作
    public static void Add(int a, int b)
    {
        Console.WriteLine($"Addition result: {a + b}");
    }
}

// 另一个类,实例化委托并进行跨类调用
class Program
{
    static void Main()
    {
        // 创建委托实例,并让它引用MathOperations类中的方法
        Operation operation = MathOperations.Add;

        // 跨类调用委托
        operation(5, 3); // 输出: Addition result: 8
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

四、写出Action,Func,Predicate的功能定义,并给出示例,并使用表格形式区分三者在参数,返回值,参数个数,使用场景上的异同点。

1. Action:
  • 用途: Action 委托用于表示无返回值的方法(void 方法)。
  • 示例:
  • Action<string> print = s => Console.WriteLine(s);
  • 特点: Action 可以用于定义没有返回值的委托,通常用于执行一些操作而不需要返回结果。
2. Func:
  • 用途: Func 委托用于表示具有返回值的方法。
  • 示例: Func<int, int, int> add = (x, y) => x + y;
  • 特点: Func 可以定义带有返回值的委托,最后一个泛型参数表示返回值类型,前面的参数表示方法的参数类型。
3. Predicate:
  • 用途: Predicate 是 Func<T, bool> 的一个特殊版本,通常用于表示接受一个参数为 T 类型并返回 bool 类型的方法。
  • 示例: Predicate<int> isEven = x => x % 2 == 0;
  • 特点: Predicate 专门用于表示条件判断的委托,通常用在需要传递一个判断条件的场景中。
4. Delegate:
  • 用途: Delegate 是 C# 中的一种基础委托类型,可以用来表示任何方法签名。
  • 特点: Delegate 是所有委托类型的基类,可以用来定义自定义委托类型,也可以用作事件的类型。

类型

用途

方法签名

返回值

参数个数

示例

Action

无返回值的方法

Action<T> Action<T1, T2>


0 到 16 个

Action action = x => Console.WriteLine(x);

Func

有返回值的方法

Func<T, TResult>Func<T1, T2, TResult>


1 到 16 个

Func<int, bool> func = x => x > 0;

Predicate

布尔条件判断

Predicate<T>

bool

1

Predicate isPositive = x => x > 0;

delegate

自定义方法签名的委托

自定义的签名 delegate TResult MethodName(T parameter);

可以自定义

任意

delegate bool IsEven(int x);

常见使用场景
  • Action 用于需要执行某些操作但不需要返回值的场景。
  • Func 用于需要计算结果或转换数据的场景。
  • Predicate 用于条件判断、过滤集合等场景。
  • delegate 用于定义自定义方法签名,适用于更复杂的需求和事件处理。