IO进程线程day3(2023.7.31)

news2024/11/16 20:25:30

一、Xmind整理:

文件描述符概念:

二、课上练习:

练习1:用fread和fwrite实现文件拷贝 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	//以读的方式打开源文件
	FILE* fp_r=fopen("./01_fopen.c","r");
	if(NULL==fp_r)
	{
		ERR_MSG("fopen");
		return -1;
	}
    //以写的方式打开源文件
	FILE* fp_w=fopen("./copy.c","w");
	if(NULL==fp_w)
	{
		ERR_MSG("fopen");
		return -1;
	}

	//读一次写一次,直到文件读取完毕
	char buf[128]="";
	size_t res=0;
	while(1)
	{
		bzero(buf,sizeof(buf));
		//以128为单位,读取1个数据,所当不足128的时候
		//剩下的数据读取不出来,所以这个代码是错误的
		res=fread(buf,1,sizeof(buf),fp_r);
		printf("res=%ld\n",res);
		if(0==res)
			break;
		fwrite(buf,1,res,fp_w);
	}
	printf("拷贝完毕\n");

	//关闭
	fclose(fp_w);
	fclose(fp_r);


	return 0;
}

练习2:time

功能:从1970-1-1日至今的秒数

原型:

 #include <time.h>
 time_t time(time_t *tloc);

参数:

time_t *tloc:若不为空,则1970-1-1日至今的秒数同样会被存储到该指针指向的内存空间中;

返回值:

成功,返回1970-1-1日至今的秒数;
失败,返回((time_t) -1),更新errno;
time_t t = time(NULL);  
printf("%ld\n", t);
time_t pt;                     
time(&pt);
printf("%ld\n", pt);

练习3:localtime

功能:将1970-1-1日至今的秒数转换成日历格式

原型:

#include <time.h>
struct tm *localtime(const time_t *timep);

参数:

time_t *timep: 指定要转换成日历格式的秒数的首地址;

返回值:

成功,返回结构体指针;  vi -t tm可以查看struct tm 成员 或者man手册往下翻
失败,返回NULL;更新errno;      
struct tm {
             int tm_sec;    /* Seconds (0-60) */         秒
             int tm_min;    /* Minutes (0-59) */         分
             int tm_hour;   /* Hours (0-23) */           时
             int tm_mday;   /* Day of the month (1-31) */  日
             int tm_mon;    /* Month (0-11) */             月= tm_mon+1
             int tm_year;   /* Year - 1900 */              年= tm_year+1900
             int tm_wday;   /* Day of the week (0-6, Sunday = 0) */    星期
             int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */   一年中的第几天

          };

例题: 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	/*
	time_t t=time(NULL);
	printf("%ld\n",t);

	time _t pt;
	time(&pt);
	printf("%d\n",pt);
	*/
	time_t t;
	struct tm* info=NULL;

	while(1)
	{
		t=time(NULL);
		info=localtime(&t);
		printf("%d-%02d-%02d %02d:%02d:%02d\r",\
				info->tm_year+1900,info->tm_mon+1,info->tm_mday,\
				info->tm_hour,info->tm_min,info->tm_sec);
		fflush(stdout);
		sleep(1);
	}

	return 0;
}

练习4:文件描述符的总量

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	printf("%d %d %d\n",stdin->_fileno,stdout->_fileno,stderr->_fileno);
	FILE*fp=NULL;
	while(1)
	{
		fp=fopen("./1.txt","w");
		if(NULL==fp)
		{
			ERR_MSG("fopen");
			return -1;
		}
		printf("%d ",fp->_fileno);
		fflush(stdout);
	}
	return 0;
}

练习5:open

功能:打开一个文件

原型:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

