当前位置: 首页 > news >正文

app资源网站开发/网站优化排名哪家性价比高

app资源网站开发,网站优化排名哪家性价比高,吉安百度seo,深圳市网站建设公司排名通常所谓的IO,其本质就是等待通信和进行通信,即IO 等 拷贝。 那么想要做到高效的IO,就要在单位时间内,减少“等”的比重。 一.五种IO模型 阻塞 IO: 在内核将数据准备好之前, 系统调用会一直等待. 所有的套接字, 默认都是阻塞方…

通常所谓的IO,其本质就是等待通信和进行通信,即IO = 等 + 拷贝。

那么想要做到高效的IO,就要在单位时间内,减少“等”的比重。


一.五种IO模型

  1. 阻塞 IO: 在内核将数据准备好之前, 系统调用会一直等待. 所有的套接字, 默认都是阻塞方式。阻塞 IO 是最常见的 IO 模型。
  2. 非阻塞 IO: 如果内核还未将数据准备好, 系统调用仍然会直接返回, 并且返回EWOULDBLOCK 错误码. 非阻塞 IO 往往需要程序员循环的方式反复尝试读写文件描述符, 这个过程称为轮询. 这对 CPU 来说是较大的浪费, 一般只有特定场景下才使用。
  3. 信号驱动 IO: 内核将数据准备好的时候, 使用 SIGIO 信号通知应用程序进行 IO 操作.
  4. IO 多路转接: 和阻塞 IO 类似. 核心在于 IO 多路转接能够同时等待多个文件描述符的就绪状态。
  5. 异步 IO: 由内核在数据拷贝完成时, 通知应用程序(而信号驱动是告诉应用程序何时可以开始拷贝数据)。

此处展开分享一下非阻塞IO。 


二.非阻塞IO

系统和网络中的文件描述符,其默认情况下都是阻塞IO,下面来看怎么将其设置为非阻塞IO。


1.fcntl函数

#include <unistd.h>

#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

