【C语言】第八期——指针、二维数组与字符串

目录

1 初始指针

2 获取变量的地址

3 定义指针变量、取地址、取值

3.1 定义指针变量

3.2 取地址、取值

4 对指针变量进行读写操作

5 指针变量作为函数参数

6 数组与指针

6.1 指针元素指向数组

6.2 指针加减运算(了解)

6.2.1 指针加减具体数字 

6.2.2 指针加减指针

6.3 数组名与数组元素首地址的关系

6.4 数组作为函数参数

7 二维数组以及字符串与指针

7.1 二维数组的定义方法

7.1.1 定义一个二维数组 

7.1.2 访问二维数组

7.2 定义字符串的几种方法

7.3 字符串数组

7.4 strcat 连接字符串

7.5 strcpy 字符串复制(拷贝)函数


1 初始指针

通过前面的教程我们知道变量是用来存储数据的,变量的本质是给存储数据的内存地址起了一个好记的别名

比如我们定义了一个变量 int a= 10 ,这个时候可以直接通过a这个变量来读取内存中保存的10 这个值,在计算机底层a这个变量其实对应了一个内存地址

指针也是一个变量,但它是一种特殊的变量,它存储的数据不是一个普通的值,而是另一个变量的内存地址

每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表 示了在内存中的一个地址

刚开始学C语言的指针操作,我们只需要记住两个符号 :&(取地址) 和 *(根据地址取值 /定义指针变量)


2 获取变量的地址

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。C语言中使用&字符放在变量 前面对变量进行取地址操作

#include <stdio.h>
int main(void)
{int a = 10;printf("a的地址是:%p\n", &a);return 0;
}

3 定义指针变量、取地址、取值

3.1 定义指针变量

指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:

type *var-name;

在这里,type 是指针的基类型,它必须是一个有效的 C 数据类型,var-name 是指针变量的名称。用 来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是 指针

以下是有效的指针声明:

int* ip;    //一个整型的指针
double* dp; //一个 double 型的指针
float* fp;  //一个浮点型的指针
char* ch    //一个字符型的指针

所有指针的值都是一个地址,不管是整型、浮点型、字符型,还是其他的数据类型,都是一样的,都是 一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同


3.2 取地址、取值

#include <stdio.h>
int main(void)
{// 定义一个int变量aint a = 10;printf("a的地址是:%p\n", &a);// 定义int类型的指针变量pint* p_a = &a;printf("指针p_a的值:%p\n", p_a);printf("指针p_a的地址:%p\n", &p_a);printf("a的值:%d\n", a);printf("根据指针p_a的值去内存取值得到的结果为:%d", *p_a);return 0;
}

总结:

  • 取地址操作符&和取值操作符是一对互补操作符, & 取出地址, 根据地址取出地址指向的值
  • 对变量进行取地址(&)操作,可以获得这个变量的地址
  • 指针变量的值是地址
  • 对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值

4 对指针变量进行读写操作

#include <stdio.h>
int main(void)
{int a = 10;int b = 20;int* p1, * p2; // 定义指针变量 p1、 p2p1 = &a;// p1 指向变量 ap2 = p1;// p2 指向变量 aprintf("&a=%p p1=%p p2=%p\n", &a, p1, p2);*p1 = 20;printf("a的值%d,取指针得到的值%d", a, *p1);return 0;
}

运行结果:

&a=000000612A17FA74 p1=000000612A17FA74 p2=000000612A17FA74
a的值20,取指针得到的值20


5 指针变量作为函数参数

在C语言中,函数参数不仅可以是字符型、整型、浮点型等,还可以是指针类型,作用是将变量地址传递给函数形参

#include <stdio.h> 
void modify1(int *c) 
{*c = 20;
}
int main(void) {int a = 10;modify1(&a);printf("%d", a);return 0;
}

6 数组与指针

6.1 指针元素指向数组

数组本质上是一片连续的内存空间,每个数组元素都对应一块独立的内存空间,它们都有相应的地址。

因此,指针变量既然可以指向变量,也就可以指向数组元素

数组的构成本质上是:数组名[偏移量]

数组名就代表第一个元素的地址,偏移量就是在此基础上偏移

数组的元素本质上完全可以当做是单独的变量对待,只不过没有名称而已