参数:

 char *pathname:指定要打开的文件的路径和名字;
 int flags:打开方式
     O_RDONLY     只读, 
     O_WRONLY     只写,
     O_RDWR       读写
 ----以上三种必须包含一种----------
     O_APPEND     追加方式打开,
     O_TRUNC      清空,若文件存在,且是一个普通文件,且以写的方式打开
     O_CREAT      若文件不存在,则创建一个普通文件。
 若有多个选项合成一个打开方式,则用按位或连接:
     "w":O_WRONLY | O_CREAT | O_TRUNC
 mode_t mode:用来指定文件创建的时候的权限,例如:0664
 若flags中包含了O_CREAT或者O_TMPFILE的时候,就必须写mode参数;
 若flags没有O_CREAT或者O_TMPFILE的时候,会忽略mode参数;

返回值:

成功,返回文件描述符,
失败,返回-1,更新errno;

注意:

标准IO中的 r r+ w w+ a a+,用文件IO中的flags进行组合。

 

练习6:umask

the mode of the created file is (mode & ~umask).

文件创建时候的真实权限是 mode & ~umask

mode: 0777 -> 111 111 111 umask?111 111 101=> ~umask -> umask = 000 000 010 = 0002

结果: 0775 ----> 111 111 101

i. umask是什么

文件权限掩码,目的就是影响文件创建时候的权限。可以通过设置umask的值保证某些用户肯定没有某些权限。

ii. 获取umask的值

终端输入:umask

iii. 修改umask的值

1.终端输入: umask 0 只在设置终端有效

2.umask()函数

 #include <sys/types.h>
 #include <sys/stat.h>
 mode_t umask(mode_t mask);
 umask(0);

练习7:close

功能:关闭文件; 释放文件描述符

原型:

#include <unistd.h>
int close(int fd);

参数:

int fd:指定要关闭的文件描述符;

返回值:

成功,返回0;
失败,返回-1,更新errno;

练习8:write

功能:将数据写入到文件中

原型:

 #include <unistd.h>
 ssize_t write(int fd, const void *buf, size_t count);

参数:

int fd:指定要将数据写入到哪个文件中,填对应的文件描述符;
void *buf:指定要输出的数据的首地址,可以是任意类型数据;
size_t count:指定要输出的数据字节数;

返回值:

成功,返回成功输出的字节数;
失败,返回-1,更新errno;

 例题: 创建一个权限是0777的文件,并在数据写入到文件中

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	//将本程序的umask的值修改成0
	umask(0);
	int fd=open("./open.txt",O_WRONLY|O_CREAT|O_TRUNC,0777);
	if(fd<0)
	{
		ERR_MSG("open");
		return -1;
	}
	printf("open success\n");

	ssize_t res=0;
	char buf[]="hello world";
	res=write(fd,buf,sizeof(buf));
	printf("res=%ld\n",res);

	if(close(fd)<0)
	{
		ERR_MSG("close");
		return -1;
	}
	printf("close success\n");
	return 0;
}

注意: 

write函数指定写多少个字节,就会从内存中拿多少个字节,写入到文件中,即使越界

练习9:read

功能:从文件中读取数据

原型:

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

参数:

int fd:指定要从哪个文件中读取数据,填对应的文件描述符;
void *buf:指定要将读取到的数据存储到那块空间中,可以是任意类型数据;
size_t count:指定要读取的数据字节数;

返回值:

 >0, 成功,返回成功读取的字节数;
 =0, 文件读取完毕;
 =-1, 失败,返回-1,更新errno;

 例题1: read的使用

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	//将本程序的umask的值修改成0
	umask(0);
	int fd=open("./01_fileno.c",O_RDONLY);
	if(fd<0)
	{
		ERR_MSG("open");
		return -1;
	}
	printf("open success\n");

	ssize_t res=0;
	char buf[128]="";

	while(1)
	{
		bzero(buf,sizeof(buf));
		res=read(fd,buf,sizeof(buf));
		if(0==res)
		{
			break;
		}
		//将数据写到终端,写的个数为实际读取到的字节数
		write(1,buf,res);
	}

#if 0
	while(1)
	{
		bzero(buf,sizeof(buf));
		/***************************************/
		//由于后续打印的是使用%s打印,所以需要保留一个\0位置
		//防止%s打印的时候越界少\0位 
		res=read(fd,buf,sizeof(buf)-1);
		if(0==res)
		{
			break;
		}
		printf("%s",buf);    //%s打印直到遇到\0位置
	}
