C语言:20250728学习(指针)

回顾

/*************************************************************************> File Name:    demo01.c> Author:       阮> Description:  > Created Time: 2025年07月28日 星期一 09时07分52秒************************************************************************/​#include <stdio.h>​/***指向一维数组指针**/int t_p1(){// 创建一个一维数组int arr[] = {10,20,30,40,50};// 计算数组大小int len = sizeof(arr) / sizeof(arr[0]);  ​// 创建一个数组指针指向一维数组arrint (*p)[len] = &arr;// 借助数组指针遍历数组for (int i = 0; i < len; i++){// p 指向 arr这个数组,p存储了arr这个数组的地址// 如果通过指针访问数组:*p  *和[]在一起,[]的优先级大于*printf("%-4d", (*p)[i]);}printf("\n");printf("==============一维===============\n");}​/*二维*/int t_p2(){// 创建一个二维数组int arr[][3] = {{10,20,30},{100,200,300},{1000,2000,3000}};// 获取行和列的容量int row_len = sizeof(arr) / sizeof(arr[0]);int col_len = sizeof(arr[0]) / sizeof(arr[0][0]);​// 方式1,二维数组指针指向二维数组   不推荐int (*p)[][3] = &arr;​// 遍历数组for (int i = 0; i < row_len; i++){for (int j = 0; j < col_len; j++){printf("%-6d", (*p)[i][j]);}}printf("\n");printf("===============二维===============\n");//方式2,一维数组指针指向二维数组,本质上是一体维数组指针指向二维数组的行(默认首行)推荐// &arr:获取该二维数组的地址,范围作用于整个数组// arr:数组名默认指向第一个元素,这里就是行,默认首行,范围作用于整个行,等价于 &arr[0]// 数组参与指针运算,会降级为指针int (*p1)[3] = arr;for(int i = 0;i < row_len;i++){for(int j=0;j < col_len;j++){printf("%-6d",p1[i][j]);printf("%-6d",(*(p1+i))[j]);//数组参与指针运算,会降级为指针printf("%-6d",*(p1[i]+j));//列偏移printf("%-6d",*(*(p1+i)+j));//列偏移​​}}printf("\n");printf("================方式2==============\n");}​int main(int argc,char *argv[]){t_p1();t_p2();return 0;}

指针

数组指针与指针数组

数组指针
指针和数组中符号优先级
 ()> [] > *
通过指针引用二维数组
表示形式含义地址/值
arr二维数组名,指向一维数组arr[0],0行首地址2000
arr[0],*(arr+0),*arr0行0列元素地址,数组降级为指针2000
arr + 1&arr[1]1行首地址2008
arr[1],*(arr + 1)1行0列元素arr[1][0]的地址2008
arr[1]+2,*(arr+1)+2,&arr[1][2]1行2列元素arr[1][2]的地址2012
*(arr[1]+2),*(*(arr+1)+2),arr[1][2]1行2列元素arr[1][2]的值元素值为13

注意:二维数组中,数组整体的地址值 == 数组中0行元素的地址值 == 数组中0行0列元素的地址值

案例
案例1
  • 需求:用指向元素的指针变量输出二维数组元素的值

  • 代码:

    /*************************************************************************> File Name:    demo02.c> Author:       阮> Description:  > Created Time: 2025年07月28日 星期一 10时46分40秒************************************************************************/​#include <stdio.h>​int main(int argc,char *argv[]){// 定义一个二维数组int arr[3][4] = {10,20,30,40,100,200,300,400,1000,2000,3000,4000};​// 定义一个指针变量,用来指向数组中的元素int *p = /* *(arr+0) |*/ *arr /* | arr[0] */;​// 获取元素个数 = 行容量 * 列容量int len = (sizeof(arr)/sizeof(arr[0])) * (sizeof(arr[0])/sizeof(arr[0][0]));​// 使用单层for循环遍历二维数组,列for (; p < arr[0] + len; p++){// 每四个一行  p1 - p2 = (p1地址 - p2地址) / sizeof(type)if ((p - arr[0]) % 4 == 0 && p != arr[0]) printf("\n");​printf("%-6d", *p);}​printf("\n");​return 0;}