int a[5]={1,2,3,4,5}; //定义长度为5的int数组
int *p_a=&a[0]; //定义指向int变量的指针变量p_a,把a数组第0个元素地址赋给指针变量p_a

注意:&a[0]等价于&(a[0]),由于[ ]运算符比取地址运算符&优先级高,因此&(a[0])中的小括号可以省略,简写为:&a[0]

在计算机中内存的最小单位是字节,每个字节都对应一个地址

如果一个变量占用多个字节,就会占用 多个内存地址

例如: char 类型变量占1字节就对应1个地址,short 类型变量占2字节对应2个地址,int 类型变量占4 字节对应4个地址.....·其他类型依次类推

同理,数组元素类型不同占用的内存地址也不同

下面通过例子来验证以上分析

#include<stdio.h>
int main(void)
{char c[5];short s[5];int i;for (i = 0; i < 5; i++){printf("&c[%d]=%p ", i, &c[i]);printf("&s[%d]=%p \n", i, &s[i]);}return 0;
}

运行结果:

&c[0]=000000000061FE17 &s[0]=000000000061FE0C

&c[1]=000000000061FE18 &s[1]=000000000061FE0E

&c[2]=000000000061FE19 &s[2]=000000000061FE10

&c[3]=000000000061FE1A &s[3]=000000000061FE12

&c[4]=000000000061FE1B &s[4]=000000000061FE14

说明:不同设备上面输出的地址可能不一样的,数组中每个元素地址都是连续的


6.2 指针加减运算(了解)

6.2.1 指针加减具体数字 

指针本质上就是内存地址,在32 位操作系统下,内存地址是 4 字节的整数。既然是整数就可以进行 加、减、乘、除等算术运算。不过需要注意的是,在 C 语言中一般只讨论指针加、减运算,乘、除等其 他算术运算都没有意义

在实际开发中,指针加、减运算多用于数组(或连续内存空间)。当指针变量p 指向数组元素时,p+1 表 示指向下一个数组元素,p-1 表示指向上一个数组元素

#include <stdio.h>
int main(void)
{int a[3] = { 1, 2, 3 };int* p = &a[0];// 指针 p 指向 a[0]printf("%p %d\n", p, *p); // 输出 a[0] 的地址 和 a[0] 的值p = p + 1;// p 加 1printf("%p %d\n", p, *p); // 输出 a[1] 的地址 和 a[1] 的值return 0;
}

运行结果:

000000811557F968 1
000000811557F96C 2

注意:实现指针加减的时候需要注意越界问题


6.2.2 指针加减指针

在C语言中,两个指针相加是没有意义的,而两个指针相减却有特殊的意义,不过只有当两个指针都指向同一数组中的元素时才有意义

一个数组中的元素时,对它们进行减法运算,得到的结果是这两个指针所指向元素之间相隔的元素个数 (不是之间有的个数,之间有的元素数要在此基础上减一),而不是它们地址差值的字节数。其计算方式是用两个指针的地址差值除以指针所指向数据类型的大小

用公式表示为:(指针2的地址 - 指针1的地址) / sizeof(指针所指向的数据类型)


6.3 数组名与数组元素首地址的关系

C语言中,数组名与数组首元素地址等价。也就是说,在程序中,输出数组名与输出数组首元素地址是相同的

#include <stdio.h>
int main(void)
{int num[5];printf("%p\n", num);     // 输出数组名printf("%p\n", &num[0]); // 输出数组首元素地址return 0;
}

输出结果:

000000000061FE00

000000000061FE00

我们就可以通过把数组名复制给指针变量,来把数组首地址给指针变量

#include <stdio.h>int main(void){int num[5] = {1, 2, 3, 4, 5};int *p_num = num; // 把num的首地址赋值给指针变量printf("p_num指针的值=%p \n p_num对应数组元素的值%d", p_num, *p_num);return 0;}

我们也可以通过p_num来访问数组里面的每个元素

 #include <stdio.h>int main(void){int num[5] = {1, 2, 3, 4, 5};int *p_num = num; // 把num的首地址赋值给指针变量printf("p_num指针的值=%p ,num的地址是=%p  p_num对应数组元素的值%d\n", p_num, num, 
*p_num);printf("p_num访问第一个元素=%d\n", p_num[0]);printf("p_num访问第二个元素=%d\n", p_num[1]);return 0;}

