数据结构-栈的讲解

栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。

进行数据插入和删除操作的一端称为栈顶,另一端称为栈底(因为先进后出)。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据也在栈顶

后进先出,后进去的先出来(就像羽毛球桶)

图片实例(这里是我画了一个图,找了两个图)

实现栈的方式

栈的实现可以是顺序表,也可以是链表

入数据 1 2 3 4

出数据 4 3 2 1

顺序表(数组)实现

链表实现的话最好是双链表

当然单链表也是可以的

不过一般情况下我们都是采取单链表的方式进行实现

因为

C语言中栈的实现通常采用顺序表的方式而不是链表的方式,原因包括但不限于以下几点:

1. **简单性**:顺序表的实现相对简单,它是基于数组的,而数组是C语言的基本数据结构。链表的实现需要额外的指针操作,对于栈的基本操作(入栈和出栈)来说,这种复杂性通常是不必要的。

2. **性能**:顺序表(数组)在内存中是连续存储的,这意味着存取速度快,CPU缓存的效率也更高。而链表由于其非连续性,访问速度相对较慢,且不利于缓存优化。

3. **空间效率**:顺序表可以预先分配固定大小的内存空间,而链表则需要为每个元素分配独立的内存空间,并且每个节点都需要额外的指针空间。在栈的应用场景中,通常可以预估栈的最大深度,因此顺序表可以更有效地利用内存。

4. **栈特性**:栈是后进先出(LIFO)的数据结构,其操作主要集中在栈顶进行。顺序表可以通过索引直接访问栈顶元素,而链表则需要从头开始遍历,直到找到最后一个元素。

5. **边界检查**:顺序表可以方便地进行上溢检查,只需比较栈的当前元素数量和预分配的大小即可。链表则需要维护一个额外的计数器来记录元素数量,以进行上溢检查。

6. **缓存局部性**:由于顺序表的数据存储是连续的,它具有较好的时间局部性和空间局部性,这使得它更适合现代计算机系统的缓存机制。

7. **编译器优化**:现代编译器对数组和循环有很好的优化,可以生成高效的代码。而链表的优化则更为复杂,且效果可能不如顺序表。

8. **编程习惯**:C语言程序员通常习惯于使用数组来实现栈,因为数组在C语言中使用非常普遍,且容易理解。

然而,这并不意味着链表不能用于实现栈。在一些特定场景下,链表实现的栈也有其优势,例如当栈的大小频繁变化或者对内存的使用有更严格的要求时。链表可以根据需要动态分配内存,而不需要像顺序表那样预先分配一块较大的内存空间。

选择顺序表还是链表来实现栈,最终取决于具体的应用场景和性能要求。

存在CPU缓存的问题 所以数组其实还是比较好用的

计算机的存储体系-CSDN博客https://blog.csdn.net/Jason_from_China/article/details/138589959

栈的实现

 创建文件

创建栈的结构

typedef int STDataType;
typedef struct Stack
{STDataType* _a; // 首元素的地址int _top;		// 栈顶,初始化为0,也就是等同于size,初始化为-1,等同于下标int _capacity;  // 容量 
}Stack;

这段代码定义了一个名为 Stack 的结构体,用于实现一个栈数据结构:

  1. STDataType:这是一个类型定义,它将 int 类型别名为 STDataType。这意味着在定义栈结构体时,可以使用 STDataType 来表示栈中存储的数据类型为整数。

  2. Stack 结构体:

    • STDataType* _a:这是一个指向 STDataType 类型数据的指针,用于指向栈的内存空间。在栈的上下文中,这个数组通常用来存储栈中的元素。_a 通常指向一个预先分配的数组,该数组的大小由 _capacity 成员指定。
    • int _top:这个整数用来表示栈顶的位置。在大多数栈的实现中,栈顶是一个非常重要的概念,因为它指向了最后一个入栈的元素的位置。在这段代码中,_top 初始化为0,意味着栈顶位于数组的第一个元素(在C语言中数组索引从0开始)。如果使用 _top 初始化为-1,则表示栈是空的,因为此时没有元素入栈,栈顶的下标为-1。
    • int _capacity:这个整数用来存储栈的最大容量,即栈能存储的最大元素数量。在栈操作中,这个值用来检查栈是否已满,以避免栈溢出。

