【C++】<知识点> 标准和文件的输入输出

目录

        一、输入输出操作

                1. 相关的类

                2. 标准流对象

                3. istream类的成员函数

二、流操纵算子

        1. 整数流的基数

        2. 浮点数精度的流操纵算子

        3. 域宽的流操纵算子

        4. 其他的流操纵算子

        5. 用户自定义流操纵算子

三、文件读写

        1. 文本文件的读写

        2. 二进制文件的读写

        3. 文件读写指针

        4. 文本文件和二进制文件区别


一、输入输出操作

1. 相关的类

  • ios基类派生出istream和ostream。
  • istream派生出ifstream,ostream派生出ofstream。
  • iostream继承自istream和ostream。
  • fstream继承自iostream。

注意:cin就是istream类的对象,cout就是istream类的对象。

2. 标准流对象

(1) 输入流对象:cin与标准输入设备相连(从键盘获取数据)。也可以被重定向为从文件中读取数据。

(2) 输出流对象:

  • cout与标准输出设备相连(在屏幕上打印数据)。也可以被重定向为向文件写入数据(freopen函数)。
  • cerr与标准错误输出设备相连。
  • clog与标准错误输出设备相连。
  • cerr和clog的区别在于cerr不使用缓冲区,直接向显示器输出信息;而clog采用缓冲区,只有缓冲区满或者刷新时才会输出到屏幕上。

(3) 代码示例:

【1】输出重定向

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

int main()
{
	double x, y;
	cin >> x >> y;
	//freopen函数:输出重定向到文件
	//原型:FILE *freopen(const char *path, const char *mode, FILE * stream);
	//path是目标文件
	//mode为文件打开模式"r"或"w"
	//stream为标准流文件,例如stdin标准输入流, stdout标准输出流, stderr标准错误流
	freopen("cout.txt", "w", stdout);
	if (y == 0) {
		cerr << "error!" << endl;
	}
	else {
		cout << x / y;//输出到文件cout.txt中
	}
	return 0;
}

  

显然,屏幕上并没有输出计算结果0.5,该结果输出到cout.txt文件中。

【2】输入重定向

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

int main()
{
	int n1 = 0, n2 = 0;
	//freopen函数:输入重定向
	freopen("input.txt", "r", stdin);
	cin >> n1 >> n2;//由于重定向了,不会在终端等用户输入
	cout << "结果:" << n1 << ", " << n2 << endl;
	return 0;
}

【3】判断输入流结束

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

int main()
{
	int x;
	freopen("test.txt", "r", stdin);
	while (cin >> x) {
		cout << "读入:" << x << endl;
	}
	return 0;
}

注意:①这里将cin重定向为从文件读取数据,那么读到文件末尾即结束。若未重定向,从键盘中输入则需要单独一行输入Ctrl+Z代表输入流结束。cin >> x返回值为istream&,而istream会有对象的重载,将其转换成bool类型,因此可以作为循环条件。

3. istream类的成员函数

(1) getline函数:

  • 原型:①istream& getline(char* buf, int bufSize); ②istream& getline(char* buf, int bufSize, char delim);
  • 对于第一个原型:从输入流中读取bufSize-1个字符到缓冲区buf,或读到'\n'为止(哪个先到算哪个)。
  • 对于第二个原型:从输入流中读取bufSize-1个字符到缓冲区buf,或读到delim字符为止(哪个先到算哪个)。
  •  注意:
    • 两个函数都会自动在buf中读入数据的结尾添加'\0'。
    • ‘\0’和delim都不会被读入buf,但会被输入流中取走。
    • 如果输入流中'\n'或delim之前的字符个数达到或超过了bufSize个,就导致读入错误,即虽然本次读入已经完成,但是之后的读入就都失败了。
    • 可以用if (!cin.getline(...))判断输入是否结束。

(2) bool eof(); 用于判断输入流是否结束。

(3) int peek(); 返回下一个字符,但不从流中去除。

(4) istream& putback(char c); 将字符ch放回输入流的头部。