案例2:
  • 需求:数组指针- 输出二维数组任意行任意列的元素的值

  • 代码:

    /*************************************************************************> File Name:    demo03.c> Author:       阮> Description:  > Created Time: 2025年07月28日 星期三 10时57分26秒************************************************************************/​#include <stdio.h>​int main(int argc,char *argv[]){// 定义一个二维数组int arr[3][4] = {1,3,5,7,11,33,55,77,111,333,555,777};​// 创建一个数组指针指向二维数组int (*p)[4] = arr; // 二维数组中的第一个元素就是首行  int (*p)[3][4]​// 创建两个变量,接收控制台输入的行和列int row, col;​printf("请输入行号和列号:\n");scanf("%d,%d",&row,&col);​printf("arr[%d][%d]=%d,%d,%d,%d\n",row,col,*(*(p+row)+col),(*(p+row))[col],*(p[row]+col),p[row][col]);​return 0;}
指针数组

定义:指针数组是一个数组,数组中每一个元素都是一个指针。

特点:

  • 先有指针,后有数组

  • 指针数组的本质是一个数组,只是数组中的每一个元素是指针。

语法:

 数据类型 *数组名[容量];

案例:

/*************************************************************************> File Name:    demo03.c> Author:       阮> Description:  > Created Time: 2025年07月28日 星期一 11时31分18秒************************************************************************/​#include <stdio.h>​int main(int argc,char *argv[]){// 定义三个变量int a = 10, b = 20, c = 30;​// 定义指针数组:先有指针,后有数组int *arr[3] = {&a, &b, &c};​// 获取大小int len = sizeof(arr) / sizeof(arr[0]);​// 遍历数组for (int i = 0; i < len; i++){printf("%-3d", *arr[i]);}​printf("\n");​return 0;}

建议:我们一般使用指针数组处理字符串,后续专门讲解。

数组指针与指针数组的区别
对比项指针数组数组指针
定义数组元素均为指针的数组指向一个完整数组的指针
存储内容存储多个指针,每个元素指向不同内存地址存储单个指针,指向一个完整的数组(首地址)
内存分配每个指针元素独立分配内存,可能分散指向的数组内存连续,指针本身存储数组首地址
语法示例int *arr[5] (元素为5个int*指针)int (*arr)[5] (指向5个int的数组的指针)
访问方式通过下标访问指针元素,再解引用: *arr[i]先解引用指针得到数组,再访问元素: (*arr)[i]
使用场景管理多个独立指针(如字符串数组、动态结构体数组)操作多维数组(如传递二维数组的行指针)
内存布局[ptr1] → 数据1 [ptr2] → 数据2 ... ptr → [数据1][数据2]...
示例代码int a=1, b=2;int *arr[] = {&a, &b};int arr[2][3] = {1,2,3,4,5,6};int (*ptr)[3] = arr;

字符数组与字符指针

字符串实现

在C语言中,表示一个字符串有以下两种方式:

① 数组形式:用字符数组存放一个字符串

② 指针形式:用字符指针指向一个字符串

案例
/*************************************************************************> File Name:    demo04.c> Author:       阮> Description:  > Created Time: 2025年07月28日 星期一 14时15分31秒************************************************************************/​#include <stdio.h>​/*** 方式1:使用字符数组实现字符串*/ void str_test1(){// 定义一个伪字符串char str[] = "I LOVE YOU";// 数组名是一个常量,也就是不支持赋值// str = "YUE QIAN"; // 编译报错,常量不支持修改,替代方案:strcpy(str,"YUE QIAN");printf("%s\n", str); // 数组在传参时,会被降级为指针}​/*** 方式2:使用字符指针指向字符串*/ void str_test2(){// 定义一个伪字符串char *str = "I LOVE YOU"; // 指针str指向一个字符串常量// 改变str的指向// str = "YUE QIAN";printf("%s\n", str);}​int main(int argc,char *argv[]){str_test1();str_test2();​char arr[200];char *str = arr; // 局部变量,如果未初始化,默认是随机值,如果是指针变量,地址值就是随机printf("请输入一个字符串:\n");scanf("%s", str);printf("%s\n", str);​return 0;}
 ​