这个 Stack 结构体的定义为栈的实现提供了基础框架。通常,还需要实现一些函数来操作这个栈,比如 Push(入栈)、Pop(出栈)、Top(获取栈顶元素)、IsEmpty(检查栈是否为空)等。接下来我们会逐个实现。

初始化栈

#include"Stack.h"
// 初始化栈 
void StackInit(Stack* ps)
{ps->_a = NULL;// 这里栈顶初始化为-1和初始化为0是不一样的//    0 0 0 0 0 0 0 0 数组// -1 0 0 0 0 0 0 0 0 初始化为-1//    0 0 0 0 0 0 0 0 初始化为0// 初始化为0,也就是等同于size,初始化为-1,等同于下标ps->_capacity = ps->_top = 0;
}

代码解释

  1. `void StackInit(Stack* ps)`:这是 `StackInit` 函数的定义开始,它接收一个指向 `Stack` 结构体的指针 `ps` 作为参数。
  2.  `ps->_a = NULL;`:这行代码将栈的数组指针 `_a` 初始化为 `NULL`。这意味着初始化时栈没有分配任何内存空间,数组为空。
  3. `ps->_capacity = ps->_top = 0;`:这里初始化了两个成员变量:
  4.    - `_capacity`:栈的容量,这里初始化为0,表示栈的最大容量为0,即栈没有任何空间可以存储元素。
  5.  - `_top`:栈顶的索引,这里初始化为0,表示栈顶位于数组的第一个位置。由于数组指针 `_a` 已经初始化为 `NULL`,此时栈是空的。

_top 初始化的不同方式:

  1. - **初始化为-1**:在一些栈的实现中,`_top` 被初始化为-1,用来表示栈为空。这种方式下,数组的索引从0开始,但 `_top` 的初始值-1意味着没有元素在栈中。当第一个元素被推入栈时,`_top` 会增加到0,表示数组的第一个元素现在包含数据。
  2. - **初始化为0**:在这段代码中,`_top` 被初始化为0,这同样表示栈为空。由于 `_a` 是 `NULL`,即使 `_top` 是0,栈实际上也是空的。当第一个元素被推入栈时,数组 `_a` 会被分配内存,且 `_top` 保持不变,直到有元素入栈。
  3. 选择哪种初始化方式取决于你的栈操作的具体实现。如果你的栈操作允许在 `_top` 为0时推入元素,那么初始化 `_top` 为0是合适的。如果你希望 `_top` 总是指向栈顶元素的下一个位置,那么初始化 `_top` 为-1可能更合适。
  4. 在这段代码中,由于 `_a` 被初始化为 `NULL`,栈的状态(空或非空)主要由 `_a` 的值决定。
  5. `_top` 的初始化值更多地是为将来元素入栈时的索引管理做准备。

这里我采取的是初始化为0,也就可以简介表示实际的个数

销毁栈

// 销毁栈 
void StackDestroy(Stack* ps)
{// 判断为不为空,判断里面有没有数值assert(ps && ps->_top);free(ps->_a);ps->_capacity = ps->_top = 0;
}
  1. free(ps->_a);:这行代码调用 free 函数来释放栈的数组 _a 所占用的内存。这是销毁栈的关键步骤,因为它避免了内存泄漏。

  2. ps->_capacity = ps->_top = 0;:在释放了栈的内存之后,将 _capacity_top 成员变量重置为0。_capacity 表示栈的容量,重置为0意味着栈不再具有存储任何元素的能力。_top 表示栈顶的位置,重置为0可以表示栈现在是空的(取决于你的栈实现中 _top 的使用方式)。

入栈

// 入栈 
void StackPush(Stack* ps, STDataType data)
{//首先判断容量是多少,然后进行扩容if (ps->_capacity == ps->_top){//扩容int newapacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;STDataType* tmp = (STDataType*)realloc(ps->_a, newapacity * sizeof(STDataType));if (tmp == NULL){perror("StackPush:tmp:error:");exit(1);}//改变容量大小,指向新空间的头第一个元素位置的地址ps->_capacity = newapacity;ps->_a = tmp;}//插入数值ps->_a[ps->_top] = data;ps->_top++;
}

