【C++】I/O流类库

news2024/11/29 12:50:50

I/O

数据的输入和输出(input/output简写为I/O),对标准输入设备和标准输出设备的输入输出简称为标准I/O。对在外存磁盘上的文件输入输出简称为文件I/O。对内存中指定的字符串存储空间的输入输出简称为串I/O。

数据输入输出的过程,可以形象地看成流。从流中获取数据地操作称为“提取”(输入操作)。向流中添加数据的操作称为“插入”(输出)操作。

流类库继承体系

在这里插入图片描述

  • 流类库具有两个平行的基类:streambuf和ios类,所有流类均以两者之一作为基类。
  • streambuf类提供对缓冲区的低级操作:设置缓冲区、对缓冲区指针操作、向缓冲区存/取字符。
  • ios_base、ios类记录流状态,支持对streambuf的缓冲区输入/输出的格式化或非格式化转换。
  • strstreambuf:使用串保存字符序列。扩展streambuf在缓冲区提取和插入操作。
  • filebuf:使用文件保存字符序列。包括打开文件、读/写、查找字符。

四个输入输出对象

C++为用户进行标准I/O操作定义了四个类对象:cin,cout,cerr和clog。cin为istream流类的对象,代表标准输入设备键盘,后三个为ostream流类的对象。cout代表标准输出设备显示器。cerr和clog含义相同,均代表错误信息输出设备显示器。

ostream流的操作

1.operator<<

为什么可以连续使用<<操作?<<返回值是一个ostream的引用,可以连续使用<<重载。<<提供了基本类型的重载。

2.put

put操作输出单个字符,返回一个ostream的引用。

cout.put('A').put('B').put('C');

3.write

write操作输出缓冲区指定的长度,返回一个ostream的引用。

char buf[] = "testing!!!";
cout.write(buf, 8);

istream流的操作

1.operator>>

返回值是一个istream的引用,可以连续使用>>重载。>>提供了基本类型的重载。

2.get

get操作读取单个字符,返回一个整数为字符的ASCII码。

int ch = cin.get();
cout << ch << endl;

还可以接收一个引用。

char ch, ch2;
cin.get(ch).get(ch2);
cout << ch << " " << ch2 << endl;

3.getline

getline操作读取一行(遇到回车键)。返回istream对象的引用。getline()操作与>>的区别:getline获取一个整行,>>遇到空格停止。

char buf[10] = { 0 };
cin.getline(buf, 10);
cout << buf << endl;

char buf2[10] = { 0 };
cin >> buf2;
cout << buf2 << endl;

4.read

read操作返回一个istream对象的引用,对空白字符照度不误,读取完指定数量的字符才结束。

char buf[10] = { 0 };
cin.read(buf, 5);
cout << buf << endl;

5.peek与putback

peek查看而不读取;putback将一个字符添加到流。

char c[10], c2, c3;
c2 = cin.get();
c3 = cin.get();
cin.putback(c2);
cin.getline(&c[0], 9);
cout << c << endl;

文件流

ofstream,由ostream派生而来,用于写文件。
ifstream,由istream派生而来,用于读文件。
fstream,由iostream派生而来,用于读写文件。

打开文件

说明了流对象之后,可使用函数open()打开文件。文件的打开即是在流与文件之间建立一个连接。函数原型:

void open(const char* filename,int mode = ios::out,int prot = _SH_DENYNO);

mode表示文件打开模式,prot保护模式。判断文件打开成功有5种方式:

#include <iostream>
#include <fstream>
#include <cassert>
using namespace std;

int main()
{
    ofstream fout;
    fout.open("test.txt");
    //1
    if (fout.is_open())
    {
        cout << "succ" << endl;
    }
    else
        cout << "failed" << endl;
    //2
    if (fout.good())
    {
        cout << "succ" << endl;
    }
    else
        cout << "failed" << endl;
    //3
    if (fout)
    {
        cout << "succ" << endl;
    }
    else
        cout << "failed" << endl;

    //4
    if (!fout)
    {
        cout << "failed" << endl;
    }
    else
        cout << "succ" << endl;

    //推荐使用断言方式
    assert(fout);

    fout.close();
    return 0;
}

