指针进阶大冒险:解锁C语言中的奇妙世界!
目录
引言
第一阶段:🔍 独特的字符指针
什么是字符指针?
字符指针的用途
演示:使用字符指针拷贝字符串
字符指针与字符串常量
小试牛刀
第二阶段:🎯 玩转指针数组
指针数组是什么?
指针数组的用途
演示:创建和使用指针数组
第三阶段:🎯 探索数组指针的神奇之旅
数组指针:是指针还是数组?
数组指针的定义
解释数组指针的应用
小试牛刀
int *p1[10];:指针数组
int (*p2)[10];:数组指针
&数组名 与 数组名:剖析引用与地址
&数组名:取地址操作
数组名:首元素的指针
比较一下
代码解释
数组指针的使用
print_arr1 函数解释
print_arr2 函数解释
练习
第四阶段:🔗 数组参数、指针参数的传递方式
一维数组传参
二维数组传参
一级指针传参
二级指针传参
第五阶段:🔗 探索函数指针的神奇世界
函数指针简介
使用函数指针
函数指针数组
指向函数指针数组的指针
第六阶段:🔗 回调函数:让程序更灵活
回调函数简介
回调函数的应用
结语:尖叫指针,飞跃编程界!🚀
引言
🌟📚 "指针是编程的魔法棒,它们能在内存中画出绚丽的图景。而在今天的探索中,我们将穿越指针的彩虹,解锁高级的指针魔法!就像在魔法学校里学习新的咒语,我们将探索字符指针、数组指针、函数指针等进阶内容,为你的编程技能注入更多的魔力。快来加入我们的奇妙旅程吧,一起解开指针的高级谜团!" 🌈✨
第一阶段:🔍 独特的字符指针
欢迎来到指针大冒险的第一站!在本阶段,我们将揭开字符指针的神秘面纱,探索它在C语言中的精彩应用。
什么是字符指针?
字符指针是指向字符数据的指针,它的灵活性和用途让人惊叹不已。在C语言中,字符串实际上是以字符数组的形式存在的,而字符指针则是指向字符串首字符的指针。
字符指针的用途
字符指针的应用极其广泛,尤其在字符串处理方面。它能够让我们以一种高效的方式操作字符串,实现诸如字符串拷贝、连接、比较等操作。此外,字符指针还为我们提供了一种遍历字符串的简洁方法。
演示:使用字符指针拷贝字符串
让我们通过一个示例来演示如何使用字符指针拷贝一个字符串。以下是一个自定义的字符串拷贝函数:
#include <stdio.h>void stringCopy(char *dest, const char *src) {while (*src != '\0') {*dest = *src;dest++;src++;}*dest = '\0'; // 添加字符串结尾的空字符
}int main() {char source[] = "Hello, World!";char destination[20];stringCopy(destination, source);printf("Copied string: %s\n", destination);return 0;
}
在这个例子中,我们使用字符指针 src
和 dest
分别指向源字符串和目标字符串。通过逐个字符地拷贝,我们可以将源字符串的内容复制到目标字符串中,然后在末尾添加一个空字符。
字符指针与字符串常量
字符指针也常用于处理字符串常量,这些常量是以字符数组的形式存储在内存中。通过字符指针,我们可以轻松地访问和操作这些常量:
#include <stdio.h>int main() {const char *message = "Hello, C Pointers!";printf("Message: %s\n", message);return 0;
}
小试牛刀
#include <stdio.h>int main() {char str1[] = "Hello, World!";char str2[] = "Hello, World!";const char *str3 = "Hello, World!";const char *str4 = "Hello, World!";if (str1 == str2)printf("str1 and str2 are same\n");elseprintf("str1 and str2 are not same\n");if (str3 == str4)printf("str3 and str4 are same\n");elseprintf("str3 and str4 are not same\n");return 0;
}
在这段代码中,我们比较了字符数组和指向字符串常量的字符指针之间的区别。以下是代码的详细解释:
在
main
函数中,我们定义了两个字符数组str1
和str2
,它们都包含相同的字符串"Hello, World!"
。我们还定义了两个指向字符串常量的字符指针
str3
和str4
,同样指向字符串"Hello, World!"
。接下来,我们使用
==
运算符分别比较str1
和str2
,以及str3
和str4
。注意,str1
和str2
是字符数组,而str3
和str4
是指向字符串常量的指针。当比较
str1
和str2
时,由于它们分别是不同的字符数组,它们的地址也是不同的,因此条件为假,将输出 "str1 and str2 are not same"。当比较
str3
和str4
时,由于它们指向相同的字符串常量,它们的地址也是相同的,因此条件为真,将输出 "str3 and str4 are same"。
第二阶段:🎯 玩转指针数组
欢迎来到指针大冒险的第二站!在本阶段,我们将深入探讨指针数组的奥秘,适合各位小白朋友学习,让我们一起探索它在C语言中的精彩应用。
指针数组是什么?
首先,让我们来理解一下什么是指针数组。在C语言中,指针数组是一种特殊的数组类型,它的每个元素都是指针。每个指针可以指向不同的数据,如整数、字符、字符串等。这意味着,指针数组实际上是存储了多个指针的数组。
指针数组的用途
指针数组在许多编程场景中都扮演着关键角色。它的灵活性使得它在多种情况下都非常有用:
字符串数组:一个常见的应用是创建字符串数组,其中每个元素指向不同的字符串。这使得我们能够轻松地管理和操作多个字符串。
函数参数:当我们需要将多个数据项作为参数传递给函数时,指针数组是一个不错的选择。它可以帮助我们将不同类型的数据集合在一起传递给函数。
多项选择题:在编程中,有时我们需要处理多个选项,指针数组可以用来存储这些选项的指针,便于处理和操作。
演示:创建和使用指针数组
让我们通过一个示例来演示如何创建和使用指针数组,并展示它在字符串数组中的应用:
#include <stdio.h>int main() {char *fruits[] = {"Apple","Banana","Orange","Grapes"};int numFruits = sizeof(fruits) / sizeof(fruits[0]);for (int i = 0; i < numFruits; i++) {printf("Fruit %d: %s\n", i + 1, fruits[i]);}return 0;
}
在这个例子中,我们创建了一个指针数组 fruits
,其中的每个元素都是指向字符串的指针。我们使用花括号初始化语法,将几个水果名字的字符串赋值给指针数组。然后,我们通过循环遍历指针数组,并打印出每个水果的名称。
第三阶段:🎯 探索数组指针的神奇之旅
欢迎来到指针大冒险的第三站!在本阶段,我们将深入探讨数组指针的奥秘,为C语言新手们揭示其精彩应用。
数组指针:是指针还是数组?
在C语言中,数组指针是一种非常有趣的概念。虽然它名字中包含了"数组",但它实际上是一种指针。数组指针允许我们以一种更加灵活的方式来处理数组,从而克服了使用普通数组下标的一些限制。
数组指针的定义
以往,我们熟悉了整型指针和浮点型指针,它们分别指向整数和浮点数类型的数据。类似地,数组指针是一种能够指向数组的指针。通过使用数组指针,我们能够以更加自由和灵活的方式操作数组中的元素。
解释数组指针的应用
数组指针在处理数组时发挥着重要作用。它不仅仅是一个单纯的指针,它更像是一个为数组开辟的一扇智能门。它允许我们以指针的方式移动、访问和操作数组中的元素,无需受限于普通数组下标的顺序
小试牛刀
在该小节,我们将深入探索两种看似相似但实际截然不同的指针类型:int *p1[10];
和 int (*p2)[10];
。虽然它们都涉及指针和数组,但它们的应用和含义却截然不同。
int *p1[10];
:指针数组
首先,让我们揭开
int *p1[10];
的面纱。这段代码定义了一个数组,这个数组中有10个元素,每个元素都是指向整数的指针。具体来说,p1
是一个指针数组,它可以存储多个整数指针。这使得我们能够方便地管理多个整数指针,每个指针可以指向不同的整数。
int (*p2)[10];
:数组指针
接下来,我们来解释
int (*p2)[10];
。这行代码定义了一个指针,这个指针指向一个包含10个整数的数组。简而言之,p2
是一个数组指针,它可以帮助我们处理整数数组。通过操作这个指针,我们可以以更加灵活的方式访问整数数组中的元素。
注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。
&数组名
与 数组名:剖析引用与地址
&数组名
:取地址操作
首先,我们来解释
&数组名
的作用。&数组名
表示取得整个数组的起始地址,它不是数组本身,而是指向数组的指针。这种操作可以让我们获取整个数组在内存中的位置。
数组名:首元素的指针
数组名不仅仅是一个名称,它还是一个指向数组首元素的指针。因此,数组名可以用来表示整个数组,也可以用来访问数组中的元素。
比较一下
&数组名
:表示整个数组的起始地址,是指向数组的指针。- 数组名:指向数组首元素的指针,可以用来表示整个数组或访问数组元素。
举个例子,假设有一个整型数组
int numbers[5];
,我们可以使用&numbers
来获得整个数组在内存中的位置,而使用numbers
则是数组首元素的指针,可以用于遍历和访问数组中的元素。
代码解释
#include <stdio.h>int main() {int arr[10] = {0};printf("%p\n", arr); // 打印数组首元素的地址printf("%p\n", &arr); // 打印整个数组的起始地址return 0;
}
printf("%p\n", arr);
打印的是数组首元素arr[0]
的地址。由于数组名本身就是指向数组首元素的指针,所以arr
和&arr[0]
是等价的。因此,它们打印的地址是相同的,都是数组的首地址。
printf("%p\n", &arr);
打印的是整个数组arr
的起始地址。在内存中,数组占据了一段连续的内存空间,&arr
就是整个数组的起始地址。
再来一个
#include <stdio.h>int main() {int arr[10] = {0};printf("arr = %p\n", arr); // 打印数组首元素的地址printf("&arr = %p\n", &arr); // 打印整个数组的起始地址printf("arr+1 = %p\n", arr+1); // 打印数组第二个元素的地址printf("&arr+1 = %p\n", &arr+1); // 打印下一个数组的起始地址return 0;
}
printf("arr = %p\n", arr);
和printf("&arr = %p\n", &arr);
打印的都是数组arr
的起始地址。因为数组名arr
本身就是指向数组首元素的指针,所以这两者的值是相同的。
printf("arr+1 = %p\n", arr+1);
打印的是数组的第二个元素的地址。由于整型数组中每个元素占用4个字节(假设为32位系统),所以arr+1
就是arr
的起始地址加上4个字节,即指向数组的第二个元素。
printf("&arr+1 = %p\n", &arr+1);
打印的是下一个数组的起始地址。在内存中,相邻的数组之间有一个间隔,这个间隔的大小是整个数组的大小。因此,&arr+1
实际上是指向下一个数组的起始地址。
数组指针的使用
看一段代码.
#include <stdio.h>// 打印二维数组,使用数组作为参数
void print_arr1(int arr[3][5], int row, int col) {int i, j;for(i = 0; i < row; i++) {for(j = 0; j < col; j++) {printf("%d ", arr[i][j]);}printf("\n");}
}// 打印二维数组,使用数组指针作为参数
void print_arr2(int (*arr)[5], int row, int col) {int i, j;for(i = 0; i < row; i++) {for(j = 0; j < col; j++) {printf("%d ", arr[i][j]);}printf("\n");}
}int main() {int arr[3][5] = {{1, 2, 3, 4, 5},{6, 7, 8, 9, 10},{11, 12, 13, 14, 15}};printf("Printing using print_arr1:\n");print_arr1(arr, 3, 5);printf("\nPrinting using print_arr2:\n");print_arr2(arr, 3, 5);return 0;
}
print_arr1
函数解释
void print_arr1(int arr[3][5], int row, int col)
这个函数的参数
arr
是一个二维数组,它是一个3x5
的整数数组。参数row
和col
分别表示行数和列数。在函数内部,我们使用嵌套循环遍历二维数组的每个元素,并使用arr[i][j]
访问它们。
print_arr2
函数解释
void print_arr2(int (*arr)[5], int row, int col)
这个函数的参数
arr
是一个指向包含5个整数的数组的指针。参数row
和col
仍然表示行数和列数。在函数内部,我们同样使用嵌套循环遍历二维数组的每个元素,但是这里使用arr[i][j]
访问它们。
值得注意的是,尽管在 print_arr2
中,我们传递的是 arr
,但实际上传递的是指向第一行的指针。这是因为在 C 语言中,数组名作为函数参数传递时,会退化为指向数组首元素的指针。因此,print_arr2
函数可以通过指针来遍历整个二维数组。
练习
int arr[5];
int *parr1[10];
int (*parr2)[10];
int (*parr3[10])[5];
int arr[5];
:这是一个包含5个整数的一维数组。
int *parr1[10];
:这是一个数组,数组中包含了10个整型指针。每个元素parr1[i]
可以指向一个整数。
int (*parr2)[10];
:这是一个指向包含10个整数的数组的指针。通过parr2
可以访问整个数组。
int (*parr3[10])[5];
:这是一个数组,数组中包含了10个指向包含5个整数的数组的指针。每个元素parr3[i]
可以指向一个长度为5的整数数组。
第四阶段:🔗 数组参数、指针参数的传递方式
欢迎来到第四阶段!在这里,我们将继续深入探讨C语言中有关函数参数传递的话题,重点介绍一维数组、二维数组、一级指针和二级指针作为函数参数的传递方式。通过了解这些传参方式的独特特点和灵活应用,我们将在C语言编程的旅程中迈出坚实一步。
一维数组传参
当你将一维数组作为函数参数传递时,实际上传递的是数组的首地址。这种方式使得函数内部可以操作数组元素,但无法获取数组的长度。下面,我们一起来看一个生动的例子吧!
#include <stdio.h>void printArray(int arr[], int size) {for (int i = 0; i < size; i++) {printf("%d ", arr[i]);}
}int main() {int arr[5] = {1, 2, 3, 4, 5};printArray(arr, 5); // 传递数组和数组长度作为参数return 0;
}
二维数组传参
在传递二维数组作为函数参数时,需要明确指定第二维的大小。这种传递方式在处理矩阵和图等二维数据结构时非常实用。让我们通过一个更详细的示例来深入理解!
#include <stdio.h>// 函数接受二维数组和行列数作为参数
void print2DArray(int arr[][3], int rows, int cols) {for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {printf("%d ", arr[i][j]);}printf("\n");}
}int main() {int arr[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};printf("Original 2D Array:\n");print2DArray(arr, 3, 3); // 传递二维数组和行列数作为参数return 0;
}
在这个示例中,我们定义了一个函数
print2DArray
,它接受一个二维数组和行列数作为参数,然后按行列的方式输出二维数组的内容。在main
函数中,我们创建了一个3x3的二维数组,并通过print2DArray
函数将其内容打印出来。
一级指针传参
一级指针作为函数参数传递时,实际上传递的是指针的地址。这种方式允许在函数内部修改指针指向的内容,但无法修改指针本身。让我们看看一个有趣的例子!
#include <stdio.h>void modifyPointer(int *ptr) {*ptr = 42; // 修改指针指向的内容
}int main() {int num = 10;int *ptr = #modifyPointer(ptr); // 传递指针作为参数printf("Value: %d\n", *ptr); // 输出修改后的值return 0;
}
二级指针传参
二级指针是指向指针的指针。传递二级指针作为函数参数时,传递的是指针的地址,允许在函数内部修改指针本身的值。来看一个有趣的示例吧:
#include <stdio.h>void modifyDoublePointer(int **pptr) {int newVal = 42;*pptr = &newVal; // 修改二级指针指向的值
}int main() {int num = 10;int *ptr = #int **pptr = &ptr;modifyDoublePointer(pptr); // 传递二级指针作为参数printf("Value: %d\n", **pptr); // 输出修改后的值return 0;
}
第五阶段:🔗 探索函数指针的神奇世界
欢迎来到第五阶段!在这里,我们将深入研究C语言中的一个强大而神秘的概念——函数指针。函数指针为我们提供了更高级的编程能力,允许我们像操作数据一样操作函数。让我们一起探索函数指针的神奇世界吧!
函数指针简介
函数指针是指向函数的指针变量。与指向数据的指针类似,函数指针存储函数的地址,使我们能够通过指针调用该函数。这种能力在回调函数、动态函数调用和多态性等场景中非常有用。
使用函数指针
以下是一个简单的例子,演示如何声明、赋值和调用函数指针:
#include <stdio.h>// 声明函数指针类型
typedef int (*Operation)(int, int);// 加法函数
int add(int a, int b) {return a + b;
}// 减法函数
int subtract(int a, int b) {return a - b;
}int main() {Operation operationPtr; // 声明函数指针变量operationPtr = add; // 赋值为add函数int result = operationPtr(5, 3); // 通过指针调用函数printf("Result: %d\n", result); // 输出结果return 0;
}
函数指针数组
函数指针可以组成数组,称为函数指针数组。这使我们可以通过索引来选择不同的函数。以下是一个使用函数指针数组的示例:
#include <stdio.h>int add(int a, int b) {return a + b;
}int subtract(int a, int b) {return a - b;
}int multiply(int a, int b) {return a * b;
}int main() {int (*operationPtr[3])(int, int); // 声明函数指针数组operationPtr[0] = add;operationPtr[1] = subtract;operationPtr[2] = multiply;int result = operationPtr[1](10, 5); // 调用subtract函数printf("Result: %d\n", result);return 0;
}
指向函数指针数组的指针
我们可以声明指向函数指针数组的指针,让我们一起看看它的用法:
#include <stdio.h>int add(int a, int b) {return a + b;
}int subtract(int a, int b) {return a - b;
}int multiply(int a, int b) {return a * b;
}int main() {int (*(*operationPtrPtr)[3])(int, int); // 声明指向函数指针数组的指针operationPtrPtr = &operationPtr; // 赋值为函数指针数组的地址int result = (*operationPtrPtr)[2](7, 3); // 通过指针调用multiply函数printf("Result: %d\n", result);return 0;
}
第六阶段:🔗 回调函数:让程序更灵活
欢迎来到第六阶段!在这里,我们将深入探讨C语言中的另一个重要概念——回调函数。回调函数是一种让程序更灵活的技术,通过它,我们可以将函数作为参数传递给其他函数,从而实现更动态的操作。让我们一起探索回调函数的奇妙之处!
回调函数简介
回调函数是指传递一个函数的指针作为参数给另一个函数,然后在后者中调用这个传递进来的函数。这种方式使得我们可以在运行时决定要执行哪些函数,实现更灵活的程序逻辑。
回调函数的应用
以下是一个简单的示例,展示如何使用回调函数来排序一个整数数组:
#include <stdio.h>
#include <stdlib.h>// 比较函数:升序排列
int compareAsc(const void *a, const void *b) {return (*(int *)a - *(int *)b);
}// 比较函数:降序排列
int compareDesc(const void *a, const void *b) {return (*(int *)b - *(int *)a);
}// 使用回调函数对数组进行排序
void sortArray(int arr[], int size, int (*compare)(const void *, const void *)) {qsort(arr, size, sizeof(int), compare);
}int main() {int arr[5] = {5, 2, 8, 1, 3};sortArray(arr, 5, compareAsc); // 使用升序比较函数排序printf("Ascending Order: ");for (int i = 0; i < 5; i++) {printf("%d ", arr[i]);}sortArray(arr, 5, compareDesc); // 使用降序比较函数排序printf("\nDescending Order: ");for (int i = 0; i < 5; i++) {printf("%d ", arr[i]);}return 0;
}
在这个示例中,我们使用了两个不同的比较函数,分别用于升序和降序排序。通过将比较函数作为参数传递给 sortArray
函数,我们实现了动态选择排序方式的功能。
结语:尖叫指针,飞跃编程界!🚀
来到本篇博客的终点,你是否感受到了指针的神奇魅力呢?从字符指针到数组指针,从函数指针到回调函数,我们一路探索,揭开了指针的奥秘面纱。
指针,如同瞬间连接你与计算机内部的魔法纽带,让操作数据、调用函数变得轻松自如。无论是在数组的海洋中航行,还是在函数的宇宙中穿梭,指针都是你最忠实的伙伴。
相信你已经在这趟指针之旅中汲取了丰富的知识。保持好奇心,继续探索,愿你的编程旅程一路飞升,创造出更多令人惊叹的代码艺术!不忘初心,一起向编程的星辰大海进发吧!🌟
相关文章:

指针进阶大冒险:解锁C语言中的奇妙世界!
目录 引言 第一阶段:🔍 独特的字符指针 什么是字符指针? 字符指针的用途 演示:使用字符指针拷贝字符串 字符指针与字符串常量 小试牛刀 第二阶段:🎯 玩转指针数组 指针数组是什么? 指针…...

2.0 Maven基础
1. Maven概述 Maven概念 Apache Maven是一个软件项目管理工具,将项目开发和管理过程抽象程一个项目对象模型(POM,Project Object Model)。 Maven作用 项目构建 提供标准的、跨平台的自动化项目构建方式。 依赖管理 方便快捷…...

在Linux虚拟机内配置nginx以及docker
目录 1、nginx源码包编译以及安装依赖 1、配置安装所需的编译环境 2、安装函数库(pcre、zlib、openssl) 2、安装nginx 1、获取源码包 2、解压编译 3、启动nginx服务 1、关闭防火墙 2、运行nginx 3、使用本地浏览器进行验证 3、安装docker 1、…...

数据结构-带头双向循环链表的实现
前言 带头双向循环链表是一种重要的数据结构,它的结构是很完美的,它弥补了单链表的许多不足,让我们一起来了解一下它是如何实现的吧! 1.节点的结构 它的节点中存储着数据和两个指针,一个指针_prev用来记录前一个节点…...

