C++的流库

1.流的概念

“流”,即“流动”的意思,是物质从一处向另一处流动的过程。在计算机这边通常是指对一种有序连续且具有方向性的数据的抽象描述。

C++ 中的流一般指两个过程的统一:

  • 信息从外部输入设备(键盘)向计算机内部(内存)输入
  • 计算机内部(内存)向外部输出设备(显示器)输出信息

这种输入输出的过程被形象的比喻为“流”,其具有有序性、连续性、方向性。

而为了实现这种流动,C++ 定义了 I/O 标准类库,每个类都称为流类。

2.C 中的流

C 语言中最常使用流输入/输出方式就是 scanf()/printf()

  • scanf():从标准输入设备(一般指键盘)读取字符数据,并将值通过指针和一定的格式存放在变量中

  • printf():将指定的字符数据通过宽度输出和精度输出控制,来输出到标准输出设备(一般指屏幕)

C 语言借助了相应的输入/输出缓冲区(缓冲区这里涉及到一点系统的知识,您可以去看看我的 Linux 系列博文)来辅助进行输入/输出。

而在实际场景中,fscanf()fprintf() 会更为实用。

输入/输出缓冲区的意义:

  1. 屏蔽低级 I/O 的实现:低级 I/O 的实现依赖于操作系统本身内核的实现(例如:LinuxIO 系统调用),如果能屏蔽这部分在系统调用上的差异,就更容易写出可移植的程序
  2. 实现“行”读取的行为:计算机没有“行”这个概念,有了缓冲区就可以定义出“行”的概念,读取一行就是指解析缓冲区的内容返回一个“行”

但是 C 语言的输入输出在面对对象和泛型上有些吃力,因此 C++ 新构建了流的类。

3.C++ 中的流

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

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

C++ 主要提供了三个流,分别为:

  1. IO 流,和控制台。终端就行流传递
  2. 文件流,和文件进行流传递
  3. 字符流,和字符间进行流传递

3.1.C++ 的 IO 流

补充:由于 IO 流的相关类继承关系比较复杂,这里只是泛泛而谈,有机会我再结合官方文档再出另外一份博文…

C++ 标准库提供了 4 个全局流对象 cincoutcerrclog

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