C语言-realloc函数的使用-CSDN博客https://blog.csdn.net/Jason_from_China/article/details/137074963注意,realloc涉及一个原地扩容和异地扩容的情况,所以才会出现这一行代码

ps->_a = tmp;

这段代码定义了一个名为 StackPush 的函数,用于向栈中添加一个新元素。

  1. void StackPush(Stack* ps, STDataType data):函数定义开始,StackPush 接收一个指向 Stack 结构体的指针 ps 和一个要入栈的数据 data

  2. if (ps->_capacity == ps->_top):这行代码检查栈是否已满。_capacity 是栈的最大容量,_top 是栈顶的索引。如果两者相等,表示栈已经达到最大容量。

  3. int newapacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;:如果栈已满,则需要扩容。新的容量 newcapacity 是当前容量的两倍,如果当前容量为0(即栈是空的或尚未分配内存),则新容量设置为4。

  4. STDataType* tmp = (STDataType*)realloc(ps->_a, newapacity * sizeof(STDataType));:使用 realloc 函数为栈的数组 _a 分配新的内存空间。realloc 会处理原有内存块的复制,并返回指向新内存块的指针。

  5. if (tmp == NULL):检查 realloc 是否成功。如果 tmpNULL,表示内存分配失败。

  6. perror("StackPush:tmp:error:");:如果内存分配失败,使用 perror 函数输出错误信息。perror 会将参数字符串作为前缀,后跟一个冒号和空格,然后输出当前设定的 errno 描述的错误信息。

  7. exit(1);:如果内存分配失败,调用 exit 函数以非零状态码退出程序。

  8. ps->_capacity = newapacity;:如果内存分配成功,更新栈的容量为新的容量。

  9. ps->_a = tmp;:将栈的数组指针 _a 更新为指向新分配的内存空间。

  10. ps->_a[ps->_top] = data;:将传入的数据 data 存储到栈顶位置。由于栈是顺序存储的,这一步是直接通过数组索引来完成的。

  11. ps->_top++;:更新栈顶索引 _top,将其增加1,以指向数组中的下一个位置,为下一次入栈做准备。

这段代码实现了一个动态栈,它可以根据需要自动扩容。当栈满时,它会增加栈的容量并重新分配内存。需要注意的是,realloc 的使用可能会导致原有内存块被移动到新的内存位置,因此所有指向原内存块的指针都需要更新。此外,realloc 失败时的错误处理是必要的,以避免程序因内存分配问题而崩溃。

出栈

// 出栈 
void StackPop(Stack* ps)
{// 判断为不为空,判断里面有没有数值assert(ps && ps->_top);ps->_top--;
}
  1. void StackPop(Stack* ps):函数定义开始,StackPop 接收一个指向 Stack 结构体的指针 ps 作为参数。

  2. assert(ps && ps->_top);assert 是一个宏,用于在运行时测试一个条件是否为真。如果条件为假,则 assert 将产生一个断言失败,通常会导致程序异常终止。在这里,它用于确保传入的栈指针 ps 不是 NULL,并且 ps->_top 也是非空的,从而确保栈已经初始化过并且 _top 成员变量是有效的。

  3. ps->_top--;:这行代码将栈顶索引 _top 减一。由于栈是后进先出(LIFO)的数据结构,减少 _top 的值就相当于从栈顶部移除了一个元素。在栈的顺序存储实现中,通常不需要实际移动数组中的元素,只需要更新栈顶的索引即可。

出栈其实就很简答,只需要删除栈顶就可以

删除

获取栈顶元素 

