<C++> IO流

news2024/11/25 13:23:57

C语言的输入与输出

在C语言当中,我们使用最频繁的输入输出方式就是scanf与printf:

  • scanf: 从标准输入设备(键盘)读取数据,并将读取到的值存放到某一指定变量当中。
  • printf: 将指定的数据输出到标准输出设备(屏幕),使用时需要注意宽度输出和精度输出的控制。

C语言借助了相应的缓冲区来进行输入与输出。如下图所示:

在这里插入图片描述

对输入输出缓冲区的理解:

  1. 可以屏蔽掉低级I/O的实现。 低级I/O的实现依赖操作系统本身内核的实现,所以如果能够屏蔽这部分的差异,可以很容易写出可移植的程序。
  2. 可以使用这部分的内容实现“行”读取的行为。 对于计算机而言是没有“行”这个概念的,有了这部分,就可以定义“行”的概念,然后解析缓冲区的内容,返回一个“行”。

流是什么

“流”即是流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续且有方向性的数据的抽象描述。

C++流是指信息从外部输入设备(如键盘)向计算机内部(如内存)输入和从计算机内部向外部输出设备(如显示器)输出的过程。这种输入输出的过程被形象的比喻为“流”。

它的特性是:有序连续、具有方向性

为了实现这种流动,C++定义了I/O标准类库,这些每个类都称为流/流类,用以完成某方面的功能

C++IO流

C++系统实现了一个庞大的类库,其中ios为基类,其他类都是直接或间接派生自ios类

在这里插入图片描述

C++标准IO流

C++标准库提供了4个全局流对象(cin、cout、cerr、clog):

  • 使用cout进行标准输出,即数据从内存流向控制台(显示器)。
  • 使用cin进行标准输入,即数据通过键盘输入到程序中。
  • 使用cerr进行标准错误的输出。
  • 使用clog进行日志的输出。

从上图可以看出,cout、cerr、clog都是由ostream类实例化出的三个不同的对象,因此这三个对象基本没什么区别,只是应用场景不同。

在使用时候必须要包含#include文件并引入std标准命名空间。

注意

1、cin为缓冲流。 键盘输入的数据保存在缓冲区中,当要提取时,是从缓冲区中拿。 如果一次输入过多,会留在那儿慢慢用,如果输入错了,必须在回车之前修改,如果回车键按下就无法挽回了。只有把输入缓冲区中的数据取完后,才要求输入新的数据。

2、输入的数据类型必须与要提取的数据类型一致,否则出错。出错只是在流的状态字state中对应位置位(置1),程序继续。

3、空格和回车都可以作为数据之间的分格符,所以多个数据可以在一行输入,也可以分行输 入。但如果是字符型和字符串,则空格(ASCII码为32)无法用cin输入,字符串中也不能有空格。回车符也无法读入。

#include <iostream>
#include <string>
using namespace std;
int main(){
	string s;
	cin >> s;          //输入:"hello world"
	cout << s << endl; //输出:"hello"
	return 0;
}

对于含有空格的字符串,我们需要使用getline函数进行读取,因为getline函数只有遇到’\n’才会停止读取。

#include <iostream>
#include <string>
using namespace std;
int main(){
	string s;
	getline(cin, s);   //输入:"hello world"
	cout << s << endl; //输出:"hello world"
	return 0;
}

4、cin和cout可以直接输入和输出内置类型数据,原因:标准库已经将所有内置类型的输入和输出全部重载了

5、对于自定义类型,如果要支持cin和cout的标准输入输出,需要对<<和>>进行重载。

6、循环输入和输出

// 单个元素循环输入
while (cin >> a) {
    // ...
}
// 多个元素循环输入
while (c >> a >> b >> c) {
    // ...
}
// 整行接收
while (cin >> str) {
    // ...
}

7、istream类型对象转换为逻辑条件判断值

istream& operator>> (int& val);
explicit operator bool() const;

实际上我们看到使用while(cin>>i)去流中提取对象数据时,调用的operator>>,返回值是 istream类型的对象,那么这里可以做逻辑条件值,源自于istream的对象又调用了operator bool,operator bool调用时如果接收流失败,或者有结束标志,则返回false。

C++文件IO流