文件打开模式

打开方式描述
iso::in打开一个供读取的文件(ifstream的默认值)
iso::out打开一个供写入的文件(ofstream的默认值)
iso::app在写之前找到文件尾
iso::ate打开文件后立即将文件定位在文件尾
iso::trunc废弃当前文件内容
iso::nocreate(已不再支持)如果要打开的文件并不存在,那么以此函数调用open()函数将无法进行
iso::noreplace(已不再支持)如果要打开的文件已存在,试图用open()函数打开时将返回一个错误
iso::binary以二进制的形式打开一个文件,默认为文本文件

保护模式

#define _SH_DENYRW      0x10    /* deny read/write mode */拒绝对文件进行读写
#define _SH_DENYWR      0x20    /* deny write mode */拒绝写入文件
#define _SH_DENYRD      0x30    /* deny read mode */拒绝文件的读取权限
#define _SH_DENYNO      0x40    /* deny none mode */读取和写入许可
#define _SH_SECURE      0x80    /* secure mode */共享读取,独占写入

文件打开的几点说明

  • 文件打开也可以通过构造函数打开,例如:
ofstream fout("test.txt,ios::out");
  • 文件的打开方式可以为上述的一个枚举常量,也可以为多个枚举常量构成的按位或表达式。

  • 使用open成员函数打开一个文件时,若由字符指针参数所指定的文件不存在,则建立该文件。

  • 当打开方式中不含有ios::ate或ios::app选项时,则文件指针被自动移到文件的开始位置,即字节地址为0的位置。

  • 从效果上看ofstream指定out模式等同于指定了out和trunc模式。

  • 默认情况下,fstream对象以in和out模式同时打开。

  • 当文件同时以in和out打开时不会清空。

  • 如果只使用out模式,而不指定in模式,则文件会清空现有数据。

  • 如果同时指定了out与app,不会清空。

  • 如果打开文件时指定了trunc模式,则无论是否同时制定了in模式,文件同样会被清空。

流状态

打开方式描述
ios::goodbit一切正常,没有错误发生,也没有输入结束
ios::eofbit输入结束
ios::failbitI/O操作失败,主要原因是非法数据(例如试图读数字时遇到字母)。流可以继续使用,输入结束时也将设置failbit位。
ios::badbit发生了(或许是物理上的)致命性错误。流将不能使用。

对应于这个标志字各状态位,ios类还提供了以下成员函数来检测或设置流的状态:

bool rdstate();             //返回流的当前状态标志字
bool eof();                 //返回非0值表示到达文件尾
bool fail();                //返回非0值表示操作失败
bool bad();                 //返回非0值表示出现错误
bool good();                //返回非0值表示流操作正常
bool clear(int flag=0);     //将流的状态设置为flag

为提高程序的可靠性,应在程序中检测I/O流的操作是否正常。当检测到流操作出现错误时,可以通过异常处理来解决问题。

文件关闭

每个文件流类中都提供有一个关闭文件的成员函数close()。功能:当打开的文件操作结束后,就需要关闭它,使文件流与对应的物理文件断开联系,并能够保证最后输出到文件缓冲区中的内容,无论是否已满,都将立即写入到对应的物理文件中。文件流对应的文件被关闭后,还可以利用该文件流调用open成员函数打开其他的文件,最好先clear 一下。

文件读写

1.>>和<<

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main()
{
    ofstream fout("test.txt");
    fout << "abcd" << " " << 200;
    fout.close();

    ifstream fin("test.txt");
    string s;
    int n;
    fin >> s >> n;
    cout << s << " " << n << endl;

    return 0;
}

2.put和get

#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
using namespace std;

int main()
{
    ofstream fout("test2.txt");
    char ch;

    assert(fout);

    for (int i = 0; i < 26; i++)
    {
        ch = 'A' + i;
        fout.put(ch);
    }
    fout.close();

    ifstream fin("test2.txt");
    while (fin.get(ch))
    {
        cout << ch;
    }

    return 0;
}

3.read和write

后面二进制文件读写介绍。

4.文本模式与二进制模式打开区别

