C语言中的数组与函数指针:深入解析与应用

文章目录

  • 一、引言
  • 二、数组的定义
    • 1、数组的定义与初始化
    • 2、char*与char[]的区别
      • 1. 存储与表示
      • 2. 修改内容
      • 3. 作为函数参数
  • 三、字符串指针数组
    • 1. 定义与概念
    • 2. 使用示例
    • 3. 内存管理
  • 四、从字符串指针数组到函数指针的过渡
    • 1、字符串指针数组的应用场景
    • 2、函数指针的基本概念
    • 3、如何从字符串指针数组的概念引申到函数指针
  • 五、函数指针的深入解析
    • 1、函数指针的定义与声明
    • 2、函数指针的赋值与调用
    • 3、函数指针作为参数传递的应用
    • 4、函数指针数组与回调函数的概念与应用
      • a.函数指针数组
      • b.回调函数

一、引言

在编程领域,字符串数组作为一种基础数据结构,它允许程序员将多个字符串存储在连续的内存空间中,并通过索引访问每个字符串。这种特性使得字符串数组在处理文本数据、构建命令行参数列表、实现字符串搜索与排序等功能时显得尤为方便和高效。

然而,当我们需要在程序中实现更高级的功能,如动态地调用不同的函数或根据特定条件执行不同的操作时,函数指针的概念便应运而生。函数指针是一种特殊的指针类型,它指向函数而非数据。通过函数指针,我们可以在运行时动态地改变函数的调用行为,实现代码的灵活性和可重用性。

本文的主题正是从字符串数组的基础知识出发,逐步探讨函数指针的概念与应用。我们将首先回顾字符串数组的基本概念和应用场景,然后逐步引入函数指针的概念,并详细阐述其在编程中的高级应用和灵活性。通过这个过程,我们希望读者能够深入理解从处理数据(字符串数组)到处理代码(函数指针)的思维转变,并学会将这两种强大的工具结合起来,实现更复杂、更灵活的编程逻辑。


二、数组的定义

字符串数组是编程中用于存储多个字符串数据的常见数据结构。它由连续的内存空间组成,每个元素都存储了一个字符串。

1、数组的定义与初始化

字符串数组的定义与初始化

在大多数编程语言中,定义字符串数组的基本语法都遵循相似的模式。下面以C语言为例来说明:

char strArray[N]; // 定义一个字符数组,可以存储N个字符的字符串(不包括结尾的'\0')  
char *strPtrArray[M]; // 定义一个指针数组,每个元素都是一个指向字符的指针,可以存储M个字符串的地址

在上面的代码中,strArray 是一个字符数组,它本身存储了字符数据。而 strPtrArray 是一个指针数组,它存储的是指向字符的指针,这些指针通常指向以 ‘\0’ 结尾的字符串。

创建和初始化字符串数组

对于字符数组,我们通常这样初始化:

char strArray[5] = {'H', 'e', 'l', 'l', 'o'}; // 初始化字符数组  
// 注意:这不是一个以'\0'结尾的字符串,如果需要作为字符串使用,需要额外添加'\0'。

而对于字符串指针数组(即存储字符串地址的数组),我们通常这样初始化:

char *strPtrArray[] = {"Hello", "World", "Programming"}; // 初始化字符串指针数组

在这个例子中,strPtrArray 是一个包含三个元素的字符串指针数组。每个元素都是一个指向以 ‘\0’ 结尾的字符串字面量的指针。这些字符串字面量通常存储在程序的只读数据段中。

当使用字符串指针数组时,我们实际上是在管理字符串的引用,而不是字符串的内容本身。这意味着我们可以轻松地改变数组中的某个元素指向的字符串,而不需要移动或复制大量的数据。

⚠️如果我们使用sizeof计算数组大小:

  1. sizeof 是在编译时计算的,因此它不会受到运行时变量值的影响。
  2. 对于数组,sizeof 返回整个数组的大小,而不是指针的大小。但如果你传递一个数组到函数中,或是使用指针,它通常会退化为指向数组首元素的指针,因此 sizeof 在函数内部会得到指针的大小,而不是整个数组的大小。
  3. 对于结构体,由于内存对齐(padding)的原因,sizeof 返回的大小可能大于结构体中所有成员大小的总和。
  4. sizeof 的结果类型是 size_t,这是一个无符号整数类型,用于表示对象的大小。

在这里插入图片描述

2、char*与char[]的区别