C++标准库中的<fstream>头文件提供了用于文件输入和输出的类和接口。这些类通常与文件流对象一起使用,允许你打开、读取、写入和关闭文件。以下是一些常用的<fstream>接口和类的介绍:

  1. ifstream(输入文件流)ifstream类用于从文件中读取数据。
  • 常用成员函数:
    • open(const char* filename, ios_base::openmode mode = ios_base::in):打开指定文件以供读取。mode参数指定了文件的打开模式,例如 ios::in 表示只读模式。
    • close():关闭打开的文件。
    • is_open():检查文件是否已经成功打开。
    • get():从文件中读取一个字符。
    • getline(char* buffer, streamsize count, char delim):从文件中读取一行文本,直到遇到指定的分隔符或达到指定的字符数。
    • operator>>:用于从文件中读取各种数据类型,例如 intdouble等。
  1. ofstream(输出文件流)
  • ofstream类用于向文件中写入数据。
  • 常用成员函数:
    • open(const char* filename, ios_base::openmode mode = ios_base::out):打开指定文件以供写入。mode参数指定了文件的打开模式,例如 ios::out 表示只写模式。
    • close():关闭打开的文件。
    • is_open():检查文件是否已经成功打开。
    • put(char c):将字符写入文件。
    • write(const char* buffer, streamsize count):将指定数量的字节写入文件。
    • operator<<:用于将各种数据类型写入文件,例如 intdouble等。
  1. fstream(文件流)
  • fstream类可用于既可以读取又可以写入文件的情况。
  • 它继承了ifstreamofstream的所有成员函数,因此可以用于打开、读取和写入文件。

以下是一些常见的文件打开模式:

  1. ios::in
    • 打开文件以供读取。可以使用ifstream类或fstream类来读取文件内容。
  2. ios::out
    • 打开文件以供写入。可以使用ofstream类或fstream类来写入文件内容。如果文件不存在,则会创建一个新文件;如果文件已存在,则会截断(清空)文件内容。
  3. ios::app
    • 打开文件以供追加写入。新数据将被添加到文件的末尾,而不会截断文件内容。如果文件不存在,则会创建一个新文件。
  4. ios::binary
    • 以二进制模式打开文件。这个模式用于处理二进制文件,如图像、音频或其他非文本文件。在二进制模式下,不会执行文本的自动换行和转换。
  5. ios::ate
    • 打开文件后,将文件指针移到文件的末尾。这可以让你立即开始读取或写入文件的末尾部分。
  6. ios::trunc
    • 如果文件已存在,在打开文件时会截断(清空)文件内容。通常与ios::out一起使用,以确保文件被清空后写入新数据。

这些打开模式可以组合使用,通过按位或运算符|来实现。例如,要以二进制追加写入的方式打开文件,可以使用ios::binary | ios::app

代码示例

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

int main() {
    // 打开一个文本文件以供读取
    ifstream inputFile("input.txt", ios::in);

    // 打开一个二进制文件以供写入,如果不存在则创建
    ofstream binaryFile("output.bin", ios::out | ios::binary);

    // 打开一个文本文件以供追加写入
    ofstream appendFile("log.txt", ios::out | ios::app);

    if (inputFile.is_open() && binaryFile.is_open() && appendFile.is_open()) {
        // 文件已成功打开,可以进行读取和写入操作
        // ...

        // 关闭文件
        inputFile.close();
        binaryFile.close();
        appendFile.close();
    } else {
        cout << "无法打开文件" << endl;
    }

    return 0;
}

控制文件指针位置