如果以文本打开文件,写入字符的时候,遇到\n会作转换。windows平台\n会转为\r\n,linux平台保留不变,mac系统\n转换为\r。\r不做转换。如果以二进制方式打开文件写入字符时不做转换。以文本方式打开文件,也可以写入二进制数据,以二进制方式打开文件,也可以写入文本。写入的数据是二进制还是文本,与打开方式无关,与写入使用的函数有关。要写入二进制数据应该用write,相应的读要用read。

二进制文件的读写

二进制文件不同于文本文件,它可用于任何类型的文件(包括文本文件)。对二进制文件的读写可采用从istream类继承下来的成员函数read()和ostream类继承下来的成员函数write()。文件打开操作时使用枚举常量ios::binary,例如:

ofstream fout("binary.dat",ios::out|ios::binary);
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
using namespace std;

struct Test
{
    int a;
    int b;
};
int main()
{
    Test test = { 100,200 };
    ofstream fout("binary.txt", ios::out | ios::binary);
    fout.write(reinterpret_cast<char*>(&test),sizeof(Test));
    fout.close();

    Test test2;
    ifstream fin("binary.txt", ios::in | ios::binary);
    fin.read(reinterpret_cast<char*>(&test2),sizeof(Test));
    cout << test2.a << " " << test2.b << endl;

    return 0;
}

当字符串足够长时文件读写

#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
using namespace std;

struct Test
{
    int x;
    string a;
    string b;
};
int main()
{
    Test t1;
    t1.x = 100;
    t1.a = "asdfsdafasfdasdfasdffsdfsdafadsadsfdfsfdsafdasfdsadfasdsfaasfddsfsadfsdfafdsasadffads";
    t1.b = "qwerqwerqrwewqrrqewewrewrqrqewerwqrewqqwerrweqrewqreqwerqwrqewrqweqrwerweqqrwerqwerwesfadsfafdfadsasfasdafsqrw";
    ofstream fout("test4.txt", ios::out | ios::binary);
    fout.write((char*)(&t1.x),sizeof(int));
    int len;
    len = t1.a.length();
    fout.write((char*)&len, sizeof(int));
    fout.write(t1.a.data(), t1.a.length());
    len = t1.b.length();
    fout.write((char*)&len, sizeof(int));
    fout.write(t1.b.data(), t1.b.length());
    fout.close();

    ifstream fin("test4.txt", ios::in | ios::binary);
    Test t2;
    fin.read((char*)(&t2.x),sizeof(int));
    fin.read((char*)(&len), sizeof(int));
    t2.a.resize(len);
    fin.read(&t2.a[0], len);
    fin.read((char*)(&len), sizeof(int));
    t2.b.resize(len);
    fin.read(&t2.b[0], len);
    cout << t2.x << " " << t2.a << " " << t2.b << endl;

    return 0;
}

当前文件流活动指针

文件流指针用以跟踪发生I/O操作的位置。每当从流中读取或写入一个字符,当前活动指针就会向前移动。当打开方式中不含有ios::ate或ios::app选项时,则文件指针被自动移到文件的开始位置,即字节地址为0的位置。

文件的随机读写seekp和seekg

  • seekp:设置输出文件流的文件流指针位置。
  • seekg:设置输入文件流的文件流指针位置。

函数参数:pos新的文件流指针位置,off需要偏移的值,dir搜索的起始位置。

文件的随机读写tellp和tellg

  • tellp:获得输出的文件流指针的当前位置,以字节为单位。
  • tellg:获得输入的文件流指针的当前位置,以字节为单位。

函数返回值实际上是一个long类型。

#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
using namespace std;

struct Test
{
    int x;
    string a;
    string b;
};
int main()
{
    ifstream fin("test5.txt");
    assert(fin);
    fin.seekg(2);

    char ch;
    fin.get(ch);
    cout << ch << endl;

    fin.seekg(-1, ios::end);
    fin.get(ch);
    cout << ch << endl;

    fin.seekg(0, ios::end);
    streampos pos = fin.tellg();
    cout << pos << endl;

    return 0;
}

seek_dir

dir参数用于对文件流指针的定位操作上,代表搜索的起始位置。在ios中定义的枚举类型:

enum seek_dir{beg,cur,end};