运行结果:

p_num指针的值=000000000061FE00 ,num的地址是=000000000061FE00  p_num对应数组元素的值1

p_num访问第一个元素=1 p_num访问第二个元素=2


6.4 数组作为函数参数

函数参数不仅可以是变量,也可以是数组,数组作函数参数的作用是将数组首元素地址传给函数作形参。 在 C 语言中,数组作函数参数时,是没有副本机制的,只能传递地址。也可以认为,数组作函数参数时,会退化为指针

#include <stdio.h>
void getSize(int nums[10]) // 定义 getSize 函数
{int size = sizeof(nums); // 计算数组 nums 的总字节数printf("指针 size=%d\n", size);
}
int main(void)
{int nums[10] = { 1, 2, 3, 4, 5 };int size = sizeof(nums); // 计算数组 nums 的总字节数printf("外部 size=%d\n", size);getSize(nums); // 调用 getSize 函数return 0;
}

 运行结果:

外部 size=40

指针 size=8

所以直接把函数的形参的类型设置为指针,来接收数组的第一个地址: 

#include <stdio.h>
void getSize(int* nums) // 定义 getSize 函数
{int size = sizeof(nums); // 计算数组 nums 的总字节数printf("指针 size=%d\n", size);
}
int main(void)
{int nums[10] = { 1, 2, 3, 4, 5 };int size = sizeof(nums); // 计算数组 nums 的总字节数printf("外部 size=%d\n", size);getSize(nums); // 调用 getSize 函数return 0;
}

运行结果:

外部 size=40

指针 size=8

分析:

32位系统中指针变量占4个字节,64位系统中指针变量占8个字节,所以getSize中num的字节数是8。在 C 语言中,数组作函数参数时,是没有副本机制的,只能传递地址,所以 的形参 int *nums应该是指针变量, void getSize方法 getSize(nums) 传入的nums并不是数组的副本,而是数组首元素的地址 

注意:因为没有副本机制,所以如果在函数内部修改数组内容,数组的内容会直接被修改,而不是修改副本

#include <stdio.h>
void getSize(int* nums) // 定义 getSize 函数
{nums[0] = 3;
}
int main(void)
{int nums[10] = { 1, 2, 3, 4, 5 };printf("%d\n", nums[0]);    //加\n是为了换行getSize(nums); // 调用 getSize 函数printf("%d", nums[0]);return 0;
}

练习:封装比较数组最大值函数

#include <stdio.h>
int getMax(int* nums, int length) // 定义函数 getMax
{int i;int max = nums[0]; // 默认 nums[0] 为最大值for (i = 1; i < length; i++) // 下标从 1 开始遍历{if (max < nums[i]) // 比较大小{max = nums[i]; // 覆盖最大值}}return max; // 返回最大值
}int main(void)
{int nums[10] = { 11, 22, 3, 24, 15, 8, 99, 21, 35, 0 };int length = sizeof(nums) / sizeof(nums[0]); // 计算数组长度int max = getMax(nums, length); // 返回最大值printf(" 最大值为 :%d\n", max);return 0;
}

7 二维数组以及字符串与指针

7.1 二维数组的定义方法

C语言中二维数组和一维数组类似,简单理解就是:二维数组由多个一维数组构成

7.1.1 定义一个二维数组 

type arrayName[x][y];

例:

int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};

内部嵌套的括号是可选的,下面的初始化与上面是等同的:

int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

7.1.2 访问二维数组

#include <stdio.h>
#include <string.h>
void main(void)
{int a[3][4] = { {1, 3, 5, 7}, {9, 11, 13, 15}, {17, 19, 21, 23} };printf("a[0][2]=%d", a[0][2]);
}

运行代码:

a[0][2]=5


7.2 定义字符串的几种方法

我们已经学习的定义方法:

#include <stdio.h>
int main(void)
{char chs1[] = { 'i', 't', 'y', 'i', 'n', 'g', '\0' };char chs2[] = "itying";printf("%s\n", chs1);// 以 %s 格式输出 strprintf("%c\n", chs1[2]); // 以 %c 格式输出一个字符printf("%s\n", chs2);  // 以 %s 格式输出 strprintf("%c", chs2[2]); // 以 %c 格式输出一个字符return 0;
}

我们也可以使用字符指针引用字符串:

#include <stdio.h>
int main(void)
{char chs1[] = "itying";char* str1 = chs1;printf("%s\n", str1);  // 以 %s 格式输出 strprintf("%c\n", str1[2]);   // 以 %c 格式输出一个字符
//---------------------------------------------------------------------------char* str2 = "this is str";printf("%s\n", str2);  // 以 %s 格式输出 strprintf("%c\n", str2[2]); // 以 %c 格式输出一个字符return 0;
}

通过上面示例我们可以通过三种方法定义字符串了

char chs1[] = {'i', 't', 'y', 'i', 'n', 'g', '\0'};
char chs2[] = "itying";
char *chs3 = "itying";

7.3 字符串数组

定义了一个指针数组,即数组中的每个元素都是一个 char 类型的指针:

char *arr[] 

例:

char *s[]={ "马总", "张总", "王麻子" };

当使用 { "马总", "张总", "王麻子" } 对这个数组进行初始化时,会把每个字符串常量的首字符地址分别赋给数组 arr 的各个元素:

  • arr[0] 被赋值为字符串 "马总" 的首字符地址,通过这个指针,就可以访问该字符串的所有字符
  • arr[1] 被赋值为字符串 "张总" 的首字符地址
  • arr[2] 被赋值为字符串 "王麻子" 的首字符地址

    在实际处理中文时,通常会使用多字节字符编码,比如常见的 UTF - 8 编码或 GBK 编码

    UTF - 8 是一种变长编码,一个中文字符通常用 3 个字节来表示。对于字符串 "张总",“张” 字在 UTF - 8 编码下会占用 3 个字节的存储空间,arr[1] 指向的就是这 3 个字节中第一个字节的存储地址


    7.4 strcat 连接字符串

    前面我们已经学习了 strlen 计算字符串数组有效长度、sprintf 字符串格式化函数、字符串拼接、整型转换成字符串等字符串知识,详细见【C语言】第七期——字符数组、字符串、类型转换

    现在我们继续学习相关知识

    原型:

    char *strcat(char *dest, const char *src);    //使用前需先引入头文件<string.h>

    参数:

    • dest:目标字符串的指针,拼接后的结果将存储在这个字符串中。dest 必须有足够的空间来容纳 src 字符串的内容以及拼接后的结果
    • src:源字符串的指针,它将被追加到 dest 字符串的末尾。src 字符串本身不会被修改

    返回值:

    函数返回一个指向目标字符串 dest 的指针

    工作原理:

    strcat 函数会从 dest 字符串的第一个空字符 '\0' 开始,将 src 字符串的内容复制到 dest 的末尾,直到遇到 src 字符串的空字符 '\0' 为止,最后,dest 字符串会以空字符 '\0' 结尾

    #include <stdio.h>
    #include <string.h>int main() {// 定义目标字符串和源字符串char dest[50] = "Hello, ";const char src[] = "World!";// 使用 strcat 函数将 src 追加到 dest 的末尾strcat(dest, src);// 输出结果printf("拼接后的字符串: %s\n", dest);return 0;
    }

    注意事项:

    • 内存空间:dest 数组必须有足够的空间来容纳 src 字符串的内容,否则会导致缓冲区溢出,这可能会引发程序崩溃或安全漏洞
    • 空字符:dest 字符串必须以空字符 '\0' 结尾,否则 strcat 函数无法确定从哪里开始追加
    • 字符串重叠:dest 和 src 所指向的字符串不能重叠,否则会导致未定义行为

    7.5 strcpy 字符串复制(拷贝)函数

    原型:

    char *strcpy(char *dest, const char *src);

    参数:

    • dest:指向目标字符数组的指针,用于存储复制后的字符串。目标数组必须有足够的空间来容纳源字符串及其终止的空字符 '\0'
    • src:指向源字符串的指针,即要被复制的字符串。该参数被声明为 const,表示在函数内部不会修改源字符串

    返回值:

    strcpy 函数返回指向目标字符数组 dest 的指针

    工作原理:

    strcpy 函数会将 src 指向的字符串(包括终止的空字符 '\0')复制到 dest 指向的字符数组中

    复制过程会一直进行,直到遇到源字符串的终止空字符 '\0',并将该空字符也复制到目标数组中

    #include <stdio.h>
    #include <string.h>int main() {// 定义源字符串char src[] = "Hello, World!";// 定义目标字符数组,确保有足够的空间char dest[20];// 使用 strcpy 函数复制字符串strcpy(dest, src);// 输出复制后的字符串printf("Copied string: %s\n", dest);return 0;
    }

    注意事项:

    • 缓冲区溢出风险:使用 strcpy 时需要确保目标数组有足够的空间来容纳源字符串及其终止空字符,否则可能会导致缓冲区溢出,引发未定义行为,为了避免这种风险,可以使用更安全的 strncpy 函数
    • 目标数组的初始化:在使用 strcpy 之前,不需要对目标数组进行初始化,因为 strcpy 会覆盖目标数组中的原有内容

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

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

    相关文章

    Linux系统管理(十七)——配置英伟达驱动、Cuda、cudnn、Conda、Pytorch、Pycharm等Python深度学习环境

    文章目录 前言安装驱动下载安装Cuda编辑环境变量安装Cudnn安装conda验证安装成功配置conda镜像退出conda环境创建python环境查看当前conda环境激活环境安装python包安装pytorch 安装pycharm安装jupyter notebook 前言 深度学习和大语言模型的部署不免会用到Linux系统&#xff…

    C++蓝桥杯基础篇(六)

    片头 嗨~小伙伴们&#xff0c;大家好&#xff01;今天我们来一起学习蓝桥杯基础篇&#xff08;六&#xff09;&#xff0c;练习相关的数组习题&#xff0c;准备好了吗&#xff1f;咱们开始咯&#xff01; 第1题 数组的左方区域 这道题&#xff0c;实质上是找规律&#xff0c;…

    计算机毕业设计Python+DeepSeek-R1大模型期货价格预测分析 期货价格数据分析可视化预测系 统 量化交易大数据 机器学习 深度学习

    温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

    webstorm的Live Edit插件配合chrome扩展程序JetBrains IDE Support实现实时预览html效果

    前言 我们平时在前端网页修改好代码要点击刷新再去看修改的效果&#xff0c;这样比较麻烦&#xff0c;那么很多软件都提供了实时预览的功能&#xff0c;我们一边编辑代码一边可以看到效果。下面说的是webstorm。 1 Live Edit 首先我们需要在webstorm的settings里安装插件Live …

    可以免费无限次下载PPT的网站

    前言 最近发现了一个超实用的网站&#xff0c;想分享给大家。 在学习和工作的过程中&#xff0c;想必做PPT是一件让大家都很头疼的一件事。 想下载一些PPT模板减少做PPT的工作量&#xff0c;但网上大多精美的PPT都是需要付费才能下载使用。 即使免费也有次数限制&#xff0…

    九、数据治理架构流程

    一、总体结构 《数据治理架构流程图》&#xff08;Data Governance Architecture Flowchart&#xff09; 水平结构&#xff1a;流程图采用水平组织&#xff0c;显示从数据源到数据应用的进程。 垂直结构&#xff1a;每个水平部分进一步划分为垂直列&#xff0c;代表数据治理的…

    vue3中ref和reactive响应式数据、ref模板引用(组合式和选项式区别)、组件ref的使用

    目录 Ⅰ.ref 1.基本用法&#xff1a;ref响应式数据 2.ref模板引用 3.ref在v-for中的模板引用 ​4.ref在组件上使用 ​5.TS中ref数据标注类型 Ⅱ.reactive 1.基本用法&#xff1a;reactive响应式数据 2.TS中reactive标注类型 Ⅲ.ref和reactive的使用场景和区别 Ⅳ.小结…

    SpringBoot集成easy-captcha图片验证码框架

    SpringBoot集成easy-captcha图片验证码框架 此项目已经很久未维护&#xff0c;如有更好的选择&#xff0c;建议使用更好的选择!!! 一、引言 验证码&#xff08;CAPTCHA&#xff09;是现代应用中防止机器人攻击、保护接口安全的核心手段之一。然而&#xff0c;从零开发验证码…

    算法与数据结构(二叉树中的最大路径和)

    题目 思路 这道题我们可以考虑用递归来解决。 首先设计一个maxPath函数用来递归计算二叉树中一个节点的最大贡献值&#xff0c;具体来说&#xff0c;就是以该节点为根节点的子树中寻找以该节点为起点的一条路径&#xff0c;使得该路径上的节点值之和最大。 如果该节点为空&a…

    7-Zip命令行复制

    先下载一个&#xff1a; 找到压缩exe目录&#xff1a; 写脚本 set EXE_PATH"C:/Program Files/7-Zip/7z.exe"%EXE_PATH% a -t7z OutputName.7z "D:/工程/前端工作"pause

    【洛谷贪心算法题】P2240部分背包问题

    【解题思路】 贪心策略选择 对于部分背包问题&#xff0c;关键在于如何选择物品放入背包以达到最大价值。由于物品可以分割&#xff0c;遍历排序后的物品数组&#xff0c;根据物品重量和背包剩余容量的关系&#xff0c;决定是将整个物品放入背包还是分割物品放入背包&#xff…

    C++ AVL树详解(含模拟实现)

    目录 AVL树的概念 AVL树节点的定义 AVL树的插入 AVL树的旋转&#xff08;难点&#xff09; AVL树的验证 AVL树的删除(本文不做具体的模拟实现) AVL树的性能 AVL树的模拟实现 AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索…

    网络安全学习中,web渗透的测试流程是怎样的?

    渗透测试是什么&#xff1f;网络安全学习中&#xff0c;web渗透的测试流程是怎样的&#xff1f; 渗透测试就是利用我们所掌握的渗透知识&#xff0c;对网站进行一步一步的渗透&#xff0c;发现其中存在的漏洞和隐藏的风险&#xff0c;然后撰写一篇测试报告&#xff0c;提供给我…

    Bitbucket 设置SSH KEY方法

    0 Preface/Foreword SSH具有传输安全特点&#xff0c;受到广泛使用。 1 添加方法 Bitbucket也是代码托管平台&#xff0c;跟GitLab类似。SSH key的设置方法也跟GitLab类似。 在个人profile设置界面&#xff0c;添加SSH KEY。

    和鲸科技推出人工智能通识课程解决方案,助力AI人才培养

    2025年2月&#xff0c;教育部副部长吴岩应港澳特区政府邀请&#xff0c;率团赴港澳宣讲《教育强国建设规划纲要 (2024—2035 年)》。在港澳期间&#xff0c;吴岩阐释了教育强国目标的任务&#xff0c;并与特区政府官员交流推进人工智能人才培养的办法。这一系列行动体现出人工智…

    Ollama下载安装+本地部署DeepSeek+UI可视化+搭建个人知识库——详解!(Windows版本)

    目录 1️⃣下载和安装Ollama 1. &#x1f947;官网下载安装包 2. &#x1f948;安装Ollama 3.&#x1f949;配置Ollama环境变量 4、&#x1f389;验证Ollama 2️⃣本地部署DeepSeek 1. 选择模型并下载 2. 验证和使用DeepSeek 3️⃣使用可视化工具 1. Chrome插件-Page …

    STM32中使用PWM对舵机控制

    目录 1、硬件JIE 2、PWM口配置 3、角度转换 4、main函数中应用 5、工程下载连接 1、硬件介绍 单片机&#xff1a;STM32F1 舵机&#xff1a;MG995 2、PWM口配置 20毫秒的PWM脉冲占空比&#xff0c;对舵机控制效果较好 计算的公式&#xff1a; PSC、ARR值的选取&#xf…

    Java+Vue+uniapp微信小程序校园自助打印系统(程序+论文+讲解+安装+调试+售后)

    感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在当今时代&#xff0c;网络与科学技术正以前所未有的速度迅猛发展&#xff0c;这股强大…

    如何利用爬虫测试1688商品详情接口

    在电商数据分析、市场调研以及商品信息管理等领域&#xff0c;获取1688商品详情数据具有重要意义。虽然1688开放平台提供了官方API接口&#xff0c;但通过爬虫技术获取数据也是一种高效且灵活的方式。本文将详细介绍如何利用爬虫测试1688商品详情接口&#xff0c;包括环境搭建、…

    期权帮|国内期权交易投资人做卖出期权价差交易收取的保证金是单边的还是双向的?

    锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 国内期权交易投资人做卖出期权价差交易收取的保证金是单边的还是双向的? 在国内期权交易中&#xff0c;投资人做卖出期权价差交易时收取的保证金通常是单边的&#xff0c;但具…