注意:字符数组和字符指针变量都能实现字符串的存储与运算。(字符指针---> 字符类型的指针变量)

字符数组和字符指针的联系
概念
  • 字符数组由元素组成,每个元素中存放一个字符;而字符指针(指向char类型的指针变量)中存放的是地址;

  • 只能对字符数组中的各个元素赋值,而不能用赋值语句对整个字符数组赋值。

     char arr[3] = {};   // 等价于 {'\0'}; 等价于 {0};arr[2] = 'A';       // 正确,对字符数组的元素赋值​arr = {'E','D','F'};// 错误,数组名是常量,不能对其进行整体赋值
  • 字符数组名虽然代表地址,但是数组名的值不能改变,因为数组名是常量。

    char a = 'A';char arr[50] = {};​char *p = arr; // 指针p指向数组第一个元素,p存储的是arr数组中第一个元素的地址​p = &a;   // 改变指针p的指向,使其指向变量a,p存储的是a的地址​arr = &a; // 错误:数组名虽然是指针,但是数组名同时也是常量,所以不能赋值​p++; // p指向arr的第2个元素arr+5;  *p = 'W';printf("%c %c\n", *p, *arr);​return 0;}​
  • 对于字符串中字符的存取,可以用下标法,也可以用指针法。

    /*************************************************************************> File Name:    demo05.c> Author:       阮> Description:  > Created Time: 2025年05月21日 星期三 14时58分00秒************************************************************************/​#include <stdio.h>​int main(int argc,char *argv[]){// 使用两种方式创建字符串char str1[] = "你好,双哥哥!";char *str2 =  "你好,豪哥哥!";// 0x11​// 赋值测试// str1 = "你好,强哥哥!"; // 错误,数组一旦创建,就无法改变其值。str2 = "你好,帅哥哥!";// 0x12​// 打印测试printf("%s,%s\n", str1, str2);​// 测试从控制台获取一个字符串// char *str;// 此时默认值是NULL,NULL对应的空间地址0x00000000,这块空间拒绝访问// printf("请输入一个字符串:\n");// scanf("%s",str);// printf("输出-%s\n",str);// 输出NULL​// 注意:从控制台接收一个字符串只能用字符数组char a[] = "I LOVE YOU!";char *b  = "I LOVE YOU!";​printf("%c,%c\n%c,%c\n%s,%s\n",a[2],*(a+2),b[2],*(b+2),a+2,b+2);// L,L L,L 1 2return 0;}
字符串作为形参

定义

  • 实参与形参都可以是字符数组

    void fun(char str[], int len) {..}void main(){char str[] = "hello";int len = sizeof(str) / sizeof(str[0]);fun(str, len)}
  • 实参用字符数组,形参用字符指针

     void fun(char *str, int len) {..}void main(){char str[] = "hello";int len = sizeof(str) / sizeof(str[0]);fun(str, len)}
  • 形参和实参都是字符指针。(在函数内部不能对字符串常量中的字符做修改)

     /*************************************************************************> File Name:    demo06.c> Author:       阮> Description:  > Created Time: 2025年07月28日 星期一 15时26分14秒************************************************************************/​#include <stdio.h>​void fun(char *str, int len) {printf("%s\n", str);// 0x1000 str依然指向“hello"这个常量空间​// *(str+1) = 'E';// 编译错误  不能修改"hello"这个常量空间的数据​// str[2] = 'L';  // 编译错误​str = "zhangsanfeng"; // 0x2000 此时并没有改变常量空间的数据,只是改变了指针的指向​printf("%s\n", str);}​void main(){char *str = "hello"; // 0x1000 str指向的"hello"是一个常量空间,常量空间不支持修改int len = sizeof(str) / sizeof(str[0]);fun(str, len); // 0x1000}
  • 实参是字符指针,形参是字符数组。(在函数内部不能对字符串常量中的字符做修改)

    /*************************************************************************> File Name:    demo06.c> Author:       阮> Description:  > Created Time: 2025年07月28日 星期一 15时26分14秒************************************************************************/​#include <stdio.h>​void fun(char str[], int len) {printf("%s\n", str);// 0x1000 str依然指向“hello"这个常量空间​// *(str+1) = 'E';// 编译错误  不能修改"hello"这个常量空间的数据​// str[2] = 'L';  // 编译错误​str = "zhangsanfeng"; // 此时并没有改变常量空间的数据,只是改变了指针的指向​printf("%s\n", str);}​void main(){// char str[] = {'h','e','l','l','o','\0'};  // 这个可以看做是字符串变量,这个是支持修改元素char *str = "hello"; // 0x1000 str指向的"hello"是一个常量空间,常量空间不支持修改int len = sizeof(str) / sizeof(str[0]);fun(str, len);// 0x1000}