#endif
	printf("读取完毕\n");
	if(close(fd)<0)
	{
		ERR_MSG("close");
		return -1;
	}
	printf("close success\n");

	return 0;
}

 例题2:用read和write函数实现,拷贝图片

 提示:1.ls-l查看图片类型

            2.eog  图片--->打开图片

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	//以读的方式打开源文件
	int fd_r=open("./1.png",O_RDONLY);
	if(fd_r<0)
	{
		ERR_MSG("open");
		return -1;
	}
	printf("open success\n");
	//以写的方式打开目标文件
	int fd_w=open("./2.png",O_WRONLY|O_CREAT|O_TRUNC,0664);
	if(fd_w<0)
	{
		ERR_MSG("open");
		return -1;
	}

	ssize_t res=0;
	char buf[128]="";
	//读一次写一次
	while(1)
	{
		bzero(buf,sizeof(buf));
		res=read(fd_r,buf,sizeof(buf));
		if(0==res)
		{
			break;
		}
		//读多少个就写多少个
		if(write(fd_w,buf,res)<0)
		{
			ERR_MSG("write");
			return -1;
		}
	}
	printf("拷贝完成\n");
	//关闭
	if(close(fd_r)<0)
	{
		ERR_MSG("close");
		return -1;
	}
	if(close(fd_w)<0)
	{
		ERR_MSG("close");
		return -1;
	}

	printf("close success\n");
	return 0;
}

练习10:lseek

功能:修改文件偏移量

原型:

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

参数:

int fd:文件描述符;
off_t offset: 距离whence参数指定的偏移量。往前偏移填负数, 往后偏移填正数
int whence:
    SEEK_SET,  文件开头位置
    SEEK_CUR,  文件当前位置
    SEEK_END   文件结尾位置

返回值:

成功,修改偏移量后,文件当前位置距离文件开头的偏移量;
失败,返回-1,更新errno;    
//计算文件大小
off_t size = lseek(fd_r, 0, SEEK_END);
printf("size=%ld\n", size);

例题:lseek的使用 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	//以读的方式打开源文件
	int fd_r=open("./1.png",O_RDONLY);
	if(fd_r<0)
	{
		ERR_MSG("open");
		return -1;
	}
	//计算文件大小
	off_t size=lseek(fd_r,0,SEEK_END);
	printf("size=%ld\n",size);
	//关闭
	close(fd_r);
	return 0;
}

注意: 

若偏移量在文件开头,能否继续往前偏移 ---> 不行

若偏移量在文件结尾,能否继续往后偏移 ---> 可以

练习11:获取文件属性

练习12:stat

功能:获取文件的属性

原型:

 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 int stat(const char *pathname, struct stat *statbuf);

参数:

char *pathname:指定要获取属性的文件路径以及名字;
struct stat *statbuf:存储获取到的属性;

返回值:

成功,返回0;
失败,返回-1,更新errno;
    
vi -t stat 或者 man手册往下翻
struct stat 
{
 ino_t     st_ino;         /* Inode number */            inode号
 mode_t    st_mode;        /* File type and mode */      文件类型和权限
 nlink_t   st_nlink;       /* Number of hard links */    硬链接数
 uid_t     st_uid;         /* User ID of owner */        用户的uid
 gid_t     st_gid;         /* Group ID of owner */       组用户的gid
 off_t     st_size;        /* Total size, in bytes */    文件大小

 struct timespec st_atim;  /* Time of last access */         最后一次被访问的时间
 struct timespec st_mtim;  /* Time of last modification */   最后一次被修改的时间
 struct timespec st_ctim;  /* Time of last status change */  最后一次改变状态的时间
 #define st_atime st_atim.tv_sec      /* Backward compatibility */
 #define st_mtime st_mtim.tv_sec
 #define st_ctime st_ctim.tv_sec
};

提取文件的权限:

mode_t st_mode 本质上是一个unsigned int类型,里面存储了文件的类型和权限。

st_mode中其中低9bits存储了文件的权限:[0bit - 8bit]

例题:文件权限提取 

#include <stdio.h>
#include <head.h>

void get_filePermission(mode_t m)   //mode_t m = buf.st_mode
{
    if((m & 0400) != 0)
        putchar('r');
    else
        putchar('-');

    if((m & 0200) != 0)                                      
        putchar('w');
    else
        putchar('-');

    if((m & 0100) != 0)
        putchar('x');
    else
        putchar('-');

    ///
    if((m & 0040) != 0)
        putchar('r');
    else
        putchar('-');

    if((m & 0020) != 0)
        putchar('w');
    else
        putchar('-');

    if((m & 0010) != 0)
        putchar('x');
    else
        putchar('-');
    

    if((m & 0004) != 0)
        putchar('r');
    else
        putchar('-');

    if((m & 0002) != 0)
        putchar('w');
    else
        putchar('-');

    if((m & 0001) != 0)
        putchar('x');
    else
        putchar('-');

    return;
}
int main(int argc, const char *argv[])
{
    struct stat buf;
    if(stat("./01_fileno.c", &buf) < 0)
    {
        ERR_MSG("stat");
        return -1;
    }

    //文件的类型和权限
    printf("mode: 0%o\n", buf.st_mode);
    get_filePermission(buf.st_mode);

    //文件的硬链接数
    printf("link: %ld\n", buf.st_nlink);

    //文件的所属用户
    printf("uid: %d\n", buf.st_uid);

    //文件所属组用户
    printf("gid: %d\n", buf.st_gid);

    //文件大小
    printf("size: %ld\n", buf.st_size);

    //文件的修改时间
    printf("time: %ld\n", buf.st_ctime);

    //文件的名字
	
    return 0;
}

三、课后作业:

1.用read函数计算文件的大小 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	int fd = open("./1.png",O_RDONLY);
	if(fd < 0)
	{
		ERR_MSG("open");
		return -1;
	}
	printf("open success\n");

	off_t size = lseek(fd,0,SEEK_END);
	printf("size=%ld\n",size);

	char c;
	ssize_t res = 0;
	int count = 0;
	lseek(fd,0,SEEK_SET);
	while(1)
	{
		res = read(fd,&c,1);
		if(0 == res)
			break;
		count++;
	}
	printf("count=%d\n",count);

	if(close(fd) < 0)
	{
		ERR_MSG("close");
		return -1;
	}
	printf("close success\n");

	return 0;
}

2.将课上的文件权限提取修改成循环方式

#include <stdio.h>
#include <head.h>

void get_filePermission(mode_t m)
{
	long x=0400;
	char c[]="rwx";
	int count=0;
	while(x)
	{
		if((m & x) != 0)
			putchar('r');
		else
			putchar('-');
		x=x>>1;
		if((m & x) != 0)                                      
			putchar('w');
		else
			putchar('-');
		x=x>>1;
		if((m & x) != 0)
			putchar('x');
		else
			putchar('-');
		x=x>>1;
	}

	return;
}
int main(int argc, const char *argv[])
{
    struct stat buf;
    if(stat("./01_fileno.c", &buf) < 0)
    {
        ERR_MSG("stat");
        return -1;
    }

    //文件的类型和权限
    printf("mode: 0%o\n", buf.st_mode);
    get_filePermission(buf.st_mode);

    //文件的硬链接数
    printf("link: %ld\n", buf.st_nlink);

    //文件的所属用户
    printf("uid: %d\n", buf.st_uid);

    //文件所属组用户
    printf("gid: %d\n", buf.st_gid);

    //文件大小
    printf("size: %ld\n", buf.st_size);

    //文件的修改时间
    printf("time: %ld\n", buf.st_ctime);
	
    return 0;
}

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

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

相关文章

12-3_Qt 5.9 C++开发指南_创建和使用静态链接库