android Ndk Jni动态注册方式以及静态注册
目录 一.静态注册方式 二.动态注册方式 三.源代码 一.静态注册方式 1.项目名\app\src\main下新建一个jni目录 2.在jni目录下,再新建一个Android.mk文件 写入以下配置 LOCAL_PATH := $(call my-dir)//获取当前Android.mk所在目录 inclu...

MySQL中的索引
1.2.MySQL中的索引 InnoDB存储引擎支持以下几种常见的索引:B树索引、全文索引、哈希索引,其中比较关键的是B树索引 1.2.1.B树索引 InnoDB中的索引自然也是按照B树来组织的,前面我们说过B树的叶子节点用来放数据的,但是放什么数…...

idea中如何处理飘红提示
idea中如何处理飘红提示 在写sql时,总是会提示各种错误 查找资料,大部分都是说关提示,这里把错误提示选择为None即可 关掉以后,也确实不显示任何提示了,但总有一种掩耳盗铃的感觉 这个sms表明明存在,但是还…...
Elasticsearch使用中出现的错误
Elasticsearch使用中出现的错误 1、分页查询异常 在分页的过程中出现了一个问题是当查询的数据超过10000条的时候报了异常: from size must be less than or equal to: [10000]这个问题最快捷的解决方式是增大窗口大小: curl -XPUT http://127.0.0.…...