char*char[] 在 C 语言中都是用来处理字符数据的,但它们之间有着本质的区别。以下是它们之间的主要差异:

1. 存储与表示

  • char*(字符指针)

    • 存储的是指向某个字符的内存地址。
    • 它本身不存储字符数据,只是指向存储字符数据的内存位置。
    • 可以指向字符串常量、动态分配的内存或其他字符数组。
  • char[](字符数组)

    • 存储的是实际的字符数据。
    • 数组在内存中占用连续的空间,用于存储一系列字符。
    • 数组的大小在声明时确定,通常是固定的。

2. 修改内容

  • char*

    • 通过指针修改指向的内容是可能的,但需要注意不要越界访问或修改不应当修改的内存区域。
    • 如果指针指向的是字符串常量,尝试修改其内容通常会导致未定义行为。
  • char[]

    • 可以直接修改数组中的元素。
    • 修改数组内容不会影响其他变量或内存区域(除非数组与其他变量在内存中有重叠)。

    如果 char* 指针指向的是字符串常量,那么尝试修改这个指针所指向的内容通常会导致未定义行为(Undefined Behavior,UB)。在 C 语言中,字符串常量通常存储在只读的数据段(也称为文本段或代码段)中,这意味着这些内存区域的内容是不允许修改的。

    尝试修改字符串常量所指向的内容可能会导致程序崩溃、数据损坏或其他不可预见的行为。这是因为操作系统或硬件可能会保护这些只读区域,以防止程序错误地修改它们。

    这里有一个简单的示例来说明这个问题:

    #include <stdio.h>  int main() {  char* ptr = "Hello"; 	// ptr 指向一个字符串常量  *ptr = 'h'; 			// 尝试修改字符串常量的第一个字符,这是未定义行为  printf("%s\n", ptr); 	// 可能不会按预期输出,或者程序可能崩溃  return 0;  
    }
    

    在上面的代码中,ptr 被初始化为指向一个字符串常量 "Hello"。然后尝试修改这个字符串的第一个字符为 'h',这是不允许的,并会导致未定义行为。

    为了避免这种情况,如果你需要修改字符串的内容,应该使用字符数组(char[])或者动态分配的内存(使用 malloccallocstrdup 等函数)。

    例如,使用字符数组:

    #include <stdio.h>  int main() {  char arr[] = "Hello"; // arr 是一个字符数组,可以修改其内容  arr[0] = 'h'; // 修改数组的第一个字符是允许的   或 *arr='h';printf("%s\n", arr); // 输出 "hello"  return 0;  
    }
    

    或者使用动态分配的内存:

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <string.h>  int main() {  char* ptr = strdup("Hello"); // 使用 strdup 动态分配并复制字符串  if (ptr == NULL) {  perror("strdup failed");  return 1;  }  ptr[0] = 'h'; // 修改动态分配内存中的第一个字符是允许的  printf("%s\n", ptr); // 输出 "hello"  free(ptr); // 不要忘记释放动态分配的内存  return 0;  
    }
    

    在上面的两个例子中,字符串内容是可以被修改的,因为它们存储在可以写的内存区域中。

3. 作为函数参数

  • char*

    • 当作为函数参数传递时,通常传递的是指向数据的指针,而不是数据的副本。
    • 可以用来修改指向的数据(如果函数内部允许这么做)。
  • char[]

    • 当作为函数参数传递时,会发生数组到指针的转换(数组衰减)。这意味着函数内部接收到的只是一个指向数组首元素的指针,而不是整个数组的副本。
    • 因此,在函数内部无法直接获取数组的大小,除非将其作为另一个参数传递。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>void modifyThroughPointer(char* ptr) {*ptr = 'X'; // 修改指针指向的第一个字符
}void modifyThroughArray(char arr[]) {arr[0] = 'Y'; // 修改数组的第一个元素
}int main() {char* ptr = malloc(sizeof(char) * 5); // 动态分配内存strcpy(ptr, "ABC"); // 初始化字符串printf("Before modification through pointer: %s\n", ptr);modifyThroughPointer(ptr);printf("After modification through pointer: %s\n", ptr);free(ptr); // 释放动态分配的内存char arr[] = "ABC"; // 声明并初始化字符数组printf("Before modification through array: %s\n", arr);modifyThroughArray(arr);printf("After modification through array: %s\n", arr);return 0;
}

输出:

Before modification through pointer: ABC
After modification through pointer: XBC
Before modification through array: ABC
After modification through array: YBC


三、字符串指针数组

1. 定义与概念