第12章中的静态链接库和动态链接库介绍&#xff0c;都是以UI操作的方式进行&#xff0c;真正在实践中&#xff0c;可以参考UI操作产生的代码来实现同样的功能。 文章目录 1. 创建静态链接库1.1 创建静态链接库过程1.2 静态链接库代码1.2.1 静态链接库可视化UI设计框架1.2.2 qw…

八大排序算法--快速排序(动图理解)

快速排序 概念 快速排序是对冒泡排序的一种改进。其基本原理是通过选取一个基准元素&#xff0c;将数组划分为两个子数组&#xff0c;分别对子数组进行排序&#xff0c;最终实现整个数组的有序排列。快速排序的时间复杂度最好为O(nlogn)&#xff0c;最坏为O(n^2)&#xff0c;…

5个值得收藏的AI绘画网站,还有国产!

随着科技的发展&#xff0c;设计领域也迎来了科技创新&#xff0c;AI绘画网站便是其中的一个代表&#xff0c;本文精选了4个好用的AI绘画网站与大家分享&#xff0c;一起来看看吧&#xff01; 1、即时灵感 作为一个国产的AI绘画网站&#xff0c;即时灵感支持设计师使用中文语…

Spring | Bean 作用域和生命周期

一、通过一个案例来看 Bean 作用域的问题 Spring 是用来读取和存储 Bean&#xff0c;因此在 Spring 中 Bean 是最核心的操作资源&#xff0c;所以接下来我们深入学习⼀下 Bean 对象 假设现在有⼀个公共的 Bean&#xff0c;提供给 A 用户和 B 用户使用&#xff0c;然而在使用的…

IO流简述

IO流IO流使用场景 什么是IO流常用的IO流字节流字符流缓冲流 BIO、NIO、AIO的区别 IO流 IO流使用场景 如果操作的是纯文本文件&#xff0c;优先使用字符流如果操作的是图片、视频、音频等二进制文件。优先使用字节流如果不确定文件类型&#xff0c;优先使用字节流。字节流是万能…

【LLM系列之指令微调】长话短说大模型指令微调的“Prompt”

1 指令微调数据集形式“花样”太多 大家有没有分析过 prompt对模型训练或者推理的影响&#xff1f;之前推理的时候&#xff0c;发现不加训练的时候prompt&#xff0c;直接输入模型性能会变差的&#xff0c;这个倒是可以理解。假如不加prompt直接训练&#xff0c;是不是测试的时…

linux网络编程--select多路IO转接模型

目录 1.TCP状态转换图 2.端口复用 3.半关闭状态 4.心跳包 5.高并发服务器模型--select 6.提纲总结 学习目录 熟练掌握TCP状态转换图熟练掌握端口复用的方法了解半关闭的概念和实现方式了解多路IO转接模型熟练掌握select函数的使用熟练使用fd_set相关函数的使用能够编写s…

winform学习(3)-----Windows窗体应用和Windows窗体应用(.Net Framework)有啥区别?

1.模板选择 在学习winform的时候总是会对这两个应用不知道选择哪个&#xff1f;而且在学习的时候也没有具体的说明 首先说一下我是在添加控件的时候出现了以下问题 对于使用了Windows窗体应用这个模板的文件在工具箱中死活不见控件。 在转换使用了Windows窗体应用(.NET Fram…

JAVA基础原理篇_1.1—— 关于JVM 、JDK以及 JRE

目录 一、关于JVM 、JDK以及 JRE 1. JVM 2. JDK 3. JRE 二、为什么说 Java 语言“编译与解释并存”&#xff1f; 2.2 将高级编程语言按照程序的执行方式分为两种&#xff1a; 2.2 Java的执行过程&#xff1a; 2.3 所以为什么Java语言“编译与解释"共存&#xff1a…

Quartz中Misfire机制源码级解析

文章目录 前文案例展示Misfire机制1. 启动过程补偿2. 定时任务补偿3. 查询待触发列表时间区间补偿 前文 Misfire是啥意义的&#xff1f;使用翻译软件结果是"失火"。一个定时软件&#xff0c;还来失火&#xff1f;其实在Java里面&#xff0c;fire的含义更应该是触发&…