tellgseekg是C++中用于在文件流对象中控制文件指针位置的函数,通常与ifstreamfstream一起使用,用于读取文件的特定位置或获取当前文件指针的位置。

  1. tellg函数

    tellg函数用于获取当前文件指针的位置(读取位置)。它返回一个类型为streampos的值,表示当前文件指针的位置。streampos通常是一个整数类型,用于表示文件的字节偏移量。

    用法示例

    ifstream inputFile("example.txt", ios::in);
    
    if (inputFile.is_open()) {
        // 获取当前文件指针的位置
        streampos currentPosition = inputFile.tellg();
        cout << "当前文件指针位置:" << currentPosition << endl;
    
        // 读取文件内容
        // ...
    
        // 获取新的文件指针位置
        currentPosition = inputFile.tellg();
        cout << "新的文件指针位置:" << currentPosition << endl;
    }
    
  2. seekg函数

    seekg函数用于设置文件指针的位置,以便在文件中进行定位。它允许你将文件指针移动到文件的特定位置,以便读取或写入数据。seekg接受两个参数,第一个参数是偏移量,第二个参数是基准位置,用于确定偏移量是相对于文件的开头、当前位置还是文件的末尾。

    基准位置可以是以下之一:

    • ios::beg:基于文件的开头。
    • ios::cur:基于当前文件指针位置。
    • ios::end:基于文件的末尾。

    用法示例

    ifstream inputFile("example.txt", ios::in);
    
    if (inputFile.is_open()) {
        // 将文件指针移动到文件的第10个字节(相对于文件开头)
        inputFile.seekg(10, ios::beg);
    
        // 读取从第10个字节开始的内容
        string data;
        inputFile >> data;
        cout << "从第10个字节开始的内容:" << data << endl;
    
        // 将文件指针移动到文件末尾
        inputFile.seekg(0, ios::end);
    
        // 获取文件末尾的位置
        streampos endPosition = inputFile.tellg();
        cout << "文件末尾位置:" << endPosition << endl;
    }
    

文件操作示例

以二进制的形式操作文件

以二进制的形式对文件进行写入操作:

//以二进制的形式对文件进行写入
void WriteBinary(){
	ofstream ofile; //定义文件流对象
	ofile.open("test.bin", ofstream::out | ofstream::binary); //以二进制写入的方式打开test.bin文件
	char data[] = "Hello World";
	ofile.write(data, strlen(data)); //将data字符串写入文件
	ofile.put('!'); //将字符'!'写入文件
	ofile.close(); //关闭文件
}

以二进制的形式对文件进行读取操作:

//以二进制的形式对文件进行读取
void ReadBinary(){
	ifstream ifile; //定义文件流对象
	ifile.open("test.bin", ofstream::in | ofstream::binary); //以二进制读取的方式打开test.bin文件
	ifile.seekg(0, ifile.end); //跳转到文件末尾
	int length = ifile.tellg(); //获取当前字符在文件当中的位置,即文件的字符总数
	ifile.seekg(0, ifile.beg); //重新回到文件开头
	char data[100];
	ifile.read(data, length); //将文件当中的数据全部读取到字符串data当中
	ifile.close(); //关闭文件
}
以文本的形式操作文件

以文本的形式对文件进行写入操作:

//以文本的形式对文件进行写入
void WriteTxt(){
	ofstream ofile; //定义文件流对象
	ofile.open("test.txt"); //以写入的方式打开test.txt文件
	char data[] = "Hello World";
	ofile.write(data, strlen(data)); //将data字符串写入文件
	ofile.put('!'); //将字符'!'写入文件
	ofile.close(); //关闭文件
}

以文本的形式对文件进行读取操作:

//以文本的形式对文件进行读取
void ReadTxt(){
	ifstream ifile; //定义文件流对象
	ifile.open("test.txt"); //以读取的方式打开test.txt文件
	ifile.seekg(0, ifile.end); //跳转到文件末尾
	int length = ifile.tellg(); //获取当前字符在文件当中的位置,即文件的字符总数
	ifile.seekg(0, ifile.beg); //重新回到文件开头
	char data[100];
	ifile.read(data, length); //将文件当中的数据全部读取到字符串data当中
	cout << length << endl;
	cout << data << endl;
	ifile.close(); //关闭文件
}

注意: 使用ofstream类对象的open函数时,若不指定打开方式,则默认以写的方式打开文件;使用ifstream类对象的open函数时,若不指定打开方式,则默认以读的方式打开文件;使用fstream类对象的open函数时,若不指定打开方式,则默认以写+读的方式打开文件。

使用>>和<<对文件进行操作

使用>>和<<运算符对文件进行读写操作,会变得很简单,也很形象。
对文件进行写入操作:

//对文件进行写入操作
void WriteFile(){
	ofstream ofs("data.txt"); //定义文件流对象,并打开文件
	ofs << "Hello World"; //字符串“流入”文件
	ofs.close(); //关闭文件
}