字符串指针数组是一个数组,其元素是指向字符串的指针。换句话说,它存储了一系列字符串的地址,而不是字符串本身的内容。这样的数据结构常用于存储多个字符串的引用,比如文件名列表、命令行参数列表等。

  • 集中管理多个字符串,方便遍历和访问。
  • 动态地创建和修改字符串列表,而不需要固定大小的字符数组。

2. 使用示例

下面是一个简单的示例,展示了如何声明、初始化和使用字符串指针数组:

#include <stdio.h>int main() {// 声明一个字符串指针数组,假设我们知道将要存储的字符串数量char* stringArray[3];// 初始化字符串指针数组,每个元素指向一个字符串常量stringArray[0] = "Hello";stringArray[1] = "World";stringArray[2] = "!";// 遍历字符串指针数组并打印每个字符串for (int i = 0; i < 3; ++i) {printf("%s ", stringArray[i]);}printf("\n");// 也可以动态分配字符串并存储它们的指针char* dynamicString = malloc(10 * sizeof(char));if (dynamicString != NULL) {strcpy(dynamicString, "Dynamic");stringArray[1] = dynamicString; // 替换原来的字符串}// 再次遍历数组以查看更改for (int i = 0; i < 3; ++i) {printf("%s ", stringArray[i]);}printf("\n");free(dynamicString);return 0;
}
//上面代码会输出:
//Hello World !
//Hello Dynamic !

在这个例子中,我们首先声明了一个固定大小的字符串指针数组 stringArray,并初始化了它指向一些字符串常量。然后,我们遍历这个数组并打印出每个字符串。接下来,我们动态分配了一个字符串,并将其地址赋给 stringArray 的一个元素,替换原来的字符串。最后,我们再次遍历数组以查看更改,并释放了动态分配的内存。

3. 内存管理

字符串指针数组在内存中的存储方式取决于它所指向的字符串。如果指针指向的是字符串常量或静态分配的字符串,那么这些字符串通常存储在程序的只读数据段或静态存储区。如果指针指向的是动态分配的字符串(使用 malloccallocstrdup 等函数),那么这些字符串存储在堆上,并且需要程序员显式地释放这些内存以避免内存泄漏。

潜在的内存管理问题包括:

  • 内存泄漏:如果动态分配了内存给字符串,但在不再需要时没有释放它,就会导致内存泄漏。
  • 野指针:如果释放了字符串的内存,但没有将相应的指针设置为 NULL,这个指针就变成了野指针,后续对它的解引用会导致未定义行为。
  • 越界访问:如果访问了数组之外的指针,或者试图通过未初始化的指针访问内存,都可能导致程序崩溃或数据损坏。

为了避免这些问题,程序员需要仔细管理字符串指针数组的内存,确保在适当的时候分配和释放内存,并避免越界访问和野指针的问题。


四、从字符串指针数组到函数指针的过渡

1、字符串指针数组的应用场景

字符串指针数组的应用场景主要是用于存储和管理多个字符串的地址。这些地址可以指向静态分配的字符串常量、堆上动态分配的字符串或者是栈上的局部变量(只要它们在数组生命周期内保持有效)。通过这种方式,可以方便地通过索引来访问和操作这些字符串,而无需关心它们实际存储在哪里。

2、函数指针的基本概念

函数指针是一个指向函数的指针变量。它存储了函数的地址,因此可以通过这个指针来调用函数。函数指针在C语言中是一种强大的工具,它允许程序员将函数作为参数传递给其他函数,或者将函数存储在数组或结构体中,从而实现更高级别的编程抽象和灵活性。

3、如何从字符串指针数组的概念引申到函数指针

从字符串指针数组的概念引申到函数指针,主要是通过类比指针的通用性来实现的。指针的本质是存储内存地址的变量,它可以指向任何类型的数据,包括基本数据类型、结构体、联合体等。同样地,指针也可以指向代码段,即函数的入口地址。这就是函数指针的概念。

我们可以将字符串指针数组看作是指向字符串数据的指针的集合,而函数指针数组则可以看作是指向函数的指针的集合。每个函数指针都存储了一个函数的地址,通过这个函数指针,我们可以间接地调用这个函数。

这种从数据指针到函数指针的过渡,体现了指针的通用性和灵活性。无论是数据还是代码,都可以通过指针来进行访问和操作。这使得C语言能够实现更高级别的编程抽象和模块化设计,提高了代码的可重用性和可维护性。