【IMX6ULL驱动开发学习】01.编写第一个hello驱动+自动创建设备节点(不涉及硬件操作)
目录 一、驱动程序编写流程 二、代码编写 2.1 驱动程序hello_drv.c 2.2 测试程序 2.3 编写驱动程序的Makefile 三、上机实验 3.1 NFS 挂载 3.2 测试示例 一、驱动程序编写流程 构造file_operations结构体 在里面填充open/read/write/ioctl成员 注册file_operations结…...

决策规划仿真平台搭建
决策规划仿真平台搭建 自动驾驶决策规划算法第二章第一节 决策规划仿真平台搭建 这部分的主要难点在于多个软件的连通与适配,环境的搭建总是折磨人的,主要是 4 个软件,各软件版本如下 Visual Studio2017PreScan8.5.0CarSim2019.0MATLAB2019b…...
计算图像哈希SHA-512
1、MATLAB实现 计算图像哈希值SHA-512,在文献[1]提到的算法如下: % Example Code: Create an MD5 crypto-hash of an arbitrary string, "str" % Main class of interest: System.Security.Cryptography.HashAlgorithm% Example String to hash with MD5 %…...

Android之消除APP图标的白色边框
有问题的效果: 解决方案: 第一步:app右键—>new—>Image Asset 第二步:上传Logo图标,选择每种分辨率,预览看效果,选择Resize,可以微调 第三步:点击 Nextÿ…...