对文件进行读取操作:

//对文件进行读取操作
void ReadFile(){
	ifstream ifs("data.txt"); //定义文件流对象,并打开文件
	char data[100];
	ifs >> data; //文件数据“流入”字符串data
	ifs.close(); //关闭文件
}

stringstream流

在C语言中,我们若是想要将一个整型变量的数据转化为字符串格式,有以下两种方法:
1、使用itoa函数进行转化。

int a = 10;
char arr[10];
itoa(a, arr, 10); //将整型的a转化为十进制字符数字存储在字符串arr当中

2、使用sprintf函数进行转化。

int a = 10;
char arr[10];
sprintf(arr, "%d", a); //将整型的a转化为字符串格式存储在字符串arr当中

虽然itoa函数和sprintf函数都能完成转化,但是在两个函数在转化时,都需要先给出保存结果的空间,而空间的大小是不太好界定的,除此之外,转化格式不匹配时,可能还会得到错误的结果甚至程序崩溃。

在C++中,我们可以使用stringstream类对象来避开此问题。在程序当中如果想要使用stringstream,必须要包含头文件sstream。在该头文件下,有三个类:

对应操作场景
ostringstream输出操作
istringstream输入操作
stringstream输入操作+输出操作

以下是stringstream的一些常用接口:

1、stringstream 的构造函数

stringstream():创建一个空的字符串流。

stringstream(std::string str):使用给定的字符串 str 初始化字符串流。

2、插入数据到字符串流

<< 操作符:插入数据到字符串流中。你可以使用它来插入各种数据类型,如整数、浮点数、字符串等。

std::stringstream ss;
int num = 42;
ss << "The answer is: " << num;

3、从字符串流中提取数据

>> 操作符:从字符串流中提取数据。你可以使用它来提取数据到不同的数据类型。

int extractedNum;
ss >> extractedNum;

4、获取字符串流中的字符串

str() 函数:获取字符串流中的全部内容作为一个字符串。

std::string content = ss.str();

5、清空字符串流

clear() 函数:清空字符串流的状态和内容。

ss.clear();

6、指定基数(进制)

std::hexstd::octstd::dec:可以使用这些流控制器来指定插入或提取整数时的进制,如十六进制、八进制或十进制。

int num = 255;
ss << std::hex << num; // 将 num 以十六进制插入

7、获取当前位置

tellg() 函数:获取当前的读取位置。

std::streampos pos = ss.tellg();

8、设置读取位置

seekg(std::streampos pos):将读取位置设置为指定的位置。

ss.seekg(0); // 设置读取位置为开头

stringstream流操作示例

1、将数值类型数据格式化为字符串。

#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main(){
	int a = 10;
	string sa;
	stringstream s;
	s << a; //将int类型的a放入输入流
	s >> sa; //从s中抽取前面插入的int类型的值,赋值给string类型(方式一)
	cout << sa << endl;
	s.str(""); //将stringstream底层管理的string对象设置为""。
	s.clear(); //将上次转换状态清空掉
	//进行下一次转换
	double b = 3.14;
	s << b;
	sa = s.str(); //获取stringstream中管理的string类型(方式二)
	cout << sa << endl;
	return 0;
}

2、字符串拼接。

#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main(){
	string rets;
	stringstream s;
	s << "Hello" << "World"; //将多个字符串放入stringstream中
	s >> rets; //方式一获取
	cout << rets << endl;
	s.str(""); //将stringstream底层管理的string对象设置为空字符串
	s.clear(); //将上次转换状态清空掉
	s << "Thanks" << " " << "for" << " " << "reading"; //将多个字符串放入stringstream中
	rets = s.str(); //方式二获取
	cout << rets << endl;
	return 0;
}

注意事项:

  1. stringstream实际是在底层维护了一个string类型的对象用来保存结果。
  2. stringstream在转换结尾时(即最后一个转换后),会将其内部状态设置为badbit,因此在下一次转换前必须调用clear将状态重置为goodbit才可以转换,但clear不会将stringstream底层的string对象清空。
  3. 可以使用s.str(“”)的方式将stringstream底层的string对象设置为空字符串,否则多次转换时,会将结果全部累积在底层string对象中。
  4. 获取stringstream转换后的结果有两个方法,一是使用>>运算符之间从流当中提取,二是使用s.str( )获取stringstream底层的string对象。
  5. stringstream使用string类对象代替字符数组,可以避免缓冲区溢出的危险,而且其会对参数类型进行推演,不需要格式化控制,也不会存在格式化失败的风险,因此使用更方便,更安全。

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

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