beg表示文件流的起始位置,cur表示文件流的当前位置,end表示文件流的结束位置。

输出流的格式化

数据输入输出的格式控制使用系统头文件中提供的操纵符。把它们作为插入操作符<<的输出对象即可。如setiosflags、setw、setfill、setprecision、hex、oct等。

#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
    int n = 64;
    double d = 123.45;
    double d2 = 0.0187;

    //通过操纵子方式进行格式化输出
    cout << "====================宽度控制====================" << endl;
    cout << n << "#" << endl;
    cout << setw(10) << n << "#" << endl;                                   //默认右对齐
    cout << setw(10) << n << "#" << n << endl;                              //宽度控制不会影响下一个输出

    cout << "====================对齐控制====================" << endl;
    cout << setw(10) << setiosflags(ios::left) << n << "#" << endl;         //设置左对齐
    cout << setw(10) << n << "#" << endl;                                   //对齐控制影响下一个输出
    cout << setw(10) << setiosflags(ios::right) << n << "#" << endl;        //设置右对齐
    cout << setw(10) << resetiosflags(ios::left) << n << "#" << endl;       //取消左对齐

    cout << "====================对齐控制====================" << endl;
    cout << setw(10) << setfill('?') << n << "#" << endl;
    cout << setw(10) << n << "#" << endl;                                   //填充控制影响下一个输出
    cout << setw(10) << setfill(' ') << n << "#" << endl;

    cout << "====================精度控制====================" << endl;
    cout << setprecision(4) << d << endl;                                   //保留四位有效数字
    cout << setprecision(2) << d2 << endl;
    cout << setiosflags(ios::fixed);
    cout << setprecision(4) << d << endl;                                   //保留小数点后四位
    cout << setprecision(2) << d2 << endl;

    cout << "====================进制输出====================" << endl;
    cout << n << endl;
    cout << dec << n << endl;
    cout << oct << n << endl;
    cout << hex << n << endl;
    cout << endl;

    cout << setiosflags(ios::showbase);
    cout << dec << n << endl;
    cout << oct << n << endl;
    cout << hex << n << endl;
    cout << endl;

    cout << setbase(10) << n << endl;
    cout << setbase(8) << n << endl;
    cout << setbase(16) << n << endl;
    return 0;
}

通过调用流的成员函数控制格式,如setf、unsetf、width、fill、precision等。优点是在设置格式同时,可以返回以前的设置,便于恢复原来的设置。

#include <iostream>
using namespace std;

int main()
{
    int n = 64;
    double d = 123.45;
    double d2 = 0.0187;

    cout << "====================宽度控制====================" << endl;//宽度控制不会影响下一个输出
    cout << n << "#" << endl;

    cout.width(10);
    cout << n << "#" << endl;

    cout << n << "#" << endl;

    cout << "====================对齐控制====================" << endl;//对齐控制影响下一个输出
    cout.width(10);
    cout.setf(ios::left);
    cout << n << "#" << endl;

    cout.width(10);
    cout << n << "#" << endl;

    cout.width(10);
    cout.unsetf(ios::left);
    cout << n << "#" << endl;

    cout.width(10);
    cout.setf(ios::right);
    cout << n << "#" << endl;

    cout << "====================对齐控制====================" << endl;//填充控制影响下一个输出
    cout.width(10);
    cout.fill('?');
    cout << n << "#" << endl;

    cout.width(10);
    cout << n << "#" << endl;

    cout.width(10);
    cout.fill(' ');
    cout << n << "#" << endl;

    cout << "====================精度控制====================" << endl;
    cout.precision(4);//保留四位有效数字
    cout << d << endl;
    cout.precision(2);
    cout << d2 << endl;

    cout.setf(ios::fixed);
    cout.precision(4);//保留小数点后四位
    cout << d << endl;
    cout.precision(2);
    cout << d2 << endl;

    cout << "====================进制输出====================" << endl;
    cout.setf(ios::showbase);
    cout << n << endl;
    cout.unsetf(ios::dec);
    cout.setf(ios::oct);
    cout << n << endl;

    cout.unsetf(ios::showbase);
    cout << n << endl;
    return 0;
}

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

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

相关文章