fcntl 函数有 5 种功能:

  • 复制一个现有的描述符(cmd=F_DUPFD.
  • 获得/设置文件描述符标记(cmd=F_GETFD F_SETFD).
  • 获得/设置文件状态标记(cmd=F_GETFL F_SETFL).
  • 获得/设置异步 I/O 所有权(cmd=F_GETOWN F_SETOWN).
  • 获得/设置记录锁(cmd=F_GETLK,F_SETLK F_SETLKW).

此处只是用第三种功能, 获取/设置文件状态标记, 就可以将一个文件描述符设置为非阻塞。


2.代码实现非阻塞

void SetNoBlock(int fd)
{int fl = fcntl(fd, F_GETFL);if (fl < 0){perror("fcntl");return;}fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}

使用 F_GETFL 将当前的文件描述符的属性取出来(这是一个位图)。

然后再使用 F_SETFL 将文件描述符设置回去. 设置回去的同时, 加上一个 O_NONBLOCK 参数,表示为非阻塞

前边提到,在非阻塞IO下,如果数据没有就绪,那么IO就会以出错的形式返回,那么如何区分到底是数据没有就绪,还是真的出错了呢???

通过判断errno错误码,如果错误码为EWOULDBLOCK,表示数据没有就绪,此时可以设计程序去做其他事,并通过轮询方式去检测数据是否就绪,反之则为真的出错,程序退出。

此外,如果进程长期阻塞,可能会收到系统的信号,中断程序运行,此时返回的错误码为EINTR,所以如果不想程序被系统中断,就可以通过此错误码在做判断。


三.多路转接

多路转接,即等待多个fd上的新事件就绪,然后通知程序员,事件已经就绪,可以进行IO拷贝了。


1.select

(1)概述

系统提供 select 函数来实现多路复用输入/输出模型。

  • select 系统调用是用来让我们的程序监视多个文件描述符的状态变化的;
  • 程序会停在 select 这里等待,直到被监视的文件描述符有一个或多个发生了状态改变;

IO = 等 + 拷贝,select负责的就是等待,并且是等待多个新事件的到了。


(2)接口

#include <sys/select.h>

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

参数:

  • nfds :是需要监视的最大的文件描述符值+1
  • rdset,wrset,exset :分别对应于需要检测的可读文件描述符的集合,可写文件描述符的集合及异常文件描述符的集合,是输入输出型参数。
  • timeout :为结构体 timeval类型,用来设置 select()的等待时间。

fd_set结构:

这个结构就是一个整数数组, 更严格的说,是一个 "位图",使用位图中对应的位来表示要监视的文件描述符。

  • 输入时,比特位的位置表示文件描述符的编号,比特位的内容表示是否关心该fd事件。
  • 输出时,比特位的位置表示文件描述符的编号,比特位的内容表示对应的fd事件是否发生。

下面是OS提供了一组操作 fd_set 的接口, 来比较方便的操作位图:

void FD_CLR(int fd, fd_set *set); // 用来清除描述词组 set 中相关 fd 的位

int FD_ISSET(int fd, fd_set *set); // 用来测试描述词组 set 中相关 fd 的位是否为真

void FD_SET(int fd, fd_set *set); // 用来设置描述词组 set 中相关 fd 的位

void FD_ZERO(fd_set *set); // 用来清除描述词组 set 的全部位

timeval结构:

struct timeval

{

        __time_t tv_sec;//秒

        __suseconds_t tv_usec;//微秒
}

timeval 结构用于描述一段时间长度,比如(5,0)则表示在0-5秒内;如果在这个时间内,需要监视的描述符没有事件发生则函数返回,返回值为 0。

参数 timeout 取值:

  • nullptr:则表示 select()没有 timeoutselect 将一直被阻塞,直到某个文件描述符上发生了事件;
  • 0:仅检测描述符集合的状态,然后立即返回,并不等待外部事件的发生,即按照非阻塞轮询的方式。
  • 特定的时间值:如果在指定的时间段里没有事件发生,select 将超时返回。

函数返回值:

  • 执行成功则返回文件描述词状态已改变的个数。
  • 如果返回 0 代表在描述词状态改变前已超过 timeout 时间,没有返回。
  • 当有错误发生时则返回-1,错误原因存于 errno,此时参数 readfdswritefds, exceptfds 和 timeout 的值变成不可预测。

(3)缺点

每次调用 select,都需要手动设置 fd 集合, 从接口使用角度来说也非常不便。

每次调用 select,都需要把 fd 集合从用户态拷贝到内核态,这个开销在 fd 很多时会很大。

同时每次调用 select 都需要在内核遍历传递进来的所有 fd,这个开销在 fd 多时也很大。

select 支持的文件描述符数量太小。


2.poll

(1)概述

poll的作用与select完全相同,也是等待多个fd,等待fd上的新事件就绪,随后派发事件,可以理解为是select的优化版本。


(2)接口

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

参数:

  •  fds是一个 poll 函数监听的结构列表. 每一个元素中, 包含了三部分内容: 文件描述符, 监听的事件集合, 返回的事件集合。

  • nfds 表示 fds 数组的长度。

  • timeout:以毫秒为单位,设定的超时时间,设为0表示非阻塞,-1表示阻塞。

pollfd结构体:

struct pollfd {

int

fd; /* file descriptor */

short events; /* requested events */

short revents; /* returned events */

};

同样是位图结构,short16位,每一位可代表一个事件,eventsrevents的取值: 

 这些事件都是,且分别表示为不同的二进制位,因此可以自由组合搭配,形成事件集合。

返回值:

  • 大于0,表示有几个fd就绪。
  • 等于0,超时。
  • 小于0,poll出错。

(3)优点

pollfd 结构包含了要监视的 event 和发生的 event,不再使用 select“参数-传递的方式. 接口使用比 select 更方便。

poll 并没有最大数量限制 (但是数量过大后性能也是会下降)。


3.epoll

(1)概述

epoll是除了select和poll之外公认为 Linux 下性能最好的多路 I/O 就绪通知方法。


(2)接口

使用epoll接口需要包含头文件 #include<sys/epoll.h>。 

int epoll_create(int size);

创建一个 epoll 的句柄.

  • size 参数可以被忽略。
  • 用完之后, 必须调用 close()关闭。

返回值epfd供接下来的函数使用。

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

epoll 的事件注册函数. 它不同于 select()是在监听事件时告诉内核要监听什么类型的事件, 而是在这里先注册要监听的事件类型。

epoll_ctl在底层会将用户让内核关心的fd及其事件添加进由内核构成的红黑树中进行维护。

  • 第一个参数是 epoll_create()的返回值(epoll 的句柄).
  • 第二个参数表示动作,用三个宏来表示.
  • 第三个参数是需要监听的 fd.
  • 第四个参数是告诉内核需要监听什么事.

第二个参数的取值:

  • EPOLL_CTL_ADD:注册新的 fd epfd 中;
  • EPOLL_CTL_MOD:修改已经注册的 fd 的监听事件;
  • EPOLL_CTL_DEL:从 epfd 中删除一个 fd

struct epoll_event 结构如下:

typedef union epoll_data {
        void *ptr;
        int fd;
        uint32_t u32;
        uint64_t u64;
} epoll_data_t;

        struct epoll_event {
        uint32_t events;/* Epoll events */
        epoll_data_t data;/* User data variable */
};

需要关注一下epoll_data_t结构体中的fd成员,其要存放事件的fd,当后续事件就绪时,需要通过该fd来获取事件

其中events同样为位图结构,可以是以下几个宏的集合:

  • EPOLLIN : 表示对应的文件描述符可以读 (包括对端 SOCKET 正常关闭);
  • EPOLLOUT : 表示对应的文件描述符可以写;
  • EPOLLPRI : 表示对应的文件描述符有紧急的数据可读 (这里应该表示有带外数据到来);
  • EPOLLERR : 表示对应的文件描述符发生错误;
  • EPOLLHUP : 表示对应的文件描述符被挂断;
  • EPOLLET : EPOLL 设为边缘触发(Edge Triggered)模式, 这是相对于水平触发(Level Triggered)来说的.
  • EPOLLONESHOT:只监听一次事件, 当监听完这次事件之后, 如果还需要继续监听这个 socket 的话, 需要再次把这个 socket 加入到 EPOLL 队列里.

int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

收集在 epoll 监控的事件中已经发送的事件.

epoll_wait会检测内核中构成的就绪队列中是否有事件已经就绪, 并将已经就绪的事件按照严格顺序放入我们定义的用户缓冲区数组中。

  • 参数 events 是分配好的 epoll_event 结构体数组. epoll 将会把发生的事件赋值到 events 数组中 (events 不可以是空指针,内核只负责把数据复制到这个 events 数组中,不会去帮助我们在用户态中分配内存).
  • maxevents 告诉内核这个 events 有多大,这个 maxevents 的值不能大于创建 epoll_create()时的 size.
  • 参数 timeout 是超时时间 (毫秒,0 会立即返回,-1 是永久阻塞).
  • 如果函数调用成功,返回对应 I/O 上已准备好的文件描述符数目,如返回 0 表示已超时, 返回小于 0 表示函数失败.

对应的事件节点,会同时包含红黑树和就绪队列两个指针,从而使得该节点既可以存在于红黑树中,也可以存在于就绪队列中,从而无需新建新节点来进行转移。 


(3)LT工作模式

LT即水平触发 Level Triggered 工作模式。

epoll 默认状态下就是 LT 工作模式.

当 epoll 检测到 socket 上事件就绪的时候, 可以不立刻进行处理,或者只处理一部分,当缓冲区还有事件未处理时,epoll_wait 会不断地立刻返回并通知 socket 读事件就绪,直到缓冲区上所有的数据都被处理完, epoll_wait 才不会立刻返回。

支持阻塞读写和非阻塞读写。


(4)ET工作模式

ET即边缘触发 Edge Triggered 工作模式。

在第 1 步将 socket 添加到 epoll 描述符的时候使用 EPOLLET 标志, epoll 将进入 ET 工作模式。

当 epoll 检测到 socket 上事件就绪时, 必须立刻处理。如果未处理或未一次性处理完,在第二次调用epoll_wait 的时候, epoll_wait 不会再返回了。

也就是说, ET 模式下, 文件描述符上的事件就绪后, 只有一次处理机会。

ET 的性能比 LT 性能更高( epoll_wait 返回的次数少了很多). Nginx 默认采用 ET 模式使用 epoll。

只支持非阻塞的读写。


LT epoll 的默认行为.

使用 ET 能够减少 epoll 触发的次数. 但是代价就是强逼着程序猿一次响应就绪过程中就把所有的数据都处理完.

相当于一个文件描述符就绪之后, 不会反复被提示就绪, 看起来就比 LT 更高效一些. 是在 LT 情况下如果也能做到每次就绪的文件描述符都立刻处理, 不让这个就绪被重复提示的话, 其实性能也是一样的.

另一方面, ET 的代码复杂程度更高。


相关文章:

Linux网络——IO模型和多路转接

通常所谓的IO&#xff0c;其本质就是等待通信和进行通信&#xff0c;即IO 等 拷贝。 那么想要做到高效的IO&#xff0c;就要在单位时间内&#xff0c;减少“等”的比重。 一.五种IO模型 阻塞 IO: 在内核将数据准备好之前, 系统调用会一直等待. 所有的套接字, 默认都是阻塞方…...

【计网】自定义序列化反序列化(二) —— 实现网络版计算器【上】

&#x1f30e; 实现网络版计算器【上】 文章目录&#xff1a; 实现网络版计算器【上】 自定义协议       制定自定义协议 Jsoncpp序列化反序列化       Json::Value类       Jsoncpp序列化       Jsoncpp反序列化 自定义协议序列化反序列化      …...

数据结构2:顺序表

目录 1.线性表 2.顺序表 2.1概念及结构 2.2接口实现 1.线性表 线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串 线性表在逻辑上是线性结构&#xff0c;也就说…...

python学习——元组

在 Python 中&#xff0c;元组&#xff08;tuple&#xff09;是一种内置的数据类型&#xff0c;用于存储不可变的有序元素集合。以下是关于 Python 元组的一些关键点&#xff1a; 文章目录 定义元组1. 使用圆括号 ()2. 使用 tuple() 函数3. 使用单个元素的元组4. 不使用圆括号…...

apache实现绑定多个虚拟主机访问服务

1个网卡绑定多个ip的命令 ip address add 192.168.45.140/24 dev ens33 ip address add 192.168.45.141/24 dev ens33 在linux服务器上&#xff0c;添加多个站点资料&#xff0c;递归创建三个文件目录 分别在三个文件夹下&#xff0c;建立测试页面 修改apache的配置文件http.…...

无需插件,如何以二维码网址直抵3D互动新世界?

随着Web技术的飞速发展&#xff0c;一个无需额外插件&#xff0c;仅凭二维码或网址即可直接访问的三维互动时代已经悄然来临。这一变革&#xff0c;得益于WebGL技术与先进web3D引擎的完美融合&#xff0c;它们共同构建了51建模网这样一个既便捷又高效的在线三维互动平台&#x…...

系统思考—感恩自己

生命中&#xff0c;真正值得我们铭记与感恩的&#xff0c;不是路途上的苦楚与风雨&#xff0c;而是那个在风雨中依然清醒、勇敢前行的自己&#xff0c;和那些一路同行、相互扶持的伙伴们。 感恩自己&#xff0c;感恩每一个与我们携手并进的人&#xff0c;也期待更多志同道合的…...

Java多线程详解①①(全程干货!!!) 实现简单的线程池 || 定时器 || 简单实现定时器 || 时间轮实现定时器

这里是Themberfue 上一节讲了 线程池 线程池中的拒绝策略 等相关内容 实现简单的线程池 一个线程池最核心的方法就是 submit&#xff0c;通过 submit 提交 Runnable 任务来通知线程池来执行 Runnable 任务 我们简单实现一个特定线程数量的线程池&#xff0c;这些线程应该在…...

DAMODEL丹摩|部署FLUX.1+ComfyUI实战教程

本文仅做测评体验&#xff0c;非广告。 文章目录 1. FLUX.1简介2. 实战2. 1 创建资源2. 1 ComfyUI的部署操作2. 3 部署FLUX.1 3. 测试5. 释放资源4. 结语 1. FLUX.1简介 FLUX.1是由黑森林实验室&#xff08;Black Forest Labs&#xff09;开发的开源AI图像生成模型。它拥有12…...

请求(request)

目录 前言 request概述 request的使用 获取前端传递的数据 实例 请求转发 特点 语法 实例 实例1 实例2 【关联实例1】 域对象 组成 作用范围&#xff1a; 生命周期&#xff1a; 使用场景&#xff1a; 使用步骤 存储数据对象 获得数据对象 移除域中的键值…...

关于VNC连接时自动断联的问题

在服务器端打开VNC Server的选项设置对话框&#xff0c;点左边的“Expert”&#xff08;专家&#xff09;&#xff0c;然后找到“IdleTimeout”&#xff0c;将数值设置为0&#xff0c;点OK关闭对话框。搞定。 注意,服务端有两个vnc服务,这俩都要设置ide timeout为0才行 附件是v…...

C语言strtok()函数用法详解!

strtok 是 C 标准库中的字符串分割函数&#xff0c;用于将一个字符串拆分成多个部分&#xff08;token&#xff09;&#xff0c;以某些字符&#xff08;称为分隔符&#xff09;为界限。 函数原型 char *strtok(char *str, const char *delim);参数&#xff1a; str&#xff1a…...

【docker 拉取镜像超时问题】

问题描述 在centosStream8上安装docker&#xff0c;使用命令sudo docker run hello-world 后出现以下错误&#xff1a; Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Ti…...

模拟手机办卡项目(移动大厅)--结合面向对象、JDBC、MYSQL、dao层模式,使用JAVA控制台实现

目录 1. 项目需求 2. 项目使用的技术 3.项目需求分析 3.1 实体类和接口 4.项目结构 5.业务实现 5.1 登录 5.1.1 实现步骤 5.1.2 原生代码问题 ​编辑 5.1.3 解决方法 1.说明&#xff1a; 2. ResultSetHandler结果集处理 5.1.4 代码 5.1.5 实现后的效果图 登录成功​…...

机器学习—大语言模型:推动AI新时代的引擎

云边有个稻草人-CSDN博客 目录 引言 一、大语言模型的基本原理 1. 什么是大语言模型&#xff1f; 2. Transformer 架构 3. 模型训练 二、大语言模型的应用场景 1. 文本生成 2. 问答系统 3. 编码助手 4. 多语言翻译 三、大语言模型的最新进展 1. GPT-4 2. 开源模型 …...

C++:探索哈希表秘密之哈希桶实现哈希

文章目录 前言一、链地址法概念二、哈希表扩容三、哈希桶插入逻辑四、析构函数五、删除逻辑六、查找七、链地址法代码实现总结 前言 前面我们用开放定址法代码实现了哈希表&#xff1a; C&#xff1a;揭秘哈希&#xff1a;提升查找效率的终极技巧_1 对于开放定址法来说&#…...

具身智能高校实训解决方案——从AI大模型+机器人到通用具身智能

一、 行业背景 在具身智能的发展历程中&#xff0c;AI 大模型的出现成为了关键的推动力量。这些大模型具有海量的参数和强大的语言理解、知识表示能力&#xff0c;能够为机器人的行为决策提供更丰富的信息和更智能的指导。然而&#xff0c;单纯的大模型在面对复杂多变的现实…...

【消息序列】详解(8):探秘物联网中设备广播服务

目录 一、概述 1.1. 定义与特点 1.2. 工作原理 1.3. 应用场景 1.4. 技术优势 二、截断寻呼&#xff08;Truncated Page&#xff09;流程 2.1. 截断寻呼的流程 2.2. 示例代码 2.3. 注意事项 三、无连接外围广播过程 3.1. 设备 A 启动无连接外围设备广播 3.2. 示例代…...

【RL Base】强化学习核心算法:深度Q网络(DQN)算法

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…...

深入浅出 Python 网络爬虫:从零开始构建你的数据采集工具

在大数据时代&#xff0c;网络爬虫作为一种数据采集技术&#xff0c;已经成为开发者和数据分析师不可或缺的工具。Python 凭借其强大的生态和简单易用的语言特点&#xff0c;在爬虫领域大放异彩。本文将带你从零开始&#xff0c;逐步构建一个 Python 网络爬虫&#xff0c;解决实…...

美国发布《联邦风险和授权管理计划 (FedRAMP) 路线图 (2024-2025)》

文章目录 前言一、战略目标实施背景2010年12月&#xff0c;《改革联邦信息技术管理的25点实施计划》2011年2月&#xff0c;《联邦云计算战略》2011年12月&#xff0c;《关于“云计算环境中的信息系统安全授权”的首席信息官备忘录》2022年12月&#xff0c;《FedRAMP 授权法案》…...

Python语法基础(三)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 我们这篇文章来说一下函数的返回值和匿名函数 函数的返回值 我们先来看下面的这一段函数的定义代码 # 1、返回值的意义 def func1():print(111111111------start)num166print…...

云计算之elastaicsearch logstach kibana面试题

1.ELK是什么? ELK 其实并不是一款软件,而是一整套解决方案,是三个软件产品的首字母缩写 Elasticsearch:负责日志检索和储存 Logstash:负责日志的收集和分析、处理 Kibana:负责日志的可视化 这三款软件都是开源软件,通常是配合使用,而且又先后归于 Elastic.co 公司名下,…...

【已解决】git push需要输入用户名和密码问题

解决方法&#xff1a; 1&#xff09;查看使用的clone方式&#xff1a; git remote -v 2&#xff09;若为HTTPS&#xff0c;删除原clone方式: git remote rm origin 3&#xff09;添加新的clone方式&#xff1a; git remote add origin gitgithub.com:zludon/git_test.git …...

python的字符串处理

需求&#xff1a; 编写一个程序&#xff0c;输入一段英文句子&#xff0c;统计每个单词的长度&#xff0c;并将单词按照长度从短到长排序。 程序逻辑框图 1、用户输入一句英文句子。 2、对输入的句子进行预处理&#xff08;去空格并分割为单词列表&#xff09;。 3、统计每个单…...

【线程】Java多线程代码案例(2)

【线程】Java多线程代码案例&#xff08;2&#xff09; 一、定时器的实现1.1Java标准库定时器1.2 定时器的实现 二、线程池的实现2.1 线程池2.2 Java标准库中的线程池2.3 线程池的实现 一、定时器的实现 1.1Java标准库定时器 import java.util.Timer; import java.util.Timer…...

虚拟机之间复制文件

在防火墙关闭的前提下&#xff0c;您可以通过几种不同的方法将文件从一个虚拟机复制到另一个虚拟机。这里&#xff0c;我们假设您想要从 IP 地址为 192.168.4.5 的虚拟机上的 /tmp 文件夹复制文件到当前虚拟机&#xff08;192.168.4.6&#xff09;的 /tmp 文件夹下。以下是几种…...

如何为 XFS 文件系统的 /dev/centos/root 增加 800G 空间

如何为 XFS 文件系统的 /dev/centos/root 增加 800G 空间 一、前言二、准备工作三、扩展逻辑卷1. 检查现有 LVM 配置2. 扩展物理卷3. 扩展卷组4. 扩展逻辑卷四、调整文件系统大小1. 检查文件系统状态2. 扩展文件系统五、处理可能出现的问题1. 文件系统无法扩展2. 磁盘空间不足3…...

Java算法OJ(11)双指针练习

目录 1.前言 2.正文 2.1存在重复数字 2.1.1题目 2.1.2解法一代码 解析&#xff1a; 2.1.3解法二代码 解析&#xff1a; 2.2存在重复数字plus 2.2.1题目 2.2.2代码 2.2.3解析 3.小结 1.前言 哈喽大家好吖&#xff0c;今天来给大家分享双指针算法的相关练习&…...

44.扫雷第二部分、放置随机的雷,扫雷,炸死或成功 C语言

按照教程打完了。好几个bug都是自己打出来的。比如统计周围8个格子时&#xff0c;有一个各自加号填成了减号。我还以为平移了&#xff0c;一会显示是0一会显示是2。结果单纯的打错了。debug的时候断点放在scanf后面会顺畅一些。中间多放一些变量名方便监视。以及mine要多显示&a…...