(5) istream& ignore(int nCount = 1, int delim = EOF); 从流中删掉最多nCount个字符,遇到EOF结束。

(6) getline函数代码示例:

#include <iostream>
using namespace std;

int main()
{
	int x;
	char buf[90];
	cin >> x;
	cin.getline(buf, 90, '\n');
	cout << buf << endl;
	return 0;
}


二、流操纵算子

1. 整数流的基数

(1) 说明:在cout时,可以指定输出的整数的进制:dec(十进制)、oct(八进制)、hex(十六进制)。

(2) 注意:①使用流操纵算子,需要添加头文件iomanip。②一旦设置,就会持续有效直到新的操纵算子出现。

(3) 代码示例:

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

int main()
{
	int n = 10;
	cout << dec << n << endl;//十进制显示n
	cout << oct << n << endl;//八进制显示n
	cout << hex << n << endl;//十六进制显示n
	//一旦设置dec、oct或者hex,就会持续有效直到写新操纵算子。
	cout << n << endl;
	return 0;
}

2. 浮点数精度的流操纵算子

(1) precision:是ostream的成员函数,调用方式为:cout.precision(5); 用于指定浮点数的有效位数(非定点方式)系统默认是非定点方式。

(2) setprecision:流操纵算子,调用方式为:cout << setprecision(5); 用于指定浮点数的有效位数(非定点方式)和指定浮点数的小数后的有效位数(非定点方式)定点方式:小数点必须出现在个位数后面。

(3) 注意:

  • 当位数超过精度时会四舍五入。
  • setprecision方式会持续有效,直到设置新的精确度。
  • setprecision操纵算子也需要添加头文件iomanip。
  • 在非定点方式下,setprecision可能会使用科学计数法来表示。

(4) setiosflags(ios::fixed):以小数点位置固定的方式来输出(可以简单用cout << fixed;)。另外,cout << scientific表示采用科学计数法。

(5) resetiosflags(ios::fixed):取消以小数点位置固定的方式来输出。

(6) 代码示例:

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

int main()
{
	float f = 1234567.89;
	int n = 123456;
	//默认是非定点方式
	cout << "*****非定点******" << endl;
	cout << setprecision(6);//设置浮点数有效位数为6
	cout << f << endl;//由于非定点方式且规定只能有6位,因此用科学计数法显示
	cout << n << endl;//浮点数的操纵算子不影响整数
	//修改为定点方式
	cout << "*****定点********" << endl;
	cout << setiosflags(ios::fixed);
	cout << f << endl;//小数点后有6位,不够就补0
	//修改为非定点方式
	cout << "*****非定点******" << endl;
	cout << resetiosflags(ios::fixed);
	cout << f << endl;//由于非定点方式且规定只能有6位,因此用科学计数法显示
	return 0;
}

3. 域宽的流操纵算子

(1) setw:流操纵算子,用于设置域宽。调用方式:cout << setw(5)或cin >> setw(5)。

(2) width:成员函数,用于设置域宽。调用方式:cout.width(5)或cin.width(5)。

(3) 注意:域宽的流操纵算子是一次性的,每次输入输出前都需要指定宽度。

(4) 代码示例:

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

int main()
{
	int m = 4;
	char string[10];
	cin >> setw(5);//设置输入宽度
	while (cin >> string) {
		cout << setw(m++);//设置输出宽度
		cout << string << endl;
		cin >> setw(5);
	}
	return 0;
}

(5) 结果解释:

  • 第一行是我们输入的数据1234567890.
  • 第二行输出1234。首先,设置输入宽度为5(实际上只接收4个字符,最后自动加'\0'),那么string里就是1234‘\0’。其次,设置输出宽度为4(设置完后m自增为5),那么输出4个字符即1234.
  • 第三行输出" 5678"。首先,设置输入宽度为5(实际上只接收4个字符,最后自动加'\0'),那么string里就是5678‘\0’。其次,设置输出宽度为5(设置完后m自增为6),那么输出5个字符即空格+5678.
  • 第四行输出"    90"。首先,设置输入宽度为5(实际上只接收4个字符,最后自动加'\0'),那么string里就是90‘\0’。其次,设置输出宽度为6(设置完后m自增为7),那么输出6个字符即4个空格+90.