Ai创作系统ChatGPT源码搭建教程+附源码

系统使用Nestjs和Vue3框架技术&#xff0c;持续集成AI能力到本系统&#xff01; 更新内容&#xff1a; 同步官方图片重新生成指令 同步官方 Vary 指令 单张图片对比加强 Vary(Strong) | Vary(Subtle) 同步官方 Zoom 指令 单张图片无限缩放 Zoom out 2x | Zoom out 1.5x 新增GP…

Linux学习之信号

trap -l和kill -l都可以列出来信号所有值。 而trap "命令1;命令2;" 信号可以捕捉到信号之后再执行命令1、命令2等命令&#xff0c;这里的命令可以不止两条。 快捷键产生信号 echo "This is a test" > trapTest.txt将This is a test写入到trapTest.t…

分布式配置中心Nacos

文章目录 一、Nacos分布式配置中心1、使用分布式配置中心的优点2、Nacos配置中心和应用间的数据同步的三种模式3、Namespace命名空间4、DataID配置5、Group配置 二、Nacos分布式配置中心的使用1、将应用对接Nacos配置中心2、Nacos实现配置动态刷新RefreshScope3、Dubbo服务对接…

QT--day6(人脸识别、图像处理)

人脸识别&#xff1a; /***********************************************************************************头文件****************************************************************************************/#ifndef WIDGET_H #define WIDGET_H#include <QWidget>…

HCIP期中实验

考试需求 1 、该拓扑为公司网络&#xff0c;其中包括公司总部、公司分部以及公司骨干网&#xff0c;不包含运营商公网部分。 2 、设备名称均使用拓扑上名称改名&#xff0c;并且区分大小写。 3 、整张拓扑均使用私网地址进行配置。 4 、整张网络中&#xff0c;运行 OSPF 协议…

汽车销售企业消费税,增值税高怎么合理解决?

《税筹顾问》专注于园区招商、企业税务筹划&#xff0c;合理合规助力企业节税&#xff01; 汽车行业一直处于炙手可热的阶段&#xff0c;这是因为个人或者家庭用车的需求在不断攀升&#xff0c;同时随着新能源的技术进一步应用到汽车领域&#xff0c;一度实现了汽车销量的翻倍。…

JavaSE类和对象(2)(重点:封装、包、static静态变量和方法)

目录 一、封装 1.封装&#xff1a;从语法来看&#xff0c;就是被private修饰的成员变量或者成员方法。只能在当前类当中使用。 2.快捷键&#xff0c;自动生成set或者get方法 3.限定访问修饰符&#xff08;private、 protected、public&#xff09; public&#xff1a;可以理…

python数学建模_2:灰色预测模型(GM(1,1))使用文档

灰色预测模型(GM(1,1))使用文档简介使用时机处理数据类型函数说明使用示例注意事项具体项目 灰色预测模型(GM(1,1))使用文档 简介 灰色预测模型(GM(1,1))是灰色系统理论的重要部分&#xff0c;常用于对包含不确定性的系统进行建模和预测。 使用时机 当数据量较小&#xff0…

树莓派通过天线+gps获取经纬度并调用高德地图api在地图上标点

完整项目为《基于机器视觉的行人和路面缺陷检测及其边缘设备部署》 完整功能视频演示地址&#xff1a;本科最后的课设&#xff1a;“车载系统的辅助系统——基于机器视觉的行人和路面缺陷检测”完结撒花*罒▽罒*_哔哩哔哩_bilibili 该博客介绍的功能为&#xff1a; 1&#xff1…

VS下开发Qt应用环境搭建

VS下开发Qt应用环境搭建 版本说明环境搭建步骤QT新增组件重新安装QTVS中的配置 版本说明 vs2019 QT5.14 我之前是按照QT基础组件的安装&#xff0c;但是这个安装只是最基础的组件&#xff0c;如果想要在VS中使用QT&#xff0c;还得安装其他组件&#xff0c;下面的安装流程、 …