在实际编程中,函数指针常常用于实现回调函数、函数表、插件系统等高级功能。通过函数指针,我们可以将函数的调用与函数的实现分离开来,提高了代码的模块化和可扩展性。同时,函数指针也可以用于实现多态性,使得不同的函数可以通过相同的接口进行调用。


五、函数指针的深入解析

1、函数指针的定义与声明

函数指针是一个变量,它存储了函数的地址。通过这个函数指针,我们可以间接地调用函数,而不需要直接使用函数名。
函数指针的声明是声明一个变量,该变量用于存储函数的地址。声明时,需要指定该指针所指向的函数的返回类型和参数列表。以下是函数指针定义与声明的基本格式:

返回类型 (*函数指针名)(参数列表);

例如,声明一个指向接受两个整数参数并返回整数的函数的指针:

int (*add_func_ptr)(int, int);

在编程中,函数指针提供了一种将函数作为参数传递或在运行时动态选择函数调用的机制,从而增强了代码的灵活性和可重用性。

2、函数指针的赋值与调用

赋值是将函数的地址赋给函数指针。调用则是通过函数指针来间接调用函数。

#include <stdio.h>int add(int a, int b) {return a + b;
}int main() {int (*func_ptr)(int, int); // 声明函数指针func_ptr= add; // 赋值,将add函数的地址赋给函数指针int sum = func_ptr(3, 4); // 调用,通过函数指针调用函数printf("Sum: %d\n", sum); // 输出:Sum: 7return 0;
}

int (*func_ptr)(int, int); 这一行声明了一个函数指针变量 func_ptr,该函数指针指向一个接受两个 int 类型参数并返回一个 int 类型结果的函数。下面我将详细解释这个声明的各个部分:

  1. int (...)(int, int);:这部分描述了一个函数的类型,即该函数接受两个 int 类型的参数,并返回一个 int 类型的值。
  2. *func_ptr* 符号表明我们声明的是一个指针,而 func_ptr 是这个指针变量的名称。
  3. 将两者结合起来,int (*func_ptr)(int, int); 就声明了一个名为 func_ptr 的函数指针,它指向一个特定类型的函数。

你可以这样理解:func_ptr 是一个变量,它的值是一个内存地址,这个地址上存储的是某个函数的机器码。当你通过 func_ptr 来调用函数时,实际上是通过这个地址来找到并执行相应的函数代码。

在上面的代码中,我们首先定义了一个名为add的函数,它接受两个整数参数并返回它们的和。然后,我们声明了一个名为func_ptr的函数指针,它指向一个接受两个int参数并返回int的函数。在main函数中,我们将add函数的地址赋值给func_ptr,并通过这个函数指针调用了add函数。

3、函数指针作为参数传递的应用

函数指针可以作为参数传递给其他函数,这使得函数更加灵活和可配置。例如,可以编写一个通用的排序函数,它接受一个比较函数的指针作为参数,以决定如何比较元素。

#include <stdio.h>// 比较函数,用于确定两个整数的顺序
int compare(int a, int b) {return a - b;
}// 通用排序函数,接受一个比较函数指针作为参数
void sort_array(int *array, int size, int (*compare_func)(int, int)) {// 实现排序算法,使用compare_func来确定元素顺序// ...
}int main() {int numbers[] = {5, 3, 8, 4, 2};int size = sizeof(numbers) / sizeof(numbers[0]);sort_array(numbers, size, compare); // 传递比较函数指针给排序函数// 输出排序后的数组for (int i = 0; i < size; ++i) {printf("%d ", numbers[i]);}printf("\n");return 0;
}

4、函数指针数组与回调函数的概念与应用

a.函数指针数组

函数指针数组是存储函数指针的数组,它允许你在数组中存储多个函数的地址,并可以通过索引来调用这些函数。

#include <stdio.h>  void func1() {  printf("Function 1 called\n");  
}  void func2() {  printf("Function 2 called\n");  
}  int main() {  void (*func_array[])() = {func1, func2}; // 函数指针数组  // 调用数组中的函数  func_array[0](); // 输出:Function 1 called  func_array[1](); // 输出:Function 2 called  return 0;  
}

b.回调函数

回调函数是一种通过函数指针实现的机制,其中一个函数(回调函数)作为参数传递给另一个函数(调用函数),并在需要时由调用函数执行。回调函数使得代码更加模块化,允许在运行时动态地确定要执行的操作。

