QT--聊天室

一、设计要求

用QT做一个聊天室,

制作一个服务器和客户端。可以进行注册、登录,

登陆成功后可以使用昵称进行发送、接收消息。

能根据昵称、聊天内容查询历史记录,也可以查询全部聊天记录。

二、客户端三级ui界面

三、项目代码

//在pro文件里加入
QT       += core gui network
RC_FILE += icon_config.rc
//客户端dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QtWidgets>
#include <QDebug>
// 网络连接类
#include <QTcpSocket>
// 文本流
#include <QTextStream>
#include <QDateTime>
#include <QByteArray>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();private:Ui::Dialog *ui;QTcpSocket *client;void printMsg(QString); // 输出内容到公屏void succRight();private slots:void btnConnClickedSlot(); // 连接按钮void btnSendClickedSlot(); // 发送按钮void connectedSlot(); // 连接成功的槽函数void disconnectedSlot(); // 断开连接的槽函数void readReadSlot(); // 接收数据的槽函数void btnHisClickedSlot();//历史记录void btnHisNameClickedSlot();//按照昵称void btnHisNeiClickedSlot();//按照内容void btnLoginClickedSlot();//登录/切换窗口void btnRegClickedSlot();//注册};#endif // DIALOG_H
//客户端dialog.c
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :QDialog(parent),ui(new Ui::Dialog)
{ui->setupUi(this);// 抢前台setWindowFlags(Qt::WindowStaysOnTopHint);connect(ui->pushButtonConn,SIGNAL(clicked()),this,SLOT(btnConnClickedSlot()));connect(ui->pushButtonSend,SIGNAL(clicked()),this,SLOT(btnSendClickedSlot()));client = new QTcpSocket(this);// 建立网络连接检测的信号槽connect(client,SIGNAL(connected()),this,SLOT(connectedSlot()));connect(client,SIGNAL(disconnected()),this,SLOT(disconnectedSlot()));// 接收消息的信号槽connect(client,SIGNAL(readyRead()),this,SLOT(readReadSlot()));
//历史connect(ui->pushButtonHis,SIGNAL(clicked()),this,SLOT(btnHisClickedSlot()));connect(ui->pushButtonName,SIGNAL(clicked()),this,SLOT(btnHisNameClickedSlot()));connect(ui->pushButtonNei,SIGNAL(clicked()),this,SLOT(btnHisNeiClickedSlot()));//切换窗口:登录connect(ui->pushButtonLo,SIGNAL(clicked()),this,SLOT(btnLoginClickedSlot()));//注册connect(ui->pushButtonReg,SIGNAL(clicked()),this,SLOT(btnRegClickedSlot()));}Dialog::~Dialog()
{disconnect(client,SIGNAL(disconnected()),this,SLOT(disconnectedSlot()));// 如果还在连接if(client->isOpen())client->close();delete ui;
}void Dialog::btnConnClickedSlot()
{// 发起连接请求// 默认用户输入的参数都对client->connectToHost(ui->lineEditIp->text(),ui->spinBox->value());
}void Dialog::printMsg(QString msg)
{// 获得当前时间QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss");ui->textBrowser->append(time);ui->textBrowser->append(msg);ui->textBrowser->append("");
}void Dialog::succRight()
{ui->stackedWidget->setCurrentIndex(1);
}void Dialog::btnSendClickedSlot()
{// 获得昵称和消息内容QString user = ui->lineEditUser->text();if(user==""){QMessageBox::warning(this,"提示","请输入昵称!");return;}QString msg = ui->lineEditMsg->text();if(msg == ""){QMessageBox::warning(this,"提示","请输入要发送的消息!");return;}QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss");// 创建文本流对象QTextStream output(client);// 连续输出发送output << time<<":"<<user << ":" << msg;// 清空消息输入框ui->lineEditMsg->clear();// 公屏显示msg = user+QString("(本机):")+msg;printMsg(msg);
}void Dialog::connectedSlot()
{// 屏蔽连接按钮,开启发送按钮ui->pushButtonConn->setEnabled(false);ui->pushButtonConn->setText("已连接");ui->pushButtonSend->setEnabled(true);ui->stackedWidget->setCurrentIndex(1);
}void Dialog::readReadSlot()
{QTextStream input(client);QString text = input.readAll();QString text1=input.readLine(100);qDebug() <<text1;QStringList list = text.split(":");QStringList list2 = text1.split(":");qDebug()<<"分割后数量"<<list.size();qDebug() <<list2.size();if(list.size()<4){if(text=="dlchengg"){qDebug() <<text;ui->stackedWidget->setCurrentIndex(2);ui->textBrowser->clear();}
//    else if(list.size()==3)
//    {//        ui->textBrowser_2->append(text);
//        return;
//    }else{printMsg(text);}}else if(list.size()>=4){ui->textBrowser_2->append(text);return;}
}void Dialog::btnHisClickedSlot()
{ui->textBrowser_2->clear();QString user = ui->lineEditUser->text();if(user==""){QMessageBox::warning(this,"提示","请输入昵称!");return;}QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss");// 创建文本流对象QTextStream output(client);QString mm="历史记录";output<< time<<":"<<user << ":" <<mm ;
}void Dialog::btnHisNameClickedSlot()
{ui->textBrowser_2->clear();QString user = ui->lineEditUser->text();QString time = "hh";// 创建文本流对象QTextStream output(client);QString mm="按照昵称";output<< time<<":"<<user << ":" <<mm ;
}void Dialog::btnHisNeiClickedSlot()
{ui->textBrowser_2->clear();QString user = "sjdhs";QString time = "按照内容";// 创建文本流对象QString msg = ui->lineEditMsg->text();if(msg == ""){QMessageBox::warning(this,"提示","请输入要发送的消息!");return;}QTextStream output(client);output<< time<<":"<<user << ":" <<msg ;
}void Dialog::btnLoginClickedSlot()
{QString user = ui->lineEditUs->text();if(user==""){QMessageBox::warning(this,"提示","请输入昵称!");return;}QString pwd = ui->lineEdit_2Pwd->text();if(pwd == ""){QMessageBox::warning(this,"提示","请输入密码!");return;}// 创建文本流对象QTextStream output(client);// 连续输出发送QString mag="hha";QString haf="lele";output <<user << ":" << pwd<<":"<<mag<<":"<<haf;}void Dialog::btnRegClickedSlot()
{QString user = ui->lineEditUs->text();if(user==""){QMessageBox::warning(this,"提示","请输入昵称!");return;}QString pwd = ui->lineEdit_2Pwd->text();if(pwd == ""){QMessageBox::warning(this,"提示","请输入密码!");return;}// 创建文本流对象QTextStream output(client);// 连续输出发送output <<user << ":" << pwd;
}void Dialog::disconnectedSlot()
{// 开启连接按钮,屏蔽发送按钮ui->pushButtonConn->setEnabled(true);ui->pushButtonConn->setText("连接");ui->pushButtonSend->setEnabled(false);// 弹窗printMsg("连接已断开!");QMessageBox::warning(this,"提示","连接已断开!");ui->stackedWidget->setCurrentIndex(0);
}
//服务器dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QtWidgets>
#include <QDebug>
// 连接管理类
#include <QTcpServer>
#include <QDateTime>
// 连接类
#include <QTcpSocket>
// 文本流
#include <QTextStream>#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlQuery>
#include <QByteArray>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();private:Ui::Dialog *ui;QTcpServer* server; // 管理对象(母鸡)void printMsg(QString); // 输出内容到公屏QTcpSocket* socket = NULL; // 连接对象(绿蛋)QList<QTcpSocket*> sockets;QList<QString> ips;QSqlDatabase db;void connect2DB(); // 连接到数据库1void createTable();// 建表void createTable2();void insertData(); // 插入数据void selectAll(int);  // 数据全查void selectLOgin(QString,QString,int);void selectName(QString,int);void selectNei(QString,int);private slots:// 新连接来了的槽函数void newConnSlot();// 连接掉线的信号槽void disconnetedSlot();// 有数据可读时的槽函数void readyReadSlot();};#endif // DIALOG_H
//服务器dialog.c
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :QDialog(parent),ui(new Ui::Dialog)
{ui->setupUi(this);// 抢前台setWindowFlags(Qt::WindowStaysOnTopHint);server = new QTcpServer(this);// 连接新连接来了的信号槽connect(server,SIGNAL(newConnection()),this,SLOT(newConnSlot()));// 开启监听服务server->listen(QHostAddress::Any,8887);connect2DB();
}Dialog::~Dialog()
{if(server->isListening()) // 如果还在监听server->close();delete ui;
}void Dialog::printMsg(QString msg)
{// 获得当前时间QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");ui->textBrowser->append(time);ui->textBrowser->append(msg);ui->textBrowser->append("");
}void Dialog::connect2DB()
{// 创建连接对象db = QSqlDatabase::addDatabase("QSQLITE");// 设置数据库的文件名称db.setDatabaseName("book_management.db");// 打开数据库if(db.open()){qDebug() << "连接成功";// createTable();// createTable2();}else{// 获得错误信息封装类QSqlError info = db.lastError();// 提取错误文本QString text = info.text();// 展示错误QMessageBox::critical(this,"错误",text);}}void Dialog::createTable()
{QString sql = "CREATE TABLE book(time TEXT PRIMARY KEY,name TEXT,msg TEXT);";// 创建数据库操作类对象QSqlQuery sq;if(sq.exec(sql)){qDebug() << "建表成功";}else// 失败{// 获得错误信息封装类QSqlError info = sq.lastError();// 提取错误文本QString text = info.text();// 展示错误qDebug() << text;}}void Dialog::createTable2()
{QString sql2 = "CREATE TABLE class(name TEXT PRIMARY KEY,pwd TEXT);";// 创建数据库操作类对象QSqlQuery sq;if(sq.exec(sql2)){qDebug() << "建表2成功";}else// 失败{// 获得错误信息封装类QSqlError info = sq.lastError();// 提取错误文本QString text = info.text();// 展示错误qDebug() << text;}
}void Dialog::selectAll(int i)
{QString sql = "SELECT * FROM book";QSqlQuery sq;sq.prepare(sql);if(sq.exec(sql)){// 清空上次显示//  ui->textBrowser->clear();while(sq.next())// 循环取出{// 取出一条数据库中的字段QString time = sq.value(0).toString();QString name = sq.value(1).toString();QString msg = sq.value(2).toString();QString msa="历史";// 拼接并显示QString text = msa.append(":")+ time.append(":")+ name.append(":") + msg;QTextStream output(sockets.at(i));output<< text<<endl;}}}void Dialog::selectLOgin(QString user, QString pwd2,int i)
{QString name=user;QString pwd=pwd2;QString sql = "SELECT * FROM class WHERE name LIKE ? AND pwd LIKE ?;";QSqlQuery sq;sq.prepare(sql);if(sq.exec(sql)){while(sq.next()){qDebug() << "yes";QString user = sq.value(0).toString();QString pwd = sq.value(1).toString();QString text ="dlchengg";QTextStream output(sockets.at(i));output<<text;}}else{QSqlError info = sq.lastError();// 提取错误文本QString text = info.text();text.prepend("登录失败:");QMessageBox::warning(this,"警告",text);}
}void Dialog::selectName(QString name1,int i)
{QString name=name1;QString sql = "SELECT * FROM book WHERE name LIKE ?";QSqlQuery sq;sq.prepare(sql);sq.addBindValue(name);if(sq.exec()){while(sq.next())// 循环取出{// 取出一条数据库中的字段QString time = sq.value(0).toString();QString name = sq.value(1).toString();QString msg = sq.value(2).toString();QString msa="历史";// 拼接并显示QString text = msa.append(":")+time.append(":")+ name.append(":") + msg;QTextStream output(sockets.at(i));output<< text<<endl;}}
}void Dialog::selectNei(QString msg, int i)
{QString sql = "SELECT * FROM book WHERE msg LIKE ?";QSqlQuery sq;sq.prepare(sql);sq.addBindValue(msg.prepend("%").append("%"));if(sq.exec()){while(sq.next())// 循环取出{// 取出一条数据库中的字段QString time = sq.value(0).toString();QString name = sq.value(1).toString();QString msg = sq.value(2).toString();QString msa="历史";// 拼接并显示QString text = msa.append(":")+time.append(":")+ name.append(":") + msg;QTextStream output(sockets.at(i));output<< text<<endl;}}
}void Dialog::newConnSlot()
{// 获得服务器端的连接类对象socket = server->nextPendingConnection();QTextStream output(socket);// 如果满员则踢出if(sockets.size() == 20){qDebug() << "聊天室满员";output << QString("聊天室已达人数上限,连接失败!");socket->close();return;}sockets.append(socket);// 绿蛋收到消息的信号槽connect(socket,SIGNAL(readyRead()),this,SLOT(readyReadSlot()));// 绿蛋掉线的信号槽connect(socket,SIGNAL(disconnected()),this,SLOT(disconnetedSlot()));// 给客户端打个招呼output << QString("服务器:你好啊!");// 获得对面的IP地址和端口号QString ip = socket->peerAddress().toString();quint16 port = socket->peerPort();QString portText = QString::number(port);QString text = "新连接来了!";text.append(ip).append(":").append(portText);printMsg(text);
}void Dialog::disconnetedSlot()
{// 拿到发射者socket = (QTcpSocket*)sender();for(int i = 0;i<sockets.size();i++){if(socket == sockets.at(i)){qDebug() << "第" << i << "个客户端掉线了";// 获得对面的IP地址和端口号QString ip = sockets.at(i)->peerAddress().toString();quint16 port = sockets.at(i)->peerPort();QString portText = QString::number(port);QString text = "连接已断开!";text.append(ip).append(":").append(portText);printMsg(text);sockets.removeAt(i);}}
}//接收数据
void Dialog::readyReadSlot()
{for(int i=0;i<sockets.size();i++){if(sockets.at(i)->isReadable() && sockets.at(i)->bytesAvailable()>0){qDebug() << "第" << i << "个客户端发的消息";QTextStream input(sockets.at(i));// 一口气都读了QString text = input.readAll();//写入数据库QStringList list = text.split(":");qDebug()<<"分割后数量"<<list.size();if(list.size()==3){QString time = list[0];QString name = list[1];QString msg = list[2];if(list[2]=="历史记录"){selectAll( i);}else if(list[2]=="按照昵称"){selectName(name,i);}else if(list[0]=="按照内容"){selectNei(msg,i);}else{createTable();QString sql = "INSERT INTO book VALUES(?,?,?);";QSqlQuery sq;sq.prepare(sql);sq.addBindValue(time);sq.addBindValue(name);sq.addBindValue(msg);if(sq.exec()){qDebug()<<"数据插入成功";// QMessageBox::information(this,"通知","数据插入成功");}else{// 获得错误信息封装类QSqlError info = sq.lastError();// 提取错误文本QString text = info.text();// 展示错误text.prepend("数据插入失败:");QMessageBox::warning(this,"警告",text);}printMsg(text);for(int m=0;m<sockets.size();m++){if(m==i)continue;QTextStream output(sockets.at(m));output << text;}}}else if(list.size()==2){createTable2();QString name = list[0];QString pwd = list[1];QString sql = "INSERT INTO class VALUES(?,?);";QSqlQuery sq;sq.prepare(sql);sq.addBindValue(name);sq.addBindValue(pwd);if(sq.exec()){qDebug()<<"注册成功";// QMessageBox::information(this,"通知","数据插入成功");}else{// 获得错误信息封装类QSqlError info = sq.lastError();// 提取错误文本QString text = info.text();// 展示错误text.prepend("注册失败:");QMessageBox::warning(this,"警告",text);}printMsg(text);for(int m=0;m<sockets.size();m++){if(m==i)continue;QTextStream output(sockets.at(m));output << text;}}else if(list.size()==4){QString name = list[0];QString pwd = list[1];qDebug() << name<<pwd;QString sql = "SELECT * FROM class WHERE name=? AND pwd=?";QSqlQuery sq;sq.prepare(sql);sq.addBindValue(name);sq.addBindValue(pwd);qDebug() << "yes";if(sq.exec()){// 取出一条数据库中的字段while(sq.next()){QString name = sq.value(0).toString();QString pwd = sq.value(1).toString();qDebug() <<name<<pwd;qDebug() << "yes";QString text ="dlchengg";QTextStream output(sockets.at(i));output<<text;}}else{QSqlError info = sq.lastError();// 提取错误文本QString text = info.text();text.prepend("登录失败:");QMessageBox::warning(this,"警告",text);}}}}}

四、项目结果

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

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

相关文章

IDEA管理远程仓库Git

1、模拟项目 新建一个文件夹&#xff0c;用来这次演示 用IDEA来打开文件夹 2、创建仓库 在IDEA中给该文件夹创建本地仓库和远程仓库 在菜单栏找到VCS选择Share project on Gitee 在弹窗中输入描述信息 接下来会出现以下弹窗 点击ADD后&#xff0c;在gitee上会创建远程仓库 …

嵌入式开发服务器与客户端交互 日志2024/7/31

嵌入式开发服务器与客户端交互 客户端 网页 操作 请求相关代码: 这里为了适配 低版本浏览器 用的不是fetch 当然用fetch更好 var curUlr window.location.href; //获取当前网页地址var newURL curUlr.lastIndexOf("/");//截取到最后一个斜杠索引var pathUrl…

mysql 数据库空间统计sql

mysql 数据库空间统计 文章目录 mysql 数据库空间统计说明一、数据库存储代码二、查询某个数据库的所有表的 代码三、列出所有已经产生碎片的表总结 说明 INFORMATION_SCHEMA Table Reference 表参考 information_schema是‌MySQL中的一个特殊数据库&#xff0c;它存储了关于…

MLP多层感知机与Pytorch实现

参考文章&#xff1a; 1.动手学深度学习——多层感知机&#xff08;原理解释代码详解&#xff09;_多层感知机 代码-CSDN博客 2.4.1. 多层感知机 — 动手学深度学习 2.0.0 documentation 3.深度理解多层感知机&#xff08;MLP&#xff09; | 米奇妙妙屋 1. 神经网络由来 神经网…

Scrapy 爬取旅游景点相关数据(七):利用指纹实现“不重复爬取”

本期学习&#xff1a; 利用网页指纹去重 众所周知&#xff0c;代理是要花钱的&#xff0c;那么在爬取&#xff08;测试&#xff09;巨量网页的时候&#xff0c;就不可能对已经爬取过的网站去重复的爬&#xff0c;这样会消耗大量的时间&#xff0c;更重要的是会消耗大量的IP (金…

vite instanceof 失效

背景&#xff1a;给一个巨石单体项目进行标准化模块拆分&#xff0c;封装出来的模块代码用 vite 进行构建&#xff0c;但模块启动后页面上的表现一直和 webpack 那版不一致 一步步 debug 后&#xff0c;发现问题出在下面这个判断条件 const GeneratorFunction function* () …

【Golang 面试 - 基础题】每日 5 题(七)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

Vue 3 中使用 InMap 绘制热力图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 Vue 3 中使用 InMap 绘制热力图 应用场景介绍 InMap 是一款强大的地图组件库&#xff0c;它提供了一系列丰富的可视化功能&#xff0c;包括热力图。热力图可以将数据点在地图上以颜色编码的方式可视化&#x…

微软:警惕利用VMware ESXi进行身份验证绕过攻击

微软于7月29日发布警告&#xff0c;称勒索软件团伙正在积极利用 VMware ESXi 身份验证绕过漏洞进行攻击。 该漏洞被追踪为 CVE-2024-37085&#xff0c;由微软安全研究人员 Edan Zwick、Danielle Kuznets Nohi 和 Meitar Pinto 发现&#xff0c;并在 6 月 25 日发布的 ESXi 8.0 …

如何学习自动化测试工具!

要学习和掌握自动化测试工具的使用方法&#xff0c;可以按照以下步骤进行&#xff1a; 一、明确学习目标 首先&#xff0c;需要明确你想要学习哪种自动化测试工具。自动化测试工具种类繁多&#xff0c;包括但不限于Selenium、Appium、JMeter、Postman、Robot Framework等&…

docker环境安装kafka/Flink/clickhouse镜像

1、安装Kafka服务 1、将一下三个tar文件复制到ubuntu指定目录下 2、进入到/home/cl/app目录&#xff0c;使用docker命令加载tar镜像文件 # cd /home/cl/app # docker load -i kafka.tar # docker load -i kafka-manager.tar # docker load -i kafka-zookeeper.tar3、查看d…

分布式:RocketMQ/Kafka总结(附下载链接)

文章目录 下载链接思维导图 本文总结的是关于消息队列的常见知识总结。消息队列和分布式系统息息相关&#xff0c;因此这里就将消息队列放到分布式中一并进行处理关联 下载链接 链接: https://pan.baidu.com/s/1hRTh7rSesikisgRUO2GBpA?pwdutgp 提取码: utgp 思维导图

web学习笔记(八十三)git

目录 1.Git的基本概念 2.gitee常用的命令 3.解决两个人操作不同文件造成的冲突 4.解决两个人操作同一个文件造成的冲突 1.Git的基本概念 git是一种管理代码的方式&#xff0c;广泛用于软件开发和版本管理。我们通常使用gitee&#xff08;码云&#xff09;来云管理代码。 …

《Linux运维总结:基于x86_64架构CPU使用docker-compose一键离线部署zookeeper 3.8.4容器版分布式集群》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;《Linux运维篇&#xff1a;Linux系统运维指南》 一、部署背景 由于业务系统的特殊性&#xff0c;我们需要面对不同的客户部署业务系统&#xff0…

前端如何实现更换项目主题色的功能?

1、场景 有一个换主题色的功能&#xff0c;如下图&#xff1a; 切换颜色后&#xff0c;将对页面所有部分的色值进行重新设置&#xff0c;符合最新的主题色。 2、实现思路 因为色值比较灵活&#xff0c;可以任意选取&#xff0c;所以最好的实现方式是&#xff0c;根据设置的…

全面整理人工智能(AI)学习路线图及资源推荐

在人工智能&#xff08;AI&#xff09;飞速发展的今天&#xff0c;掌握AI技术已经成为了许多高校研究者和职场人士的必备技能。从深度学习到强化学习&#xff0c;从大模型训练到实际应用&#xff0c;AI技术的广度和深度不断拓展。作为一名AI学习者&#xff0c;面对浩瀚的知识海…

递归方法清空多维数组中的null元素(对象)

源码 //【递归】说明&#xff1a;递归方法清空多维数组中的null元素&#xff08;对象&#xff09; let clearNullElementsInArray (arr) > {return (arr || []).filter(v > {if (v null) {return false;} else {if (v.children) {v.children clearNullElementsInArra…

【C语言】Linux 飞翔的小鸟

【C语言】Linux 飞翔的小鸟 零、环境部署 安装Ncurses库 sudo apt-get install libncurses5-dev壹、编写代码 代码如下&#xff1a; bird.c #include<stdio.h> #include<time.h> #include<stdlib.h> #include<signal.h> #include<curses.h>…

科普文:Linux目录详解

在 Linux/Unix 操作系统中&#xff0c;一切都是文件&#xff0c;甚至目录也是文件&#xff0c;文件是文件&#xff0c;鼠标、键盘、打印机等设备也是文件。 这篇文章&#xff0c;我们将一起学习 Linux 中的目录结构及文件。 Linux 的文件类型 Linux系统中的文件系统&#xf…

【初阶数据结构】11.排序(2)

文章目录 2.3 交换排序2.3.1 冒泡排序2.3.2 快速排序2.3.2.1 hoare版本2.3.2.2 挖坑法2.3.2.3 lomuto前后指针2.3.2.4 非递归版本 2.4 归并排序2.5 测试代码&#xff1a;排序性能对比2.6 非比较排序2.6.1 计数排序 3.排序算法复杂度及稳定性分析 2.3 交换排序 交换排序基本思想…