相关文章

idea自动封装方法

例如 package com.utils;import java.lang.reflect.Field; import java.sql.*; import java.util.ArrayList; import java.util.List; import java.util.ResourceBundle;/*** author hrui* date 2023/10/13 13:49*/ public class DBUtils {private static ResourceBundle bund…

【网络编程】Linux网络编程基础与实战第二弹——Socket编程

Socket编程套接字概念套接字通讯原理 网络编程接口网络字节序sockaddr数据结构socket函数bind函数listen函数accept函数connect函数 ) Socket编程 套接字概念 Socket本身有“插座”的意思&#xff0c;在Linux环境下&#xff0c;用于表示进程间网络通信的特殊文件类型。本质为…

多机器人三角形编队的实现

文章目录 前言一、机器人编队前的准备二、配置仿真环境2.编写机器人编队.cpp文件 三、三角形编队测试 前言 前阵子一直想要实现多机器人编队&#xff0c;找到了很多开源的编队代码&#xff0c;经过好几天的思索&#xff0c;终于实现了在gazebo环境中的TB3三角形机器人编队。 一…

prostate数据集下载

1. prostatex 下载地址&#xff1a;https://wiki.cancerimagingarchive.net/pages/viewpage.action?pageId23691656 比赛&#xff1a;https://prostatex.grand-challenge.org/ 这个下载的是一个tcia文件&#xff0c;参考这篇文章打开该文件 2. promise12 地址&#xff1a;…

阿里健康大药房七周年峰会:两大变革叠加 风往何处吹

10月11日&#xff0c;2023数字医药产业论坛暨阿里健康大药房7周年活动在杭州举行。 作为一年一度的医药圈峰会&#xff0c;大会现场集聚了数百家全球知名医药健康企业、经济学者、学术智库等各界领袖、专家&#xff0c;针对健康行业新趋势、新技术、新场景分享产业见解和经验&…

Redis HyperLogLog的使用

Redis HyperLogLog知识总结 一、简介二、使用 一、简介 Redis HyperLogLog是一种数据结构&#xff0c;用于高效地计算基数&#xff08;集合中唯一元素的数量&#xff09;。它的主要作用是用于在内存中高效地存储和计算大量数据的基数&#xff0c;而无需完全存储所有的数据。Hy…

XMind思维导图软件forMac/win:让你的大脑更高效地运转

XMind 是一款非常实用的思维导图软件&#xff0c;它可以帮助用户更好地组织思维、提高工作效率。 您是否曾经遇到过这样的问题&#xff1a;在工作中需要处理大量的信息、任务和项目&#xff0c;但却又不知道该如何下手&#xff1f;这种情况很常见&#xff0c;但是&#xff0c;…

简单好用的解压缩软件:keka 中文 for mac

Keka是一款功能全面、易于使用的文件压缩和解压缩软件&#xff0c;为Mac用户提供了便捷的文件管理工具。它支持多种压缩格式&#xff0c;具有快速解压和强大的压缩功能&#xff0c;让您能够轻松地处理各种文件压缩需求。 隐私非常重要 安全共享只需设置密码并创建高度加密的文…

虚幻引擎:如何实现骨骼重定向

前言&#xff1a; 为什么需要做骨骼重定向&#xff0c;因为当前角色素材没有对应的动画&#xff0c;这时候我们可以找个身高体型差不多的带有动画素材的另一个角色来做重定向&#xff0c;这样我们就可以得到我们需要的动画素材了。 1.首先创建两个骨骼的IK绑定 2.然后给两个骨骼…

Java Kids-百倍提速【Mac IOS】

引言&#xff1a;当今社会&#xff0c;创新和提升效率已经成为了大家普遍的追求。无论是个人生活还是企业经营&#xff0c;我们都希望能够以更高的效率完成任务&#xff0c;节省时间和资源。因此&#xff0c;提速成为了一种时代的要求&#xff0c;而"Java Kids 百倍提速&q…