注意
  1. 字符数组在创建的时候,会在内存中开辟内存空间,内存空间可以存放字符数据;字符指针在创建的时候,需要依赖于字符数组,字符指针在内存开辟的内存空间中,存放的是数组元素的地址。字符指针的创建依赖于字符数组,字符数组可以独立存在,而字符指针不能独立存在。

  2. 字符数组可以初始化,但是不能赋值;字符指针可以初始化,也可以赋值。

      char str1[] = "hello"; // 对数组初始化str1 = "hi"; // 对数组赋值,此时错误str1[0] = 'H';  // 对数组中的元素赋值,此时正确
案例
案例1
  • 字符指针作为函数参数:用函数调用实现字符串的复制以及长度计算

  • 代码:

    /*************************************************************************> File Name:    demo07.c> Author:       阮> Description:  > Created Time: 2025年07月28日 星期一 15时50分22秒************************************************************************/​#include <stdio.h>​/*** 定义一个函数,实现字符串拷贝* @param source 拷贝的源字符串,该字符串不能被修改* @param dest 需要拷贝的目标数组* @return 字符串的长度*/ int _str_cpy(const char *source, char *dest){// 定义一个循环变量register int i = 0;​// 遍历循环while (source[i] != '\0'){// 实现拷贝*(dest + i) = *(source + i); // 等价于 dest[i] = source[i];i++;}​// 拷贝结束,一定要给dest中插入\0*(dest + i) = '\0';​return i;}​int main(int argc,char *argv[]){char source[20],dest[20];​printf("请输入一个字符串:\n");scanf("%s", source);​int size = _str_cpy(source, dest);​printf("字符串:%s的长度是%d\n", dest, size);​return 0;}
案例2
  • 需求:字符指针作为函数的参数-给定一个字符串,截取start到end之间的字符串,含头不含尾

  • 代码:

     /*************************************************************************> File Name:    demo08.c> Author:       阮> Description:  > Created Time: 2025年07月28日 星期一 16时07分40秒************************************************************************/​#include <stdio.h>​/*** 定义一个函数,实现字符串的截取* @param source 源字符串(字符数组、字符串常量、字符指针)* @param start  开始位置* @param end    结束位置* @param dest   目标数组(字符数组)* @return 目标字符串长度*/​int str_substr(char *source,int start,int end,char *dest){register int i = 0,k=0;// 遍历字符串while(source[i] != '\0'){// 根据start和end截取if(i >= start && i < end)// 含头不含尾{*(dest + k) = *(source + i);k++;}i++;}*(dest + k) = '\0';​return k;}​int main(int argc,char *argv[]){char *str = "abcdefg";char dest[26];int len = str_substr(str,2,5,dest);​printf("%s,%s,%d\n",str,dest,len);return 0;}

函数指针与指针函数

指针函数

定义:

本质上是上函数,这个函数的返回值类型是指针,这个函数称之为指针函数。(返回值是指针的函数叫做指针函数)

语法:

 //写法1返回类型*  函数名(形参列表){函数体;return 指针;}​//写法2返回类型  *函数名(形参列表){函数体;return 指针;}

举例:

 int *get(int a){int *p = &a;return p;}​int main(){int *a = get(5);printf("%d\n", *a);}