#include <stdio.h>  // 回调函数类型  
typedef void (*Callback)(int);  // 调用函数,接受一个回调函数作为参数  
void process_data(int data, Callback callback) {  // ... 执行一些操作 ...  // 调用回调函数  callback(data);  
}  // 回调函数实现  
void print_data(int data) {  printf("Data: %d\n", data);  
}  int main() {  process_data(42, print_data); // 输出:Data: 42  return 0;  
}

在这个示例中,我们定义了一个名为Callback的回调函数类型,它是一个接受int参数并返回void的函数指针。然后,我们定义了一个名为print_number的简单回调函数,它打印传入的整数。process_data函数接受一个整数和一个回调函数作为参数,并在某个时刻调用这个回调函数。在main函数中,我们将print_number作为回调函数传递给process_data函数,后者在适当的时候调用了它。

函数指针数组和回调函数经常一起使用,以实现更高级的功能。例如,在一个事件处理系统中,我们可以有一个函数指针数组,每个元素指向一个处理特定事件的函数。当事件发生时,我们查找数组中的相应函数,并将其作为回调函数调用。

总结来说,函数指针数组和回调函数是C语言中非常强大的工具,它们允许我们编写更加灵活和可维护的代码,实现复杂的逻辑和功能。通过深入理解这两个概念,我们可以更好地利用它们来编写高效的C语言程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/791654.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【管理咨询宝藏48】AA银行信息科技提升分析报告

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏48】AA银行信息科技提升分析报告 【格式】PPT版本&#xff0c;可编辑 【关键词】战略规划、商业分析、管理咨询 【强烈推荐】这是一套市面上非常…

【代码篇】事件监听函数的内存泄漏,都给我退散吧!

前言 内存泄漏是个很严肃的问题&#xff0c;可是迄今也没有一个非常有效的排查方案&#xff0c;本方案就是针对性的单点突破。 工作中&#xff0c;我们会对window, DOM节点&#xff0c;WebSoket, 或者单纯的事件中心等注册事件监听函数, 添加了&#xff0c;没有移除&#xff…

开源软件技术社区方案

开源软件技术社区是一个由开发者、贡献者、用户和维护者组成的共享平台&#xff0c;主要目的是打造技术、软件产品良性互动、开源技术安全可控的软件生态环境&#xff0c;实现可复用应用或服务的快速部署与使用、完成资源与能力的高度共享、促进社区成员的共建共赢&#xff0c;…

c语言--枚举类型(声明、使用、优点)

目录 一、枚举类型的声明二、 枚举类型的优点三、 枚举类型的使用 一、枚举类型的声明 枚举顾名思义就是一一列举。 把可能的取值⼀⼀列举。 比如我们现实生活中&#xff1a; ⼀周的星期⼀到星期日是有限的7天&#xff0c;可以⼀⼀列举 性别有&#xff1a;男、女、保密&#x…

渐进式图片解决前端在页面中使用大图,图片体积过大导致页面出现白屏现象

1、演示 可以看到&#xff0c;图片还在拼命加载的时候&#xff0c; 页面上就已经有内容了 2、什么渐进式图片 图片一开始是模糊的&#xff0c;然后逐渐的开始变的清晰。如果页面上有一些大图&#xff0c;如果直接扔给浏览器的话那么图片的传输时间就会比较长&#xff0c;用户就…

软考高级架构师:校验码概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

【STM32】ST-LINK 下载时遇到的问题

如果出现“ST-Link USB communication error”ST-Link USB通信错误&#xff0c;则需要启动STM32 ST-LINK Utility&#xff0c;点击【ST-LINK】->【Firmaware】更新固件&#xff0c;然后打开Kei&#xff0c;点击魔术棒->->Debug->Settings&#xff0c;开到出现类似“…

电磁兼容故障整改-静电放电抗扰度不合格

电磁兼容故障整改-静电放电抗扰度不合格 ESD干扰机理不合格的主要原因 静电放电对设备的影响有下面几种安装滤波器也对静电放电有所帮助通过良好的搭接与接地防止ESD ESD干扰机理 ESD干扰电流其实是一种共模电流&#xff0c;因为ESD电压总是以参考接地板为基准的。如空击穿放电…

从redux的基本概念渐进式理解redux/toolkit的用法