4. 其他的流操纵算子

(1) cout << showpos; 非负数显示正号。

(2) cout << noshowpos; 非负数不显示正号。

(3) cout << setfill(*); 宽度不足用*填补。

(4) cout << right; 右对齐,宽度不足则左边填充。

(5) cout << left; 左对齐,宽度不足则右边填充。

(6) cout << internal; 在负号和数字之间填充。

(7) 综合案例:

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

int main()
{
	int i = 141;
	double x = 1234567.89, y = 12.34567;
	//1) 8d 141 215
	cout << "1) " << hex << i << " " << dec << i << " " << oct << i << endl;

	//2) 1.2346e+006 12.346
	cout << "2) " << setprecision(5) << x << " " << y << endl;

	//3) 1234567.89000 12.34567
	cout << "3) " << fixed << setprecision(5) << x << " " << y << endl;

	//4) 1.23457e+006 1.23457e+001
	cout << "4) " << scientific << setprecision(5) << x << " " << y << endl;
		 
	//5) ***+12.10000
	cout << "5) " << showpos << right << fixed << setprecision(5) << setfill('*') << setw(12) << 12.1 << endl;

	//6) 12.10000****
	cout << "6) " << noshowpos << left << fixed << setprecision(5) << setfill('*') << setw(12) << 12.1 << endl;
	
	//7) ****12.10000
	cout << "7) " << noshowpos << right << fixed << setprecision(5) << setfill('*') << setw(12) << 12.1 << endl;
	
	//8) -***12.10000
	cout << "8) " << showpos << right << fixed << setprecision(5) << internal << setfill('*') << setw(12) << -12.1 << endl;
	
	//9) 12.10000
	cout << "9) " << noshowpos << fixed << setprecision(5) << 12.1 << endl;
	return 0;
}

5. 用户自定义流操纵算子

(1) 格式:

ostream& 函数名(ostream& cout) {
	//执行的操作
    return cout;
}

(2) 代码示例:定义tab流操纵算子。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

ostream& tab(ostream& output) {
	return output << '\t';
}

int main()
{
	cout << "a" << tab << "b" << endl;
	return 0;
}

(3) 底层解释:由于iostream里对<<进行了重载(使用成员函数方式),即ostream& operator << (ostream& (*p) (ostream&)); 其中ostream& (*p) (ostream&)是函数指针,能够根据函数名找到对应的函数并执行函数体,同时内部还返回了*this就是对象本身。因此,在上述示例中,tab就是一个函数名,会执行tab的函数体。


三、文件读写

1. 文本文件的读写

(1) 创建读文件对象:ifstream srcFile("in.txt", ios::in);

(2) 创建写文件对象:ofstream destFile("out.txt", ios::out);

(3) 从文件中读取字符:srcFile >> x;

(4) 将字符写入文件:destFile << x;

(5) 注意:

  • 写文件对象中ios::out选项:删除原有内容,写入新内容。
  • 写文件对象中ios::app选项:在原内容后面追加新内容。
  • 读写文件对象中ios::binary选项:以二进制方式写入/读取。
  • ifstream和ofstream换成fstream也行。

(6) 代码示例:将in.txt中的内容1 234 9 45 6 879排序,并存到out.txt中。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
	//1.打开文件in.txt
	ifstream srcFile("./in.txt", ios::in);
	if (!srcFile) {
		cout << "srcFile文件打开失败!" << endl;
		return -1;
	}
	//2.读取文本字符并加入vector中
	int readInt;
	vector<int> v;
	while (srcFile >> readInt) {
		v.push_back(readInt);
	}
	//3.对vector中元素排序
	sort(v.begin(), v.end());
	//4.将排序结果写入out.txt
	ofstream outFile("./out.txt", ios::out);
	if (!outFile) {
		cout << "outFile文件打开失败!" << endl;
		return -1;
	}
	for (int i = 0; i < v.size(); i++) {
		outFile << v[i] << " ";
	}
	//5.关闭文件
	srcFile.close();
	outFile.close();
	return 0;
}

         