注意:

在函数中不要直接返回一个局部变量的地址。因为函数调用完毕后,随着栈帧的回收,变量空间会销毁,使得返回的地址就不明确,此时返回的指针叫做野指针。

解决方案:

如果非要访问,可以给这个局部变量添加(定义的时候添加)static,可以延长它的生命周期,从而避免野指针(尽量少用,因为存在内存泄漏)

演示案例:

 /*************************************************************************> File Name:    demo0.c> Author:       阮> Description:  > Created Time: 2025年07月28日 星期四 14时22分07秒************************************************************************/#include <stdio.h>int *add(int a, int b){static int sum;sum = a + b;return &sum;// 执行完return 作为函数作用域的布局变量sum的空间被释放}int main(int argc,char *argv[]){int *res = add(5,3);  // 接收到了地址,但是地址对应的空间已经释放printf("%d\n", *res);return 0;}
案例
  • 需求:有若干个学生,每个学生有4门成绩,要求在用户输入学号(int id)后,能输出该学生的全部成绩(float scores[4]),用指针函数实现。

  • 代码:

     /*************************************************************************> File Name:    demo09.c> Author:       阮> Description:  > Created Time: 2025年07月28日 星期一 17时11分38秒************************************************************************/​#include <stdio.h>​/*** 定义一个函数,要求输入学号,返回该学号对应学生的4门成绩* @param all:所有人的成绩传进来 查找源头* @param id:要检索学生的学号* @return id对应学生的4门成绩*/ float* search(float (*all)[4], int id){// 定义一个指针变量,用来接收查询到的学生的所有成绩float *pt;​pt = *(all + id);// 行偏移 {10,20,30,40}​return pt;}​int main(int argc,char *argv[]){// 准备一个二维数组,存储3个学生的成绩float scores[3][4] = {{60,70,80,90}, // 0x2000  0x2004  0x2008 0x200C{66,77,88,99}, // 0x2010  0x2014  0x2018 0x201C{61,71,81,91}};​// 定义一个变量,用来接收学生学号int id;printf("请输入学生学号(0~2):\n");scanf("%d", &id);printf("第%d个学生的成绩:\n", id);​// 创建一个指针,用来接收成绩float *p;// 0x11 --> 0x2000p = search(scores, id);// 0x21 --> 0x2000​// 遍历for (; p < scores[id] + 4;  p++){printf("%5.2f\t", *p);}// *(p + i)printf("\n");​return 0;}

章节练习

  1. 利用指针变量将一个数组中的数据反向输出。

  2. 利用指针变量计算下标为奇数的数组的和;

  3. 确认整型,字符型,浮点型指针变量的大小;

  4. 利用指针变量输出字符数组中的所有字符。

  5. 编写一个函数,用指针变量做参数,用于求出一个浮点型数组元素的平均值。

  6. 编写函数,要求用指针做形参,分别实现以下功能: (1)求一个字符串长度 (2)在一个字符串中统计大写字母的个数 (3)在一个字符串中统计数字字符的个数

  7. 编写函数,要求用指针做形参,实现将二维数组(行列相同)的进行转置(行列数据互换): int (*p)[N]

  8. 编写函数,要求用指针做形参,实现统计二维数组上三角中的0 的数量:

  9. 编写一个指针函数,返回二维数组中最大元素的地址。

  10. 面试题

    1)定义整形变量i; 2)p为指向整形变量的指针变量; 3)定义整形一维数组p,它有n 个整形元素; 4)定义一维指针数组p,它有n个指向整形变量的指针元素; 5)定义p为指向(含有n个整形元素的一维数组)的指针变量; 6)p为返回整形函数值的函数; 7)p为返回一个指针的函数,该指针指向整形数据; 8)p为指向函数的指针变量,该函数返回一个整形值; 9)p是一个指向整形指针变量的指针变量;

  11. 动态申请一个具有10个float类型元素的内存空间,从一个已有的数组中拷贝数据,并找出第一次出现 12.35 的下标位置,并输出。

  12. 动态申请一个整型数组,并给每个元素赋值,要求删除第3个元素;

  13. 动态申请一个整型数组,并给每个元素赋值,要求在第4个元素后插入100;

  14. 附加题【选做】: 编写一个函数,实现 memmove 的功能。

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

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