概念 Redux toolkit是帮助提高redux开发效率的一个库 React-redux 是将React和Redux toolkit绑定在一起的一个库 action 是一个对象,里面有一个type属性 action creator是一个函数,这个函数可以返回上面的action对象。 reducer 是一个函数,接受两个参数(initilastate, acti…

微软邮箱被锁住,该如何解除限制?

ChatGPT账号是微软邮箱注册的&#xff0c;我们在登陆微软邮箱时&#xff0c;http://www.outlook.com&#xff0c;不需要开魔法工具&#xff0c;直接就可以登陆&#xff0c;否则会出现安全验证&#xff0c;限制登陆。 那么如果账号被锁&#xff0c;我们该如何解除限制呢&#x…

mongoDB 优化(2)索引

执行计划 语法&#xff1a; db.collection_xxx_t.find({"param":"xxxxxxx"}).explain(executionStats) 感觉这篇文章写得很好&#xff0c;可以参考 MongoDB——索引&#xff08;单索引&#xff0c;复合索引&#xff0c;索引创建、使用&#xff09;_mongo …

asf是什么格式的文件?用手机怎么打开?

由于手机操作系统和硬件的限制&#xff0c;大部分手机并不直接支持asf文件的播放。因此&#xff0c;如果你想在手机上打开asf文件&#xff0c;你可能需要先将文件转换为手机支持的格式&#xff0c;如MP4。可以通过使用一些视频转换软件来实现&#xff0c;比如野葱视频转换器。 …

【VSCode】修改插件地址

不想放在原始C盘下面C:\Users\{用户}\.vscode\extensions为了后续存储空间考虑&#xff0c;想通过添加环境变量创建名为VSCODE_EXTENSIONS的环境变量&#xff0c;内容指向vs Code扩展所在目录即可 直接配置环境变量&#xff0c;不要在有空格的文件夹下面 变量名称&#xff1a;…

TCP的十个重要的机制

注&#xff1a;TCP不是只有十个机制 TCP 可靠传输是tcp最为重要的核心&#xff08;初心&#xff09; 可靠传输&#xff0c;并不是发送方把数据能够100%的传输给接收方 而是退而求其次 让发送方发送出去数据之后&#xff0c;能够知道接收方是否收到数据。 一但发现对方没有…

CVE-2021-30517:Type confusion bug in LoadSuperIC

前言 这个漏洞是一个比较老的洞&#xff0c;之所以分析这个漏洞&#xff0c;只要是想再学习一下 ICs 相关的知识。并该漏洞的利用是利用与 String/Function 之间的混淆&#xff0c;比较有意思。 环境搭建 sudo apt install python git checkout 7d5e5f6c62c3f38acee12dc4114…

vite.config.js

Vue3vite vite和webpack区别&#xff1f; 1.vite服务器启动速度比webpack快&#xff0c;由于vite启动的时候不需要打包&#xff0c;也就无需分析模块依赖、编译&#xff0c;所以启动速度非常快。当浏览器请求需要的模块时&#xff0c;再对模块进行编译&#xff0c;这种按需动态…

AI智能涂抹修补解决方案助力企业高效创作

传统的手动涂抹修补方式不仅效率低下&#xff0c;而且往往难以达到理想的视觉效果。美摄科技凭借深厚的AI技术研发实力&#xff0c;推出了面向企业的AI智能涂抹修补解决方案&#xff0c;为企业带来前所未有的创作体验。 美摄科技的AI智能涂抹修补解决方案&#xff0c;具备强大…

年少不知EFCore好,错把SqlSugar当成宝

背景&#xff1a;依然记得我的第一份WebApi项目使用得是SqlSugar&#xff0c;当时还没有系统学习b/s这边的知识&#xff0c;跟着别人做项目用SqlSugar觉得非常方便&#xff0c;减少了自己手写ADO.Net的痛苦。但是今天发现这个EFCore也是巨好用啊&#xff0c;下面写一下他的简单…

DDD 的四层领域模型是怎样的?包含哪些基础概念?

DDD的四层领域模型如下所示&#xff1a; 展现层&#xff1a;这一层负责向用户显示信息和解释用户命令&#xff0c;完成前端界面逻辑。并将用户请求传递给应用层。应用层&#xff1a;这一层是很薄的一层&#xff0c;负责协调领域层中的领域对象&#xff0c;组成具体应用场景。应…

LangChain入门:11.Pydantic(JSON)解析器实战

摘要 在数字化营销的浪潮中&#xff0c;自动化内容生成成为了提升效率和用户参与度的利器。本文将详细介绍如何利用LangChain的自然语言处理能力和Pydantic的数据验证特性&#xff0c;构建一个自动化的花店文案生成器。通过这个工具&#xff0c;您可以快速为各种花卉生成吸引人…