边缘智能:边缘计算和人工智能的深度融合

摘要 随着通信技术的飞速发展和移动设备使用的激增&#xff0c;一种全新的计算范式——边缘计算正在迅速普及。与此同时&#xff0c;随着深度学习的突破和硬件架构的许多改进&#xff0c;人工智能(AI)应用正在蓬勃发展。在网络边缘产生数十亿字节的数据&#xff0c;对数据处理…

也聊聊BLDC 电机的 10 大热门应用---【其利天下技术分享】

近年来&#xff0c;随着全球提出的低碳&#xff0c;高能效的概念提出&#xff0c;作为高效动力来源的BLDC技术&#xff0c;越来越受到各界的追捧。 大家都知道&#xff0c;BLDC的发展史也就短短几十年的时间&#xff0c;随着近年来&#xff0c;新磁性材料的运用、微电子技术和…

基于大模型的虚拟数字人__虚拟主播实例

基于大模型的虚拟数字人__虚拟主播实例 本文目录&#xff1a; 一、技术的背景&#xff1a; 二、创意名称&#xff1a; 三、创意背景 四、创意目标 五、创意设计 六、技术实现路径 七、完整代码实现 八、创意总结 九、人工智能虚拟人物的一些优秀代表作品及其特点 十、…

河道水位标尺识别预警 yolov7

河道水位标尺识别预警系统通过pythonyolov7网络模型技术&#xff0c;河道水位标尺识别预警算法对河道水位标尺进行实时监测&#xff0c;当河道水位出现异常情况时&#xff0c;河道水位标尺识别预警算法将自动发出警报提示后台管理人员及时采取措施。YOLO系列算法是一类典型的on…

【工具篇】SpringBoot基于assembly的服务化打包方案

简介 最近项目中&#xff0c;使用插件式开发方式&#xff0c;将多个Web应用打成一个FatJar程序包部署运行。但考虑到原始裸Jar包方式交付&#xff0c;有很多不便之处&#xff0c;比如启动命令过长&#xff08;JVM参数配置、Spring环境配置等&#xff09;、配置无法修改等问题会…

基于OpenMV的自动驾驶智能小车模拟系统

一、项目简介 基于机器视觉模块OpenMV采集车道、红绿灯、交通标志等模拟路况信息&#xff0c;实现一辆能车道保持、红绿灯识别、交通标志识别、安全避障以及远程WiFi控制的多功能无人驾驶小车。 赛道规格&#xff1a; 1、编程所需软件&#xff1a; OpenMV&#xff1a;使用Op…

cuda pyinstall cvs 使用记录

1.pip 换源 pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/2.安装匹配cuda的pytorch 官网&#xff1a;PyTorch pip3 install torch torchvision torchaudio查看能否使用cuda: import torch torch.cuda.is_available()获得以下反馈&#xff1a; 意思…

CSS基础学习--22 图像透明/不透明

一、透明度属性 CSS3中属性的透明度是 opacity 正常的图像 相同的图像带有透明度&#xff1a; img {opacity:0.4;filter:alpha(opacity40); /* IE8 及其更早版本 */ } 备注&#xff1a;Opacity属性值从0.0 - 1.0。值越小&#xff0c;使得元素更加透明。 IE8和早期版本使用滤…

【MySQL】库和表结构的增删查改

目录 一、库的操作 1、创建数据库 2、数据库所使用的编码 2.1查询编码集和校验集 2.2查看数据库的字符集和校验集 2.3创建数据库指定字符集和校验集 2.4不同的校验集所筛选的数据结果不一样 3、查看数据库 4、修改数据库 5、删除数据库 6、数据库的备份和恢复 6.1备…

【Spring MVC】获取 @RequsetBody 标识的对象,使用适配器模式增加代码可读性

1. 前言 一个技术需求引发的思考和实践&#xff1a; 思考 用 AOP 把校验代码 实践 用 Spring MVC 的 RequestBodyAdvice 做AOP逻辑继承 RequestBodyAdviceAdapter 实现自己的 适配器用自己的适配器让代码可读性增加熟悉 Spring MVC 、Java 反射的一些实践 本文内容 澄清一个A…

Mysql 调优