从类继承的图中可以看出:coutcerrclog 是同属于 ostream 类的三个不同的对象,因此这三个对象的内部原理基本没有区别,只是应用场景和一些细节不同,这里只点出一些细节问题:

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

    而输入的数据类型与要提取的数据类型不一致时出错,出错仅仅在流的状态字 state 字段中将对应位进行置位操作(置为 1 即可),但程序依旧继续运行。

    //使用 cin 过程中出错并且处理的过程 
    #include <iostream> //streamsize
    #include <string>
    #include <limits> //numeric_limitsusing namespace std;int main()
    {int number = 0;cin >> number;if (cin.fail()) //判断 cin 的状态,若 cin 为错误状态则返回 true, 正常状态则返回 false{cout << "发生错误" << endl;cin.clear(); //清除cin的错误状态(重要)in.ignore(numeric_limits<streamsize>::max(), '\n');  //忽略缓冲区中的所有字符,直到遇到换行符为止(重要)/* (1)std::numeric_limits 是一个模板类,用于获取各种数值类型(如整数、浮点数等)的特征信息 (2)std::streamsize 是一个类型,用于表示输入/输出流操作的字节数或字符数的整数类型,通常情况下等同于 std::ptrdiff_t,也就是指针之间的差值类型*/}else{cout << "number:" << number << endl;}//如果不清除状态,代码后续的 cin 都不会被执行,并且原先的输入数据仍然留在缓冲区中//如果清除状态后,没有清除缓冲区,则原先留在缓冲区的数据会被 cin 继续读取char character = 0;cin >> character;cout << "character:" << character << endl;return 0;
    }
    
  2. 空格和回车都可以作为数据之间的分格符,所以多个数据可以在一行输入,也可以分行输入。但如果是字符型或字符串,则空格(ASCII 码为 32)无法用 cin 输入,字符串中也不能有空格,回车符也无法被读入(这里可以了解一下 C++ 的原始字符串)。

    //cin 无法直接获取空格字符和回车字符
    #include <iostream>
    #include <string>
    using namespace std;int main()
    {string str;cin >> str;cout << "str:" << str; //输入空格字符和换行字符无效return 0;
    }
    

    这也使得读取读取带有空格的长字符串成为困难,因此可以使用 getline() 替代 >> 输入:

    注意:getline 有两个版本,还挺乱的,待补充…

  3. cincout 可以直接输入和输出内置类型数据,这是因为标准库已经将所有内置类型的输入方法和输出方法全部重载了。而对于自定义类型,若要支持 cincout 的标准输入输出,需要对 <<>> 进行重载

  4. istream 类型对象可以转换为逻辑条件判断值。使用 while(cin >> i){/*...*/} 去流中提取对象数据时, 调用的是 istream& operator >>(),但其返回值是 istream 类型的对象,为什么这里可以直接做逻辑条件呢?

    这是因为 istream 对象自动调用了 operator bool()(类似隐式类型转载)。因此如果接收流失败,或者有结束标志,则可以返回转化后的 bool 类型,值为 false,正常读取则返回 true

    operator bool() 的本质是将自定义类型转化为内置类型,这是我们第一次遇到这种情况。以往我们都是:

    (1)内置类型转内置类型的(C++ 默认支持,是自动的)

    (2)内置类型转自定义类型的(通过构造函数)

    (3)自定义类型转自定义类型的(通过构造函数)

    补充:之前关于自定义类型转自定义类型的例子

    //通过构造函数来转化两个不相干的类型
    list<int> lt;
    list<int>::const_iterator it = lt.begin();
    

    但是没有尝试过自定义类型转化为内置类型(不过内置类型转化为自定义类型是有的,构造函数就可以做到,例如:std::string str = "limou"),这种行为默认不支持,即便用户使用强制类型转化也做不到。

    但用户可以借助 operator bool() 这来达到逆向转化的目的(类似的也有 operatou int() 等),该重载可以算作是关键字的重载,没有返回值,可以让用户有更为强大的转化方法。

    //自定义类型转为内置类型
    #include <iostream>
    using namespace std;class Data
    {
    public:operator int(){return _data2;}
    private:int _data1 = 10;int _data2 = 20;
    };
    int main()
    {Data d;int number = d;cout << number << '\n';return 0;
    }
    

    有这个重置也可以玩出一些比较“奇怪”的玩法:

    //通过自定义隐式转化来控制循环
    #include <iostream>
    using namespace std;class Data
    {friend istream& operator>>(istream& in, Data& d);friend ostream& operator<<(ostream& out, const Data& d);public:operator bool() const{if (_data == 0)return false;elsereturn true;}private:int _data = 10;
    };istream& operator>>(istream& in, Data& d)
    {in >> d._data;return in;
    }ostream& operator<<(ostream& out, const Data& d)
    {cout << "save data:" << d._data << '\n';return out;
    }int main()
    {Data d;while (d == true) //如果用户的输入导致 _data 为 0,则停止循环{cin >> d;cout << d;}return 0;
    }
    

    如果在该重载前加上 explicit (意思为“明确的、坦率地”)就不允许隐式类型转化,但允许强制类型转化。

    //通过自定义显式转化来控制循环
    #include <iostream>
    using namespace std;class Data
    {friend istream& operator>>(istream& in, Data& d);friend ostream& operator<<(ostream& out, const Data& d);public:explicit operator bool() const //添加 explicit 防止隐式类型转化{if (_data == 0)return false;elsereturn true;}private:int _data = 10;
    };istream& operator>>(istream& in, Data& d)
    {in >> d._data;return in;
    }ostream& operator<<(ostream& out, const Data& d)
    {cout << "save data:" << d._data << '\n';return out;
    }int main()
    {Data d;//while (d == true) //这里会报错//while ((bool)d == true) //这样写就不会报错//while (bool(d) == true) //或者这样写也不会报错while (static_cast<bool>(d) == true) //或者这样写也不会报错{cin >> d;cout << d;}return 0;
    }
    

    需要注意的是,库内不是所有类都有这个重载的…

    补充:早期的 C++operator void*() const 来实现上述类似的转化…

  5. 关于 sync_with_stdio(bool sync = true) 的使用:在 C++sync_with_stdio(false) 是一种提升 cincout 效率的手段。

    尽可能在使用 cincout 时,调用成员函数 sync_with_stdio(false),因为 cincout 的输入输出缓冲区和 C 是两套缓冲区逻辑,而 C++ 又需要兼容 C,因此以下代码可以正常运行:

    //两套输入方法之间的兼容关系
    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    #include <cstdio>
    using namespace std;int main()
    {int number = 0;//下面两种输入互不不影响,等同于用两次 cin >> number 或 scanf("%d", &number)cin >> number;cout << number << '\n';scanf("%d", &number);printf("%d", number);//前者输入兼容后者return 0;
    }
    

    而调用成员函数 sync_with_stdio(false) 即可关闭这个兼容(告诉编译器不用考虑 C 语言标准库的输入输出流的兼容问题)。

    //使用 sync_with_stdio(false) 关闭兼容
    #include <iostream>
    using namespace std;int main()
    {cin.sync_with_stdio(false);cout.sync_with_stdio(false);int value;cin >> value;cout << value << endl;return 0;
    }
    

    而调用 sync_with_stdio(false) 后,scanf()printf()cincout 等混用将存在输入顺序/输出顺序与调用顺序不一致的问题(因为它们不再共享相同的缓冲区),且在代码中调用 sync_with_stdio(false) 属于不可逆操作。

    注意:我简单测试了一些平台,暂时没有遇到哪些调用顺序混乱的情况,以后遇到了再补充上来…

  6. 终止字符输入的方法主要有两种,比较暴力的就使用 [ctrl+c],而更为正常的操作是 [ctrl+z+enter],相当于流读取到结束标志。