// 获取栈顶元素 
STDataType StackTop(Stack* ps)
{assert(ps && ps->_top);return ps->_a[ps->_top - 1];
}
  1. STDataType StackTop(Stack* ps):函数定义开始,StackTop 接收一个指向 Stack 结构体的指针 ps 作为参数,并返回栈顶的元素。

  2. assert(ps && ps->_top);assert 是一个宏,用于在运行时测试一个条件是否为真。如果条件为假,则 assert 将产生一个断言失败,通常会导致程序异常终止。在这里,它用于确保传入的栈指针 ps 不是 NULL,并且 ps->_top 也是非空的,从而确保栈已经初始化过并且 _top 成员变量是有效的。

  3. return ps->_a[ps->_top - 1];:这行代码返回栈顶元素的值。由于栈是后进先出(LIFO)的数据结构,栈顶元素就是数组 _a 中索引为 _top - 1 的元素。这里假设 _top 初始化为0并且数组索引从0开始,所以栈顶元素的索引是 _top - 1

获取栈中有效元素个数 

int StackSize(Stack* ps)
{assert(ps && ps->_top);return ps->_top - 1;
}

检测栈是否为空,如果为空返回非零结果(1),如果不为空返回0 

int StackEmpty(Stack* ps)
{assert(ps);return ps->_top == 0;// 所以,ps->_top == 0 这个表达式的作用是比较栈顶位置 ps->_top 是否等于 0。// 如果相等,说明栈为空,表达式结果为 true(在C语言中用 1 表示);// 如果不相等,说明栈不为空,表达式结果为 false(在C语言中用 0 表示)
}

栈代码的总结

Stack.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int STDataType;
typedef struct Stack
{STDataType* _a; // 首元素的地址int _top;		// 栈顶,初始化为0,也就是等同于size,初始化为-1,等同于下标int _capacity;  // 容量 
}Stack;
// 初始化栈 
void StackInit(Stack* ps);
// 销毁栈 
void StackDestroy(Stack* ps);
// 入栈 
void StackPush(Stack* ps, STDataType data);
// 出栈 
void StackPop(Stack* ps);
// 获取栈顶元素 
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数 
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps);

Stack.c

#include"Stack.h"
// 初始化栈 
void StackInit(Stack* ps)
{ps->_a = NULL;// 这里栈顶初始化为-1和初始化为0是不一样的//    0 0 0 0 0 0 0 0 数组// -1 0 0 0 0 0 0 0 0 初始化为-1//    0 0 0 0 0 0 0 0 初始化为0// 初始化为0,也就是等同于size,初始化为-1,等同于下标ps->_capacity = ps->_top = 0;
}
// 销毁栈 
void StackDestroy(Stack* ps)
{// 判断为不为空,判断里面有没有数值assert(ps && ps->_top);free(ps->_a);ps->_capacity = ps->_top = 0;
}
// 入栈 
void StackPush(Stack* ps, STDataType data)
{//首先判断容量是多少,然后进行扩容if (ps->_capacity == ps->_top){//扩容int newapacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;STDataType* tmp = (STDataType*)realloc(ps->_a, newapacity * sizeof(STDataType));if (tmp == NULL){perror("StackPush:tmp:error:");exit(1);}//改变容量大小,指向新空间的头第一个元素位置的地址ps->_capacity = newapacity;ps->_a = tmp;}//插入数值ps->_a[ps->_top] = data;ps->_top++;
}
// 出栈 
void StackPop(Stack* ps)
{// 判断为不为空,判断里面有没有数值assert(ps && ps->_top);ps->_top--;
}
// 获取栈顶元素 
STDataType StackTop(Stack* ps)
{assert(ps && ps->_top);return ps->_a[ps->_top - 1];
}
// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{assert(ps && ps->_top);return ps->_top - 1;
}
// 检测栈是否为空,如果为空返回非零结果(1),如果不为空返回0 
int StackEmpty(Stack* ps)
{assert(ps);return ps->_top == 0;// 所以,ps->_top == 0 这个表达式的作用是比较栈顶位置 ps->_top 是否等于 0。// 如果相等,说明栈为空,表达式结果为 true(在C语言中用 1 表示);// 如果不相等,说明栈不为空,表达式结果为 false(在C语言中用 0 表示)
}

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

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

相关文章

学习注意力机制并将其应用到网络中