2. 二进制文件的读写

(1) 创建读写对象:方式与文本文件相同,但是选项要或(|)上ios::binary选项!

(2) 读文件:使用ifstream和fstream中的成员函数read函数。

  • 函数原型:istream& read(char* s, long n);
  • 功能:将文件读指针指向的地方的n个字节内容,读取到内存地址s,然后读指针向后移动n字节。

(3) 写文件:使用ofstream和fstream中的成员函数write函数。

  • 函数原型:istream& write(const char* s, long n);
  • 功能:将内存地址s处的n个字节内容,写入到写指针指向的位置,然后写指针向后移动n字节。

(4) 代码示例:将整数120写入二进制文件,再从该二进制文件中读取整数。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
	//写入ret于二进制文件out.dat中
	int ret = 120;
	ofstream outFile("./out.dat", ios::out | ios::binary);
	outFile.write((const char*)(&ret), sizeof(int));
	outFile.close();
	//从out.dat中读取一个整数
	int readInt;
	ifstream inFile("./out.dat", ios::in | ios::binary);
	inFile.read((char*)(&readInt), sizeof(int));
	inFile.close();
	//显示读取的整数
	cout << readInt << endl;
	return 0;
}

3. 文件读写指针

(1) 介绍:

  • 对于输入文件,有一个读指针。
  • 对于输出文件,有一个写指针。
  • 对于输入输出文件,有一个读写指针。
  • 读/写指针标识文件操作的当前位置。

(2) 读指针相关操作:

  • tellg():获取读指针的位置。调用方式:"输出对象.tellg()"。
  • seekg(int i):移动读指针至第i个字节处。调用方式:"输出对象.seekg(i)"。
  • seekg(int i, ios::beg):移动至距文件开始的第i个位置。
  • seekg(int i, ios::cur):移动至当前位置后的第i位置。
  • seekg(int i, ios::end):移动至距文件末尾的第i个位置。(常用于统计文本的字符数)

(3) 写指针相关操作:

  • tellp():获取写指针的位置。调用方式:"输出对象.tellp()"。
  • seekp(int i):移动写指针至第i个字节处。调用方式:"输出对象.seekp(i)"。
  • seekp(int i, ios::beg):移动至距文件开始的第i个位置。
  • seekp(int i, ios::cur):移动至当前位置后的第i位置。
  • seekp(int i, ios::end):移动至距文件末尾的第i个位置。

(4) 代码示例:输出A~Z于test.txt中,并且每两个字符间空两格。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
	ofstream outFile("./test.txt", ios::out);
	/* 输出A~Z于test.txt中,并且每两个字符间空两格*/
	for (char i = 'A'; i <= 'Z'; i++) {
		//获取写文件指针位置
		int location = outFile.tellp();
		//写入字符
		outFile << i;
		//文件指针会自动+1,再使用seekp跳到后两个位置
		outFile.seekp(2, ios::cur);
		//打印测试信息
		cout << location << endl;
	}
	//关闭文件
	outFile.close();
	return 0;
}

4. 文本文件和二进制文件区别

(1) 不同操作系统下换行符号区别:

  • Linux下的换行:'\n'(ASCII:0x0a)
  • Windows下的换行:'\r\n'(ASCII:0x0d0a)
  • MacOS下的换行:'\r'(ASCII:0x0d)
  • 由于ASCII码不同,Linux和MacOS的文本文件在Windows中的记事本打开时不换行。

(2) 文本文件和二进制文件区别:

  • Linux下打开文件,用不用ios::binary没区别。
  • Windows下打开文件,如果不用ios::binary,则会造成①读取文件时,所有的'\r\n'都会被当作'\n'处理,因此会少读了一个字符'\r'。②写入文件时,写入单独的'\n'时,系统会自动加'\r',因此多写了一个字符'\r'。
  • 一般来说,使用二进制文件更加节省空间。例如,保存123456,若保存于文本文件则需要6个字节,而保存于二进制文件用一个int的字节就行了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