Hadoop3教程(四):HDFS的读写流程及节点距离计算

文章目录 &#xff08;55&#xff09;HDFS 写数据流程&#xff08;56&#xff09; 节点距离计算&#xff08;57&#xff09;机架感知&#xff08;副本存储节点选择&#xff09;&#xff08;58&#xff09;HDFS 读数据流程参考文献 &#xff08;55&#xff09;HDFS 写数据流程 …

SpringBoot+原生HTML+MySQL开发的电子病历系统源码

电子病历系统源码 电子病历编辑器源码 云端SaaS服务 电子病历系统&#xff0c;采用 “所见即所得、一体化方式”&#xff0c;协助医生和护士准确、标准、快捷实现病历书写、修改、审阅、打印、体温单浏览、医嘱管理等&#xff0c;是提供病历快速简洁化完成的一系列综合型医生病…

MyCat分片水平拆分

场景 在业务系统中 , 有一张表 ( 日志表 ), 业务系统每天都会产生大量的日志数据 , 单台服务器的数据存 储及处理能力是有限的 , 可以对数据库表进行拆分。 准备 准备三台服务器&#xff0c;具体的结构如下&#xff1a; 并且&#xff0c;在三台数据库服务器中分表创建一…

启山智软/JAVA商城

一、项目介绍 启山网上商城采用目前流行的JAVA spring cloud架构开发&#xff0c;前端使用的是目前最流行的TypeScript、VUE3、uniapp、element-plus、pinia技术&#xff0c;后端采用的是JAVA、SpringBoot、spring cloud技术&#xff0c;数据库采用的是MSQ&#xff0c;采用前后…

C语言----程序环境

目录 前言: 1.翻译环境 1.1预编译(预处理) 1.2编译 1.3汇编 1.4链接 2.运行环境 前言: 我们在用vs或一些其他的编译器写代码的时候,当我们运行代码的时候,很自然而然的就出结果了,但是它究竟是如何是如何实现的呢?因为这部分的内容是涉及到"编译原理"的,所以本章…

读书笔记——C++高性能编程(六)

第六章.并发和性能 阿姆达尔定律 介绍了阿姆达尔定律&#xff08;Amdahls Law&#xff09;&#xff0c;这个定律的意义是“系统中对某一部件采用更快执行方式所能获得的系统性能改进程度&#xff0c;取决于这种执行方式被使用的频率”。具体的公式如下&#xff1a; 其中s0是程…

基于CodeFormer使用C++实现图片模糊变清晰,去除马赛克等效果

前言 CodeFormer是一种基于AI技术深度学习的人脸复原模型&#xff0c;由南洋理工大学和商汤科技联合研究中心联合开发。该模型通过结合了VQGAN和Transformer等技术&#xff0c;可以通过提供模糊或马赛克图像来生成清晰的原始图像。可以实现老照片修复、照片马赛克修复、黑白照…

深入浅出ThreadPoolExecutor(一)

文章目录 线程池简诉ThreadPoolExecutor详解ThreadPoolExecutor参数详解创建线程池的工具类Executors 线程池简诉 针对各种池子,比如 连接池:用于管理和重复使用数据库连接&#xff0c;避免频繁创建和销毁数据库连接带来的性能开销。对象池&#xff1a;用于管理和重复使用对象…

中国雪深长时间序列数据集(1979-2020)

简介 中国雪深长时间序列数据集&#xff08;1979-2020&#xff09;提供1979年1月1日到2020年12月31日逐日的中国范围的积雪厚度分布数据&#xff0c;其空间分辨率为25km&#xff0c;是“中国雪深长时间序列数据集&#xff08;1978-2012&#xff09;”的升级版本。前言 – 人工…

5.Python-使用XMLHttpRequest对象来发送Ajax请求

题记 使用XMLHttpRequest对象来发送Ajax请求&#xff0c;以下是一个简单的实例和操作过程。 安装flask模块 pip install flask 安装mysql.connector模块 pip install mysql-connector-python 编写app.py文件 app.py文件如下&#xff1a; from flask import Flask, reque…