什么是注意力机制 注意力机制的核心重点就是让网络关注到它更需要关注的地方。 当我们使用卷积神经网络去处理图片的时候&#xff0c;我们会更希望卷积神经网络去注意应该注意的地方&#xff0c;而不是什么都关注&#xff0c;我们不可能手动去调节需要注意的地方&#xff0c;…

证明力引导算法forceatlas2为什么不是启发式算法

一、基本概念 吸引力 F a ( n i ) ∑ n j ∈ N c t d ( n i ) ω i , j d E ( n i , n j ) V i , j \displaystyle \bm{F}_a(n_i) \sum_{n_j \in \mathcal{N}_{ctd}(n_i)} \omega_{i,j} \; d_E(n_i,n_j) \bm{V}_{i,j} Fa​(ni​)nj​∈Nctd​(ni​)∑​ωi,j​dE​(ni​,nj​…

class常量池、运行时常量池和字符串常量池的关系

类常量池、运行时常量池和字符串常量池这三种常量池&#xff0c;在Java中扮演着不同但又相互关联的角色。理解它们之间的关系&#xff0c;有助于深入理解Java虚拟机&#xff08;JVM&#xff09;的内部工作机制&#xff0c;尤其是在类加载、内存分配和字符串处理方面。 类常量池…

NeurIPS‘24 截稿日期逼近 加拿大温哥华邀你共赴盛会

会议之眼 快讯 第38届NeurIPS24(Conference and Workshop on Neural Information Processing Systems)即神经信息处理系统研讨会将于 2024 年 12月9日-15日在加拿大温哥华会议中心举行&#xff01; NeurIPS 每一年都是全球AI领域的一场盛宴&#xff0c;吸引着来自世界各地的顶…

5.10.8 Transformer in Transformer

Transformer iN Transformer (TNT)。具体来说&#xff0c;我们将局部补丁&#xff08;例如&#xff0c;1616&#xff09;视为“视觉句子”&#xff0c;并将它们进一步划分为更小的补丁&#xff08;例如&#xff0c;44&#xff09;作为“视觉单词”。每个单词的注意力将与给定视…

信号和槽基本概念

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;QT❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、概述 二、信号的本质 三、槽的本质 一、概述 在 Qt 中&#xff0c;用户和控件的每次交互过程称…

Bootloader+升级方案

随着设备的功能越来越强大&#xff0c;系统也越来越复杂&#xff0c;产品升级也成为了开发过程不可或缺的一道程序。在工程应用中&#xff0c;如何在不更改硬件的前提下通过软件的方式实现产品升级。通过Bootloader来实现固件的升级是一种极好的方式&#xff0c;Bootloader是单…

I2CKD : INTRA- AND INTER-CLASS KNOWLEDGE DISTILLATION FOR SEMANTIC SEGMENTATION

摘要 本文提出了一种新的针对图像语义分割的知识蒸馏方法&#xff0c;称为类内和类间知识蒸馏&#xff08;I2CKD&#xff09;。该方法的重点是在教师&#xff08;繁琐模型&#xff09;和学生&#xff08;紧凑模型&#xff09;的中间层之间捕获和传递知识。对于知识提取&#x…

12个乒乓球,有一个次品,不知轻重,用一台无砝码天平称三次,找出次品,告知轻重?

前言 B站上看到个视频&#xff1a;为什么有人不认可清北的学生大多是智商高的? 然后试了下&#xff0c;发现我真菜 自己的思路&#xff08;失败&#xff09; 三次称重要获取到12个乒乓球中那个是次品&#xff0c;我想着将12个小球编号&#xff0c;分为四组&#xff0c;每组…

yo!这里是socket网络编程相关介绍

目录 前言 基本概念 源ip&&目的ip 源端口号&&目的端口号 udp&&tcp初识 socket编程 网络字节序 socket常见接口 socket bind listen accept connect 地址转换函数 字符串转in_addr in_addr转字符串 套接字读写函数 recvfrom&&a…

Java入门基础学习笔记2——JDK的选择下载安装

搭建Java的开发环境&#xff1a; Java的产品叫JDK&#xff08;Java Development Kit&#xff1a; Java开发者工具包&#xff09;&#xff0c;必须安装JDK才能使用Java。 JDK的发展史&#xff1a; LTS&#xff1a;Long-term Support&#xff1a;长期支持版。指的Java会对这些版…

pycharm报错Process finished with exit code -1073740791 (0xC0000409)

pycharm报错Process finished with exit code -1073740791 (0xC0000409) 各种垃圾文章&#xff08;包括chatgpt产生的垃圾文章&#xff09;&#xff0c;没有给出具体的解决办法。 解决办法就是把具体报错信息显示出来&#xff0c;然后再去查。 勾选 然后再运行就能把错误显示…

MetaRTC-play拉流客户端代码分析

渲染使用opengl&#xff0c;音频播放使用alsa。 当点击播放按钮后&#xff0c;以此调用的类如下&#xff0c;开始建立rtc连接&#xff0c;AV解码&#xff0c;音频渲染&#xff0c;视频渲染。 如果想去除QT&#xff0c;改为cmake工程管理&#xff0c;去掉渲染部分即可。 下方是…

Linux---vim编辑器(续写)

5. vim正常模式命令集 插入模式 按「i」切换进入插入模式「insert mode」&#xff0c; 按“i”进入插入模式后是从光标当前位置开始输入文件&#xff1b; 按「a」进入插入模式后&#xff0c;是从目前光标所在位置的下一个位置开始输入文字&#xff1b; 按「o」进入插入模式…

从头开始学Spring—01Spring介绍和IOC容器思想

目录 1.Spring介绍 1.1Spring概述 1.2特性 1.3五大功能模块 2.IOC容器 2.1IOC思想 ①获取资源的传统方式 ②反转控制方式获取资源 ③DI 2.2IOC容器在Spring中的实现 ①BeanFactory ②ApplicationContext ③ApplicationContext的主要实现类 1.Spring介绍 1.1Sprin…

Linux系统一步一脚印式学习

Linux操作系统具有许多特点和优势。首先&#xff0c;它是开放源代码的&#xff0c;也就意味着任何人都可以对源代码进行查看和修改。其次&#xff0c;可以同时支持多个用户且可以同时执行多个任务&#xff0c;此外&#xff0c;Linux操作系统也非常稳定和安全。相对于其他操作系…

安全测试|常见SQL注入攻击方式、影响及预防

SQL注入 什么是SQL注入&#xff1f; SQL注入是比较常见的网络攻击方式之一&#xff0c;主要攻击对象是数据库&#xff0c;针对程序员编写时的疏忽&#xff0c;通过SQL语句&#xff0c;实现无账号登录&#xff0c;篡改数据库。 SQL注入简单来说就是通过在表单中填写包含SQL关键…

SSD-60S施耐德电机保护器EOCR-SSD

EOCR主要产品有电子式电动机保护继电器&#xff0c;电子式过电流继电器&#xff0c;电子式欠电流继电器&#xff0c;电子式欠电压继电器&#xff0c;其它保护装置&#xff0c;电流互感器。EOCR-SSD 10-60A电机保护器 系列型号: EOCRSSD-05SEOCRssD-30s EOCRSSD-60SEOCRSSD-0…

开源即时通讯IM框架 MobileIMSDK v6.5 发布

一、更新内容简介 本次更新为次要版本更新&#xff0c;进行了bug修复和优化升级&#xff08;更新历史详见&#xff1a;码云 Release Notes、Github Release Notes&#xff09;。 MobileIMSDK 可能是市面上唯一同时支持 UDPTCPWebSocket 三种协议的同类开源IM框架。轻量级、高…

8种常见的CMD命令

1.怎么打开CMD窗口 步骤1&#xff1a;winr 步骤2&#xff1a;在弹出的窗口输入cmd&#xff0c;然后点击确认&#xff0c;就会出现一个cmd的窗口 2.CMD的8种常见命令 2.1盘符名称冒号 说明&#xff1a;切换盘的路径 打开CMD窗口这里默认的是C盘的Users的27823路径底下&#xf…