编一个自己的万年历

编一个自己的万年历 前阶段突然想查一下某一天是星期几&#xff0c;于是自己编了一个[小程序][https://blog.csdn.net/weixin_41905135/article/details/138972055?spm1001.2014.3001.5501]&#xff0c;但是功能很单一&#xff0c;就是单纯的查是星期几。&#xff08;虽然用网…

Deep Residual Learning for Image Recognition--论文笔记

论文笔记 论文来源&#xff1a; Deep Residual Learning for Image Recognition 代码来源 还没上传 1论文摘要的翻译 深度神经网络更难训练。我们提出了一个残差学习框架&#xff0c;以简化比以前使用的网络深度大得多的网络的训练。我们明确地将层重新表述为参考层输入的…

十五、Python模块 1、(入门一定看!!!)「长期更新Python简单入门到适用」

首先什么是模块&#xff1f; 小伙伴们经常看我写的教程不难发现&#xff0c;前面我们用过几次模块就是sys的那个&#xff0c;其实python不仅标准库中包含了大量的模块&#xff08;也被称之为准模块&#xff09;&#xff0c;还有大量的第三方模块&#xff0c;开发者也可以自己发…

Python学习---基于HTTP的服务端基础框架搭建案例

整体功能&#xff1a; 1 创建框架构建相关的文件夹 2 创建app,模块文件 3 在 app模块文件中创建application函数(用于处理请求) 4 将request_handler()中的处理逻辑交由app模块的application函数完成 5 app模块的 application函数返回响应报文 6 在application 文件夹中创建一个…

零基础HTML教程(34)--HTML综合实例

文章目录 1. 背景2. 开发流程2.1 网站功能设计2.2 建立网站目录结构2.3 开发首页2.2 生平简介页2.3 经典诗词页2.4 苏轼图集页2.5 留言板 3. 小结 1. 背景 通过前面33篇文章的学习&#xff0c;我们对HTML有了一个比较全面的了解。 本篇&#xff0c;我们编写一个网站实例&…

C++ RBTree封装mapset