相关文章

esp32s3文心一言/豆包(即火山引擎)大模型实现智能语音对话--流式语音识别

一、引言 在之前的帖子《Esp32S3通过文心一言大模型实现智能语音对话》中&#xff0c;我们介绍了如何使用Esp32S3微控制器与文心一言大模型实现基本的智能语音对话功能&#xff0c;但受限于语音识别技术&#xff0c;只能处理2-3秒的音频数据。为了提升用户体验&#xff0c;满足…

面试150 最长递增子序列

思路 定义 dp[i] 表示以第 i 个元素结尾的最长递增子序列的长度&#xff0c;初始时每个位置的最长子序列长度为 1。然后通过双重循环遍历每一对元素 j < i&#xff0c;如果 nums[i] > nums[j]&#xff0c;说明 nums[i] 可以接在 nums[j] 的递增序列之后&#xff0c;更新 …

TCP 套接字--服务器相关

1.创建 TCP 套接字int server_sockfd socket(AF_INET,SOCK_STREAM, 0);函数原型&#xff1a;#include <sys/socket.h>int socket(int domain, int type, int protocol);domain协议族&#xff08;地址族&#xff09;AF_INET&#xff08;IPv4&#xff09;type套接字类型SO…

六、搭建springCloudAlibaba2021.1版本分布式微服务-admin监控中心

前言Spring Boot Actuator 是 spring-boot 自带监控功能 &#xff0c;可以帮助实现对程序内部运行情况监控&#xff0c;比如监控状况、Bean 加载情况、环境变量、日志信息、线程信息等。 Spring Boot Admin是一个针对 spring-boot 的 actuator 接口进行 UI 美化封装的监控工具。…

轻量级远程开发利器:Code Server与cpolar协同实现安全云端编码

前言&#xff1a;作为一款专为Web环境设计的VS Code托管方案&#xff0c;Code Server通过精简架构重新定义了远程开发体验。其核心优势在于将完整的编辑器功能封装于轻量容器中——仅需不到200MB内存即可运行基础服务&#xff0c;并支持在树莓派等低性能设备上流畅操作。系统采…

图论:最小生成树

今天要介绍两中最小生成树的算法&#xff0c;分别是prim算法和kruskal算法。 最小生成树是所有节点的最小连通子图&#xff0c;即&#xff1a;以最小的成本&#xff08;边的权值&#xff09;将图中所有节点链接到一起。 图中有n个节点&#xff0c;那么一定可以用n-1条边将所有节…

haproxy七层代理

1、负载均衡Load Balance(LB) 概念 负载均衡&#xff1a;是一种服务或基于硬件设备等实现的高可用反向代理技术&#xff0c;负载均衡将特定的业务(web服务、网络流量等)分担给指定的一个或多个后端特定的服务器或设备&#xff0c;从而提高了 公司业务的并发处理能力、保证了业务…

【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 微博文章数据可视化分析-点赞区间实现

大家好&#xff0c;我是java1234_小锋老师&#xff0c;最近写了一套【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasecharts)视频教程&#xff0c;持续更新中&#xff0c;计划月底更新完&#xff0c;感谢支持。今天讲解微博文章数据可视化分析-点赞区间实现 视频…

Redis实战(3)-- 高级数据结构zset

有序集合&#xff08;ZSET&#xff09;&#xff1a;可以用作相关有序集合相对于哈希、列表、集合来说会有一点点陌生,但既然叫有序集合,那么它和集合必然有着联系,它保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序。但是它和列表使用索引下标作为排序依据…

Mistral AI开源 Magistral-Small-2507

宣布Magistral——Mistral AI推出的首款推理模型&#xff0c;专精于垂直领域、具备透明化特性与多语言推理能力。 最优秀的人类思维并非线性——它穿梭于逻辑、洞见、不确定性与发现之间。推理型语言模型让我们得以将复杂思考和深度理解交由AI增强或代劳&#xff0c;提升了人类…