java线程的优先级、守护线程的概念
1.线程的调度 抢占式调度 非抢占式调度 1.1 抢占式调度 优先级越高,抢到cpu的概率越高 1.2 守护线程 守护线程,非守护线程。当其他的非守护线程执行完毕以后,守护线程会陆续结束。 守护线程的应用场景...
asp.net core 6.0 efcore +sqlserver增删改查的demo
asp.net core 6.0 efcore sqlserver增删改查的demo 下面是一个使用ASP.NET Core 5.0和Entity Framework Core进行增删改查操作的示例。 首先,创建一个空的ASP.NET Core 6.0 Web应用程序项目。 然后,安装以下NuGet包: Microsoft.EntityFra…...

HC32L110B6芯片测试
到货之后,直观上感觉的确很小,小包装盒里面还装了说明书。 下载器单独在一个盒里面,但是这个T-U2T没用上,还是用的STLINK。 开发之前先去网上找了一些别人遇到的坑,的确不少。 涉及的方面也是挺全的,供电、…...
关于我乱删注册表导致电脑没有声音这件事
之前因为想彻底删除迅雷,照着网上进入注册表一顿乱删,也忘记删了啥,反正把一顿xmp的文件,和搜索出来迅雷的全删了。结果迅雷确实没了,被带走的还有电脑的声音。 很离谱,就试过了所有方法都没用,…...
Linux 命令 su 和 sudo 的区别
之前一直对 su 和 sudo 这两个命令犯迷糊,最近专门搜了这方面的资料,总算是把两者的关系以及用法搞清楚了,这篇文章来系统总结一下。 1. 准备工作 因为本篇博客中涉及到用户切换,所以我需要提前准备好几个测试用户,方…...
微信小程序:Mobx的使用指南
简要 微信小程序中有时需要进行全局状态管理,这个时候就需要用到Mobx.下面我们来看一下在小程序中是如何使用Mobx的 安装 pnpm i mobx-miniprogram4.13.2 mobx-miniprogram-bindings1.2.1 或 npm i mobx-miniprogram4.13.2 mobx-miniprogram-bindings1.2.1 或 yarn…...

【Spring Boot】Spring Boot项目的创建和文件配置
目录 一、为什么要学Spring Boot 1、Spring Boot的优点 二、创建Spring Boot项目 1、创建项目之前的准备工作 2、创建Spring Boot项目 3、项目目录的介绍 4、安装Spring Boot快速添加依赖的插件 5、在项目中写一个helloworld 三、Spring Boot的配置文件 1、配置文件的…...

Spring Cloud 智慧工地源码(PC端+移动端)项目平台、监管平台、大数据平台
智慧工地源码 智慧工地云平台源码 智慧建筑源码 “智慧工地”是利用物联网、人工智能、云计算、大数据、移动互联网等新一代信息技术,彻底改变传统建筑施工现场参建各方现场管理的交互方式、工作方式和管理模式,实现对人、机、料、法、环的全方位实时监…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...

若依登录用户名和密码加密
/*** 获取公钥:前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...