3.2.C++ 的文件流

C++ 根据文件内容的数据格式分为二进制文件和文本文件。采用文件流对象操作文件的一般步骤:

  1. 定义一个文件流对象
    • ifstream ifile(只输入)
    • ofstream ofile(只输出)
    • fstream iofile(既输入又输出)
  2. 使用文件流对象的成员函数打开磁盘文件,使得文件流对象和磁盘文件之间建立联系
  3. 使用流提取运算符和流插入运算符对文件进行读写操作,或直接使用成员函数进行读写
  4. 关闭文件对象,释放资源(有析构函数的存在,因此可以不显示调用)
//文件流接口演示
#include <string>
#include <fstream>
#include <iostream>
using namespace std;//描述数据的类
struct Data
{int _data1;int _data2;int _data3;
};//描述服务器的类
struct Serverinfo
{char _address[32]; //地址//这里的 _address 不能使用 string 类型,否则二进制写入就回变成写入指向字符串的“指针信息”,而不是“字符串”本身(string 本身的成员有:指向字符串的指针、字符串的大小、存储的容量),//在 string 释放后就会导致指向字符串的指针变成“野指针”,因此读取的时候就会变成野指针解引用,这有可能导致程序奔溃(本质上就是浅拷贝问题)//(1)在同一个进程下,可能只是浅拷贝问题(输出结果有可能对)//(2)但是在两个进程的情况下,就必然会出现野指针解引用(写入的进程将指针指向的资源销毁了)//因此二进制读写的时候,最好不要用容器,否则很容易出现类似的问题//但是文本输入不会在这方面出问题,因为 string 对象会被提前转化为“字符串”后再写入,不会简单进行浅拷贝int _port; //端口Data _data; //数据
};//描述操作的管理器
class ConfigManager
{/* 封装各种文件流的操作 */
public:ConfigManager(const char* fileName): _fileName(fileName){}void WriteBin(const Serverinfo& info){ofstream ofs(_fileName, ofstream::out | ofstream::binary); //二进制写入(ofstream::out 可忽略,ofstream::binary 表示二进制操作)ofs.write((char*)&info, sizeof(info));}void ReadBin(Serverinfo& info){ifstream ifs(_fileName, ofstream::in | ofstream::binary); //二进制读取(ofstream::in 可忽略,ofstream::binary 表示二进制操作)ifs.read((char*)&info, sizeof(info));}//文本写入/读取时,C 语言需要将数据不断转化为字符串再读写,但是 C++ 通过运算重载自动化了这个过程void WriteText(const Serverinfo& info){ofstream ofs(_fileName); //文本写入,直接使用流操作符即可ofs << info._address << " "<< info._port << " "<< info._data._data1 << " "<< info._data._data2 << " "<< info._data._data3 << '\n';}void ReadText(Serverinfo& info){ifstream ifs(_fileName); //文本读取,直接使用流操作符即可ifs >> info._address>> info._port>> info._data._data1>> info._data._data2>> info._data._data3;}private:string _fileName;
};int main()
{Serverinfo winfo = {"190.0.0.0", 80, {1, 2, 3}}; //服务器传递的信息//模拟程序 A(二进制读写)Serverinfo rinfo1; //读取服务器的信息ConfigManager cmb("limouBin"); //信息文件路径cmb.WriteBin(winfo); //写入信息cmb.ReadBin(rinfo1);cout << rinfo1._address << "-" << rinfo1._port << ":"<< rinfo1._data._data1 << "-"<< rinfo1._data._data2 << "-"<< rinfo1._data._data3 << '\n';//模拟程序 B(文本读写)Serverinfo rinfo2; //读取服务器的信息ConfigManager cmt("limouText.txt"); //信息文件路径cmt.WriteText(winfo); //写入信息cmt.ReadText(rinfo2);cout << rinfo2._address << "-" << rinfo2._port << ":"<< rinfo2._data._data1 << "-"<< rinfo2._data._data2 << "-"<< rinfo2._data._data3 << '\n';return 0;
}

补充:可以看到,写入文件的字符默认使用空格分割,但是有些时候我们需要输入带有空格的数据,这种情况可以了解一下 fstream 下的成员函数 getline(),这个接口和之前 IO 流的功能类似…

3.3.C++ 的字符流

C 中若想要将一个“自定义类型数据转化为字符串类型数据”或者“字符串类型数据转化为自定义类型数据”,有以下常见方式:

  • 使用 itoa()、使用 sprintf() 输出字符串数据
  • 使用 sscanf() 读取字符串数据

但都需要给出保存结果的空间大小,而空间的大小不容易界定,且转化格式不匹配时,还会得到错误的结果甚至是程序崩溃,因此 C++ 又设计了新的 sstream 头文件,该文件包含四个类:

  1. istringstream:进行流的输入
  2. ostringstream:进行流的输出
  3. stringstream:进行流的输入输出操作

我们主要介绍 stringstream,该类在其底层维护了一个 string 类型的对象用来保存结果。

注意:这个类用起来还是很不错的,推荐使用…

3.3.1.将数值类型数据格式化为字符串

//将数值类型数据格式化为字符串
#include <sstream> //stringstream
#include <iostream>
#include <string>
using namespace std;int main()
{string str;stringstream ss;//将一个整形变量转化为字符串,存储到 string 类对象中int int_a = 114514;ss << int_a; //输入数据ss >> str; //输出数据cout << str << '\n';cout << ss.str() << '\n'; //str() 返回 stringsteam 中管理的 string 成员//stringstreams 在转换结尾时(即最后一次转换输出后),会将其内部状态设置为 badbit//因此如果我们需要多次转换,就必须使用 clear() 将上次转换状态清空掉,将状态重置为 goodbit 才可以转换ss.clear();//但是 clear() 不会将 stringstreams 底层字符串清空掉(第一次使用很容易误解 clean() 的作用)//如果不将 stringstream 底层管理 string 对象设置成 "",则多次转换时,就会将结果全部累积在底层 string 对象中ss.str("");//将一个浮点变量转化为字符串,存储到 string 类对象中double d = 3.14159;ss << d; //输入数据ss >> str; //输出数据cout << str << '\n';cout << ss.str() << '\n'; //str() 返回 stringsteam 中管理的 string 成员return 0;
}

3.3.2.字符串拼接

//字符串拼接
#include <sstream>
#include <iostream>
using namespace std;int main()
{stringstream ss;//将多个字符串放入 sstream 中sstream << "first" << " " << "string,";sstream << " second string";cout << "strResult is: " << sstream.str() << endl;//清空 sstreamsstream.str("");sstream << "third string";cout << "After clear, strResult is: " << sstream.str() << endl;return 0;
}

3.3.3.序列化和反序列化数据

//序列化和反序列化数据
#include <sstream>
#include <iostream>
using namespace std;struct Date
{int _year = 2023;int _month = 12;int _day = 19;
};
istream& operator>>(istream& in, Date& d)
{return in >> d._year >> d._month >> d._day;
}
ostream& operator<<(ostream& out, const Date& d)
{return out << d._year << " " << d._month << " " << d._day;
}struct ChatInfo
{string _name = "name";      //名字int _id = 0;                //idDate _date = { 2000,1,1 };  //时间string _msg = "msg";        //聊天信息
};int main()
{//1.结构信息序列化为字符串ChatInfo winfo = { "limou", 114514, { 2023, 12, 19 }, "今天晚上吃什么?" };ostringstream oss;oss << winfo._name << " "<< winfo._id << " " << winfo._date << " "<< winfo._msg;string str = oss.str();cout << str << '\n';//假设通过网络,将这个字符串发送给对象//一般会选用 JSON、XML 等方式进行更好的序列化支持(是描述信息用的文件)//2.字符串解析成结构信息ChatInfo rInfo;istringstream iss(str); //将字符传递给 ississ >> rInfo._name >> rInfo._id >> rInfo._date >> rInfo._msg;cout << "-------------------------------------------------------" << '\n';cout << "姓名:" << rInfo._name << "(" << rInfo._id << ") " << '\n';cout << "时间:" << rInfo._date << '\n';cout << "消息:" << rInfo._name << ":>" << rInfo._msg << endl;cout << "-------------------------------------------------------" << '\n';return 0;
}

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

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

相关文章

【数据结构与算法】之字符串系列-20240121

这里写目录标题 一、344. 反转字符串二、125. 验证回文串三、205. 同构字符串四、242. 有效的字母异位词五、290. 单词规律 一、344. 反转字符串 简单 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额…

k8s集群加入一个master2--kubeadm方式

已经有一个集群&#xff1a; 192.168.206.138 master 192.168.206.136 k8s-node1 192.168.206.137 k8s-node2 kubectl get nodes -o wide 新加入一个master2节点 192.168.206.139 master2 一、初始化系统参数 139 master2 上 #在136、137、138上添加hosts“” echo "…

贪心算法笔记

贪心 1.序列问题1.1摆动序列1.2单调递增的数字 2.多维度权衡2.1分发糖果2.2根据身高重构队列 3.区间问题3.1跳跃问题3.2跳跃问题 II3.3用最小数量的箭引爆气球3.4无重叠区间3.5划分字母区间3.6合并区间 4.其他4.1最大子数组和4.2加油站4.3监控二叉树 正如这个算法的名字一样&am…

【办公类-19-02】20240122图书EXCEL插入列并删除空行

作品展示 背景需求 上次23个班级班主任统计图书&#xff0c;写在EXCEL内 【办公类-19-01】20240108图书统计登记表制作&#xff08;23个班级&#xff09;EXCEL复制表格并合并表格-CSDN博客文章浏览阅读693次&#xff0c;点赞12次&#xff0c;收藏7次。【办公类-19-01】202401…

Unity 编辑器篇|(十三)自定义属性绘制器(PropertyDrawer ,PropertyAttribute) (全面总结 | 建议收藏)

目录 1. 前言2. PropertyDrawer2.1 参数总览2.2 两种用途2.3 注意事项2.4 代码样例 3. PropertyDrawer与PropertyAttribute结合使用 1. 前言 在Unity中&#xff0c;PropertyDrawer和PropertyAttribute是两个重要的工具&#xff0c;它们主要用于自定义属性的显示和行为。Proper…

【JS逆向学习】国家加密系列-SM算法实例

SM系列 1、国家加密算法介绍 事实上从 2010 年开始&#xff0c;我国国家密码管理局就已经开始陆续发布了一系列国产加密算法&#xff0c;其中SM1、SM4、SM7、祖冲之密码&#xff08;ZUC&#xff09;是对称算法&#xff1b;SM2、SM9是非对称算法&#xff1b;SM3是哈希算法。目…

Django框架二

一、模型层及ORM 1.模型层定义 负责跟数据库之间进行通信 2.Django配置mysql 安装mysqlclient&#xff0c;mysqlclient版本最好在13.13以上 pip3 install mysqlclient DATABASES {default: {ENGINE: django.db.backends.mysql,NAME: "mysite1",USER:root,PASSWO…

pip安装之后还是无法使用问题处理

最近由于需要使用到Python 相关功能&#xff0c; 记录下一些入门小技巧 1 python 下载安装 在window10 环境下载免安装版本&#xff0c; 并解压 安装包下载地址&#xff1a; https://www.python.org/ftp/python/3.12.1/python-3.12.1-embed-amd64.zip 2. 安装pip, 由于是内嵌…

【立创EDA-PCB设计基础】5.布线设计规则设置

前言&#xff1a;本文详解布线前的设计规则设置。经过本专栏中的【立创EDA-PCB设计基础】前几节已经完成了布局&#xff0c;接下来开始进行布线&#xff0c;在布线之前&#xff0c;要设置设计规则。 目录 1.间距设置 1.1 安全间距设置 1.2 其它间距设置 2.物理设置 2.1 导…

力扣hot100 合并两个有序链表 递归 双指针

Problem: 21. 合并两个有序链表 文章目录 &#x1f496; 递归思路 &#x1f496; 双指针 &#x1f496; 递归 思路 &#x1f468;‍&#x1f3eb; 参考地址 n , m n,m n,m 分别为 list1 和 list2 的元素个数 ⏰ 时间复杂度: O ( n m ) O(nm) O(nm) &#x1f30e; 空间复杂…

是谁说网工这行是小众行业?我帮你搜了搜……

有人说网工这行是个小众行业&#xff0c;很多朋友在喊岗位不够多&#xff0c;我帮你搜了搜&#xff0c;其实招聘岗位的需求真的很多&#xff1a; 可能你换着搜索下关键词&#xff0c;善用不同类型的渠道&#xff0c;你会有新的惊喜。 能达到这要求的&#xff0c;这位朋友&#…

线程池--JAVA

虽然线程是轻量级进程&#xff0c;但是如果当创建和销毁的的频率非常之高&#xff0c;那么它也就会消耗很多的资源。 而线程池就是用来优化线程频繁创建和销毁的场景&#xff0c;减少线程创建、销毁的频率。 ExecutorService JAVA标准库为我们实现了线程池&#xff0c;Execu…

华而有实,维乐Prevail Glide带你领略风景线,成为风景线~

大家都知道呢&#xff01;骑行&#xff0c;不仅是一种运动&#xff0c;更是一种生活态度。在骑行装备的世界里&#xff0c;一个好的坐垫对于骑行的舒适度和安全性至关重要。那今天&#xff0c;我要为大家推荐一款备受赞誉的坐垫——维乐坐垫美学系列-Prevail Glide。    为…

基于springboot+vue的甘肃非物质文化网站(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 研究背景…

pycharm创建vue项目idealTree:npm: sill idealTree buildDeps,换taobao源后还不好使?那就再换一个

心血来潮打算写个小项目&#xff0c;前后端分离&#xff0c;flask/fastapivue&#xff08;具体用哪个后端还没想好&#xff09;&#xff0c;里面的功能大概就是目前所有热门的应用的合集&#xff0c;一键出结果的那种&#xff0c;然后跟随着科技趋势&#xff0c;不断去更新维护…

CSGO搬砖项目还能火多久?

最近放假回到老家&#xff0c;见了不少亲戚朋友&#xff0c;大家不约而同都在感叹今年大环境不好&#xff0c;工作不顺&#xff0c;生意效益不好&#xff0c;公司状况不佳&#xff0c;反问我们生意如何&#xff1f;为了让他们心里好受一点&#xff0c;我也假装附和道:也不咋地&…

JavaScript DOM表单相关操作之表单相关事件

1、焦点事件 焦点事件就是鼠标的光标事件&#xff0c;点到输入框中&#xff0c;叫做获得焦点事件&#xff0c;当鼠标离开这个输入框时叫做失去焦点事件。 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>知数SEO_专注搜…

Rust 程序设计语言学习——基础语法

Rust 语言是一种高效、可靠的通用高级语言。其高效不仅限于开发效率&#xff0c;它的执行效率也是令人称赞的&#xff0c;是一种少有的兼顾开发效率和执行效率的语言。 Rust 语言由 Mozilla 开发&#xff0c;最早发布于 2014 年 9 月。Rust 的编译器是在 MIT License 和 Apach…

基于SpringBoot+vue的在线视频教育平台的设计与实现,附源码,数据库

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

【文件处理】spring boot 文件处理

接收文件 PostMappingpublic result<String> add(MultipartFile file) throws IOException {// 得到目标文件夹File directory new File("file");//如果文件夹不存在就创建if(!directory.exists()){directory.mkdirs();}//文件名称String fileName file.getO…