【Kotlin】如何实现静态方法?(单例类、伴生对象、@JvmStatic)

静态方法 静态方法&#xff08;类方法&#xff09;&#xff1a;不需要创建实例就可以调用&#xff08;直接通过类名调用&#xff09;的方法 Java 中的静态方法&#xff08;static&#xff09; public class Util {public static void doAction() {//...} }调用&#xff1a;Util…

SQL Schema 和Pandas Schema什么意思

在数据处理和分析领域&#xff0c;SQL Schema 和 Pandas Schema 分别指的是在不同数据处理环境中数据的结构定义&#xff0c;以下为你详细介绍&#xff1a;SQL Schema含义SQL Schema&#xff08;模式&#xff09;是数据库对象的一个逻辑容器&#xff0c;它定义了数据库中表、视…

机器学习(一)KNN,K近邻算法(K-Nearest Neighbors)

&#x1f4a1; 建议初学者掌握KNN作为理解其他复杂算法&#xff08;如SVM、决策树、神经网络&#xff09;的基石。K近邻算法&#xff08;K-Nearest Neighbors, KNN&#xff09;详解&#xff1a;原理、实践与优化K近邻算法&#xff08;K-Nearest NeighboKrs&#xff0c;简称KNN&…

Qt 多线程数据库操作优化

在多线程应用中&#xff0c;数据库操作往往是性能瓶颈与稳定性风险的高发区。当多个线程同时读写数据库时&#xff0c;若处理不当&#xff0c;轻则出现查询卡顿、事务冲突&#xff0c;重则导致数据错乱、连接泄漏甚至程序崩溃。Qt作为跨平台框架&#xff0c;提供了QSql系列类支…

Qt 状态机框架:复杂交互逻辑的处理

Qt状态机框架&#xff08;Qt State Machine Framework&#xff09;是一个强大的工具&#xff0c;用于简化复杂的交互逻辑和状态管理。它基于UML状态图概念&#xff0c;提供了声明式的方式来定义对象行为&#xff0c;特别适合处理具有多种状态和转换的场景&#xff08;如GUI交互…

【docker】DM8达梦数据库的docker-compose以及一些启动踩坑

摘要&#xff1a;本文介绍了通过docker-compose配置启动达梦数据库(DM8)的方法。配置包括容器镜像、端口映射、数据卷挂载以及关键环境变量设置&#xff08;如字符集、大小写敏感等&#xff09;。也说明了启动过程可能遇到的一些问题。通过docker-compose启动达梦数据库可以按照…

服务器中的防火墙设置需要打开吗

服务器中的防火墙属于是一种保护计算机网络不会受到未经授权的网络设备所访问的技术手段&#xff0c;防火墙还有着将内部网络和外部网络进行隔离的功能&#xff0c;在网络之间创建安全屏障&#xff0c;以此来保护网络中数据的安全。防火墙是一种网络安全系统&#xff0c;可以帮…

Java项目:基于SSM框架实现的社区团购管理系统【ssm+B/S架构+源码+数据库+毕业论文+答辩PPT+远程部署】

摘 要 使用旧方法对社区团购信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在社区团购信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。 这次开发的社区团购系统有…

介绍一下static关键字

在Java中&#xff0c;被static修饰的成员称为静态成员&#xff0c;static关键字可以用来修饰方法或者成员变量&#xff0c;且被static修饰的方法或者成员变量属于类方法或者类属性&#xff0c;也就是说被static修饰的方法或者成员变量不是单独存储在某一个对象的空间&#xff0…

【Java学习|黑马笔记|Day23】网络编程、反射、动态代理

【DAY23】 文章目录【DAY23】一.网络编程1&#xff09;三要素1.1&#xff09;IPInetAddress类的使用1.2&#xff09;端口号1.3&#xff09;协议2.1&#xff09;UDP协议发送数据2.2&#xff09;UDP协议接收数据2.3&#xff09;UDP的三种通信方式3.1&#xff09;TCP协议的发送和接…