目录 RBTreeNode的声明 RBTree结构 map结构 set结构 改造红黑树 迭代器类 迭代器成员函数 默认成员函数 Insert set map RBTreeNode的声明 template<class T> struct RBTreeNode {RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>*…

心理咨询系统|心理咨询系统开发|心理咨询软件开发

在快节奏的现代生活中&#xff0c;心理健康问题越来越受到人们的关注。为了有效应对这些问题&#xff0c;心理咨询系统应运而生&#xff0c;它为人们提供了一个安全、便捷的平台&#xff0c;以寻求心理帮助和支持。本文将详细介绍心理咨询系统的功能、优势以及未来发展趋势。 …

vue项目实战 - 如果高效的实现防抖和节流

在Vue项目中&#xff0c;处理高频事件的优化至关重要&#xff0c;直接影响用户体验和应用性能。防抖&#xff08;Debounce&#xff09;和节流&#xff08;Throttle&#xff09;是两种常用且有效的方法&#xff0c;可以控制事件触发频率&#xff0c;减少不必要的资源消耗。如何在…

使用Word表格数据快速创建图表

实例需求&#xff1a;Word的表格如下所示&#xff0c;标题行有合并单元格。 现在需要根据上述表格数据&#xff0c;在Word中创建如下柱图。如果数据在Excel之中&#xff0c;那么创建这个图并不复杂&#xff0c;但是Word中就没用那么简单了&#xff0c;虽然Word中可以插入图表&a…

免费撸gpt-4o和各种大模型实用经验分享

项目 Github: https://github.com/MartialBE/one-api 先贴两张图&#xff1a; 说明 免费撸AI大模型,各位可以对照下面我给出的大模型记录表来填&#xff0c;key需要自己去拿&#xff0c;国内都需要手机号验证&#xff0c;如果你不介意。另外我在自己的博客放出免费API给大家…

自定义RedisTemplate序列化器

大纲 RedisSerializerFastJsonRedisSerializer自定义二进制序列化器总结代码 在《RedisTemplate保存二进制数据的方法》一文中&#xff0c;我们将Java对象通过《使用java.io库序列化Java对象》中介绍的方法转换为二进制数组&#xff0c;然后保存到Redis中。实际可以通过定制Red…

[emailprotected](2)核心概念-JSX

目录 1&#xff0c;什么是 jsx2&#xff0c;空标签3&#xff0c;通过大括号使用 js4&#xff0c;防止注入攻击5&#xff0c;元素的不可变性 官方文档 1&#xff0c;什么是 jsx Facebook 起草的 js 扩展语法。本质上是 js 对象&#xff0c;会被 babel 编译&#xff0c;最终转换…

根据多个坐标经纬度获取到中心点的经纬度,scala语言

文章目录 前言scala 代码 总结 前言 Scala 语言 通过多个经纬度坐标点, 计算出中心点, 这里使用的是 Scala 语言,其他的语言需要自行转换。求出来的并不是原有的点&#xff0c;而是原有点的中心位置的点。 scala 代码 package com.dw.process.midimport java.lang.Double.pa…

【test】Windows11下通过sshfs挂载远程服务器目录

下载安装下面三个软件&#xff1a; sshfs-win&#xff1a;https://github.com/billziss-gh/sshfs-win/releases winfsp&#xff1a;https://github.com/billziss-gh/winfsp/releases SSHFS-Win Manager&#xff1a;https://github.com/evsar3/sshfs-win-manager/releases 安装…

数据结构---优先级队列(堆)

博主主页: 码农派大星. 数据结构专栏:Java数据结构 关注博主带你了解更多数据结构知识 1. 优先级队列 1.1 概念 前面介绍过队列&#xff0c;队列是一种先进先出(FIFO)的数据结构&#xff0c;但有些情况下&#xff0c;操作的数据可能带有优先级&#xff0c;一般出队 列时&am…

python低阶基础100题(上册)

** python低阶基础100题&#xff08;上册&#xff09; ** 1. 请打印出字符串 Hello World print("Hello World")2. 请打印出字符串 爸爸妈妈&#xff0c;你们辛苦啦 print("爸爸妈妈&#xff0c;你们辛苦啦")3. 请打印出字符串 人生苦短&#xff0c;我…

如何使用Studio 3T导出MongoDB数据成excel?

导出MongoDB查询集合数据成excel 1. 新建查询页面&#xff0c;输入指定的查询语句&#xff0c;执行查询获取结果。 这里以查询集合accountbackLogger表中的reqTime字段日期是2024年5月的数据为列。 db.getCollection("accountbackLogger").find({reqTime:{$gte: IS…

UE4/UE5像素流送云推流:多人访问不稳定、画面糊、端口占用多等

UE4/UE5想要实现网页访问&#xff0c;很多工程师会选择guan方的像素流送。但这个技术要求在模型开发初期就接入。对于一些已有UE模型是无法进行流化的。虽然也可以解决新UE模型的网页访问问题&#xff0c;但在实际的应用中&#xff0c;点量云流也收到很多反馈说&#xff0c;使用…

LeetCode题练习与总结:从中序与后序遍历序列构造二叉树--106

一、题目描述 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7], postorder [9,15,7,20,3] 输出…

【百度云千帆AppBuilder】诗词达人:AI引领的诗词文化之旅

文章目录 写在前面&#xff1a;百度云千帆AppBuilder诗词达人&#xff1a;AI引领的诗词文化之旅功能介绍&#xff1a;诗词达人智能体的深度体验1. 诗词接龙学习2. 诗词深度解析3. 互动式问答4. 诗词创作辅助 技术特点详解&#xff1a;"诗词达人"智能体的创新技术零代…