前言 硬件层面&#xff1a;使用固态硬盘、扩大内存、加大带宽等等 架构层面&#xff1a;主从复制实现读写分离【一主一 或 双主双从】 表结构层面&#xff1a;对表结构进行垂直拆分、水平分表、分库分表。常用的数据库中间件有&#xff1a;MySQL Proxy、MyCat以及ShardingSphe…

电脑C盘的清理 | 微信QQ缓存信息

记录一下我处理C盘爆满时的几个方法&#xff0c;基本上都是可以日常使用的。 一、磁盘清理 链接 二、查看具体哪些文件占内存 win图标右击 -----> 点击“系统&#xff08;Y&#xff09;” 点击查看具体是哪些文件夹哪些app占用了大量的内存&#xff0c;并选择删除部分…

第二章 re模块

1. re模块介绍 正则表达式 在处理字符串时&#xff0c;经常会有查找符合某些复杂规则的字符串的需求。正则表达式就是用于描述这些规则的工具。换句话说&#xff0c;正则表达式就是记录文本规则的代码。 re 模块 Python 提供了 re 模块用于实现正则表达式的操作。在实现时&…

CTFshow-pwn入门-前置基础pwn23-pwn25

pwn23-25的题目会涉及到ret2shellcode、ret2libc等内容&#xff0c;本篇文章只会侧重研究这几道题目的wp&#xff0c;不会过多涉及到ret2shellcode、ret2libc的基本原理&#xff0c;等有时间再来写关于ret2libc、ret2shellcode…的相关内容。大家可以参考CTFwiki的文章去慢慢学…

FPGA_数码管显示UART串口接收的数据

实验目标&#xff1a;通过电脑调试助手向FPGA的UART串口接收模块发送数据&#xff0c;然后数据可以稳定显示在数码管上。 实验目的: 练习UART串口模块和数码管的使用。之前已经有文章详细讲解了串口和数码管的开发&#xff0c;故这里直接提供设计思路供大家参考。 &#xff08…

求解矩阵行列式因子、不变因子、初等因子、Jordan标准形

首先&#xff0c;我们先来简要了解一下行列式因子、不变因子和初等因子的概念。 下面举例说明。 例1 首先&#xff0c;我们要求 λ I − A λI-A λI−A 然后&#xff0c;我们先求行列式因子。 D 2 ( λ ) D_2(λ) D2​(λ)的求法如下&#xff1a; 然后&#xff0c;我们再求…

015、数据库管理之用户和权限

用户和权限 认证与赋权连接过程本地连接远程连接查看用户信息创建用户账号创建角色管理用户账户管理角色设置账号密码忘记root密码实验1-用户和角色实验2-授权注意事项 认证与赋权 认证&#xff1a;对用户进行验证 是权限控制的第一步当用户第一次连接数据库时必须进行认证如果…

【Git】TortoiseGit(小乌龟)配置SSH和使用

目录 1、TortoiseGit&#xff08;小乌龟&#xff09;配置SSH 1.1、右击打开Git命令窗口 1.2、设置Git的全局name和email 1.3、查看是全局名字和邮箱是否设置成功 1.4、生成 sshkey秘钥 2、TortoiseGit&#xff08;小乌龟&#xff09;的使用 2.1、创建本地仓库 2.2、添加…

企业会计软件必备!深入了解为何选择会计软件以及其带来的好处

随着科技的发展&#xff0c;企业需要更加智能化和数字化的财务管理方式&#xff0c;因此会计软件是现代社会的必然产物&#xff0c;会计软件可以帮助企业更有效地进行财务管理。 企业为什么需要会计软件&#xff1f; 提高准确度 通过传统的手工操作财务记录&#xff0c;会有很…

Qt6.2教程——2.介绍 Qt 中的 QWidgets、QMainWindow 和 QDialog

详细介绍 Qt 中的 QWidgets、QMainWindow 和 QDialog Qt 是一个广受欢迎的跨平台 C GUI 库。在 Qt 中&#xff0c;创建图形用户界面的基本单元是 Widget。本文将详细介绍三个重要的 Widget 类&#xff1a;QWidget, QMainWindow 和 QDialog&#xff0c;并比较它们的特点和用途。…