php企业网站通讯录管理系统,组织建设六个方面内容,能玩游戏的网站,pc网站转换手机网站wap1. IO 流
1.1 流的概念
在C中#xff0c;存在一种被称为“流”的概念#xff0c;它描述的是信息流动的过程#xff0c;具体来说就是信息从外部输入设备#xff08;比如常见的键盘#xff09;传输到计算机内部#xff08;像内存区域#xff09;#xff0c;以及信息从内…1. IO 流
1.1 流的概念
在C中存在一种被称为“流”的概念它描述的是信息流动的过程具体来说就是信息从外部输入设备比如常见的键盘传输到计算机内部像内存区域以及信息从内存向外部输出设备例如显示器传输的过程因其类似水流一样的连续性所以被形象地比喻成“流”。
C的“流”具备两个重要特性 有序连续意味着信息在流动过程中是按照一定顺序依次进行传输的就好像水流沿着固定的河道依次流淌那样不会出现无序混乱的情况。具有方向性流的传输是有明确方向的要么是从外部输入设备到内存的输入方向要么是从内存到外部输出设备的输出方向不能随意反向或者混淆。 为了能够实现这种信息的流动过程C专门定义了I/O标准类库。在这个类库当中包含了多个类每一个这样的类都被称作“流”或者“流类”它们各自承担着完成某一方面相关功能的任务共同协作来保障信息在计算机内外设备之间顺利地实现输入和输出操作。
1.1 C IO 流
C 系统实现了一个庞大的类库其中 ios 为基类其他类都是直接或间接派生自 ios 类。 1.2 iostream
其中 iostream它主要用于标准输入输出操作。其中std::cin 用于从标准输入设备通常是键盘读取数据。std::cout 用于向标准输出设备一般是显示器输出数据就能在屏幕上显示指定的字符串。
比如说下面一个简单的示例首先用 cout打印提示信息然后用 cin读入最后再用 cout打印来验证你输入是否正确。
#include iostream
using namespace std;int main() {int num;cout 请输入一个整数: ;cin num; // 从键盘读取用户输入的整数cout 你输入的整数是: num endl;return 0;
}我们同样可以使用 cerr来打印错误信息比如下面这段代码
当用户输入的除数为 0 时程序使用 cerr 输出错误信息告知用户除数不能为 0需要重新输入。因为 cerr 是无缓冲的所以这个错误提示会马上显示在屏幕上方便用户及时察觉错误情况并进行相应处理。
#include iostream
using namespace std;int main() {int dividend, divisor;cout 请输入被除数: ;cin dividend;cout 请输入除数: ;cin divisor;if (divisor 0) {cerr 错误: 除数不能为 0请重新输入 endl; // 使用 cerr 输出错误提示无缓冲会立即显示return 1; // 结束程序返回错误码}int result dividend / divisor;cout 除法运算的结果是: result endl;return 0;
}并且我们有时候也可以使用 clog打印日志信息
#include iostream
#include ctime // 引入时间相关头文件用于获取当前时间
using namespace std;int main() {time_t now time(0); // 获取当前时间的时间戳char* dt ctime(now); // 将时间戳转换为字符串形式的日期时间clog 程序开始运行当前时间是: dt; // 使用 clog 记录程序开始运行的日志信息有缓冲int num;cout 请输入一个整数: ;cin num;cout 你输入的整数是: num endl;clog 用户输入了整数 num endl; // 继续使用 clog 记录用户输入的相关日志信息return 0;
}在这里
首先通过 clog 输出程序开始运行时的日志信息记录下当前的时间由于 clog 是有缓冲的它会先将这些日志信息暂存起来通常在缓冲区满了或者程序正常结束等情况下才会输出到屏幕对应的标准错误输出处。之后在用户输入整数后又使用 clog 记录用户输入的具体数值相关的日志内容展示了如何利用 clog 在程序运行过程中对一些关键信息进行日志记录便于后续查看程序执行情况等分析工作。
我们使用 cin 和 cout 可以直接输入和输出 内置类型数据原因就是标准库已经将所有内置类型的输入和输出全部重载了。 如果我们想使用 cincout输入输出自定义类型就需要进行流插入与流提取重载。比如下面我们实现一个日期类的流提取与流插入。
inline ostream operator(ostream out, const Date d)//流插入
{out d._year / d._month / d._day endl;return out;
}inline istream operator(istream in, Date d)//流提取
{in d._year d._month d._day;return in;
}并且我们一般在刷 OJ 练习题时可能会使用一些这样的做法
// 单个元素循环输入
while(cina)
{// ...
}
// 多个元素循环输入
while(cinabc)
{// ...
}
// 整行接收
while(cinstr)
{// ...
}但是你可能会提出这样的疑问就是 while语句的判断条件一般是 布尔类型而 cin 返回的 istream对象怎么能够做 while的判断条件呢
其实就是 istream实现了 bool 类型转换运算符重载 1.3 fstream
fstream 需要包含头文件fstream。其用于文件的输入输出操作。它包含了 ifstream用于从文件中读取数据即文件输入流、ofstream用于向文件中写入数据即文件输出流以及 fstream既可以读又可以写文件的流对象这几个类。
首先我们来介绍一下常见的文件操作函数
函数名功能getline常用于从输入流比如std::cin或者文件输入流ifstream等中读取一行字符串它可以处理包含空格等空白字符的整行文本内容参数一般是输入流对象和用于存储读取字符串的字符串变量。例如从文件中逐行读取文本内容进行后续处理时经常会用到它。put向输出流写入单个字符例如可以用于向文件输出流ofstream或者标准输出流cout写入特定的字符。write用于将一段指定长度的字符数组或可看作字节序列写入到输出流中常用于文件输出操作可按照设定的字节数将内存中的数据准确地写入到文件等输出目标中。read从输入流中读取指定长度的字节数据到字符数组或其他合适的内存区域中常用于文件输入操作比如从文件里读取一定字节数的数据进行后续解析等处理。open用于打开文件是文件流类ifstream、ofstream、fstream的成员函数通过传入文件名等参数按照指定的模式如只读、只写、读写等打开文件为后续的文件输入输出操作做准备。close对应文件流的 open 操作用于关闭已经打开的文件释放相关的系统资源保证文件操作的正常结束和资源合理利用。is_open文件流类的成员函数用于判断文件是否已经成功打开返回 bool 类型的值在进行文件输入输出操作前通常先通过这个函数检查文件打开情况避免后续对未成功打开的文件进行无效操作。seekg主要用于文件输入流ifstream或者可读写的文件流fstream 在读取模式下可以设置文件读取指针的位置实现从文件的指定位置开始读取数据比如可以跳到文件中间某个位置读取后续内容。seekp针对文件输出流ofstream或者可读写的文件流fstream 在写入模式下用于设置文件写入指针的位置决定后续向文件中写入数据的起始位置例如可以覆盖文件中某个特定位置的原有内容等。tellg用于获取文件输入流ifstream或者可读写的文件流fstream 在读取模式下当前读取指针的位置返回值通常是一个表示位置的偏移量便于记录或者后续根据该位置进行相关操作。tellp对应文件输出流ofstream或者可读写的文件流fstream 在写入模式下可获取当前写入指针的位置同样返回表示位置偏移量的值方便对文件写入操作进行定位和管理。
1.3.1 ifstream
首先我们可以使用 ifstream对文件进行对取。
#include iostream
#include fstream
#include string
using namespace std;int main() {ifstream ifile(input.txt); // 尝试打开名为input.txt的文件if (ifile.is_open()) { // 判断文件是否成功打开string line;while (getline(ifile, line)) { // 逐行读取文件内容cout line endl; // 将读取到的每行内容输出到屏幕显示}ifile.close(); // 读取完成后关闭文件} else {cerr 无法打开文件 input.txt endl;}return 0;
}上述代码尝试打开 input.txt 文件若成功打开则逐行读取文件内容并输出到屏幕最后关闭文件若打开失败会输出错误提示信息。
1.3.2 ofstream
然后我们也可以使用 ofstream对文件进行写入
#include iostream
#include fstream
using namespace std;int main() {ofstream ofile(output.txt); // 创建并打开名为output.txt的文件if (ofile.is_open()) {ofile 这是写入文件的一些内容 endl; // 向文件写入内容ofile.close(); // 写完后关闭文件} else {cerr 无法打开文件 output.txt endl;}return 0;
}此示例创建 output.txt 文件若不存在并向其写入一行文字操作结束后关闭文件若文件打开失败会输出相应错误提示。
1.3.3 fstream
fstream 它兼具输入和输出的功能既可以读取文件里的数据也能往文件里写入数据灵活性更高。一般会与常见的文件打开方式标志结合使用
打开方式标志含义ios::in以输入读取模式打开文件。用于 ifstream 时表示从已存在的文件中读取数据用于 fstream 时使文件可用于读取操作。如果文件不存在使用 ifstream 打开会失败。ios::out以输出写入模式打开文件。对于 ofstream 会创建新文件若文件不存在或者截断覆盖已有文件内容来写入数据用于 fstream 时使文件可用于写入操作。ios::app以追加模式打开文件即写入的数据总是添加在文件末尾不会覆盖原有文件内容。常用于 ofstream 或者 fstream 在写入相关操作时确保每次新写入的内容接续在已有内容之后。ios::ate打开文件后立即将文件指针定位到文件末尾“ate”表示“at the end”可以用于后续的读写操作。常用于 fstream 这样既能读又能写的流后续可以从文件末尾往前读取内容或者继续往文件末尾添加内容等。ios::binary以二进制模式打开文件用于处理二进制数据文件区别于默认的文本模式。在进行文件读写操作时不会对数据进行文本格式相关的转换比如换行符的转换等适用于读写非文本格式的文件像图片、音频等文件或者自定义二进制格式的数据文件可与其他打开方式标志组合使用如 ios::in
这些打开方式标志可以通过逻辑或|运算符进行组合使用以满足不同的文件操作需求。例如ios::in | ios::out | ios::binary 表示以二进制模式打开文件并且这个文件既可以进行读取操作也可以进行写入操作。
比如下面代码我们先读取文件内容再向文件中写入相关数据。
#include iostream
#include fstream
#include string
using namespace std;int main() {fstream iofile(test.txt, ios::in | ios::out); // 以可读可写模式打开test.txt文件if (iofile.is_open()) {string line;// 先读取文件已有的内容并输出到屏幕while (getline(iofile, line)) { cout line endl;}// 将新内容写入文件iofile 新添加的一行内容 endl;iofile.close();} else {cerr 无法打开文件 test.txt endl;}return 0;
}代码中以可读可写模式打开 test.txt 文件先读取文件原有的内容并显示出来然后往文件里写入新的内容最后关闭文件若打开失败则输出错误提示。
最后我们可以将相关的文件操作封装成类再进行使用
#includeiostream
#includestring
#includefstream// 定义结构体ServerInfo用于存储服务器相关信息包含IP地址用字符数组表示和端口号
struct ServerInfo
{char _ip[32];int _port;
};// ConfigManager类用于管理配置文件的读写操作
class ConfigManager
{
public:// 构造函数默认配置文件名是liren.config可传入其他文件名来指定ConfigManager(const char* configfile liren.config):_configfile(configfile){}// 将ServerInfo结构体信息以二进制形式写入配置文件void WriteBin(const ServerInfo info){// 以二进制写模式打开指定的配置文件std::ofstream ofs(_configfile, std::ofstream::out | std::ofstream::binary);if (ofs.is_open()){// 将整个ServerInfo结构体数据写入文件这里强制转换为const char*类型以适配write函数的参数要求ofs.write((const char*)info, sizeof(ServerInfo));}else{// 如果文件打开失败输出错误提示信息到标准错误输出std::cerr 无法打开文件 std::endl;}// 关闭文件流释放相关资源ofs.close();}// 从配置文件中以二进制形式读取数据到ServerInfo结构体中void ReadBin(const ServerInfo info){// 以二进制读模式打开配置文件std::ifstream ifs(_configfile, std::ifstream::in | std::ifstream::binary);if (ifs.is_open()){// 从文件中读取sizeof(ServerInfo)字节的数据到ServerInfo结构体对应的内存空间这里强制转换为char*类型以适配read函数的参数要求ifs.read((char*)info, sizeof(ServerInfo));}else{// 文件打开失败时输出错误提示信息std::cerr 无法打开文件 std::endl;}// 关闭文件流ifs.close();}// 将ServerInfo结构体信息以文本形式写入配置文件每行分别写IP和端口号void WriteText(const ServerInfo info){// 以文本模式打开配置文件默认会覆盖原有内容std::ofstream ofs(_configfile);if (ofs.is_open()){// 先写入IP地址然后换行再写入端口号再换行ofs info._ip std::endl info._port std::endl;}else{// 文件打开失败输出提示信息std::cerr 无法打开文件 std::endl;}// 关闭文件流ofs.close();}// 从配置文件中以文本形式读取数据到ServerInfo结构体中按顺序读取IP和端口号void ReadText(ServerInfo info){// 以文本模式打开配置文件std::ifstream ifs(_configfile);if (ifs.is_open()){// 从文件中依次读取IP地址和端口号到ServerInfo结构体对应的成员变量中ifs info._ip info._port;}else{// 文件打开失败输出错误提示std::cerr 无法打开文件 std::endl;}// 关闭文件流ifs.close();}private:std::string _configfile;
};int main()
{// 创建ConfigManager类的实例使用默认配置文件名ConfigManager cfgMgr;// 初始化一个ServerInfo结构体实例设置IP和端口号ServerInfo winfo { 192.0.0.1, 80 };ServerInfo rdinfo;// 二进制读写操作cfgMgr.WriteBin(winfo);cfgMgr.ReadBin(rdinfo);// 输出读取到的IP地址信息std::cout rdinfo._ip std::endl;// 输出读取到的端口号信息std::cout rdinfo._port std::endl;// 文本读写操作cfgMgr.WriteText(winfo);cfgMgr.ReadText(rdinfo);// 输出读取到的IP地址信息std::cout rdinfo._ip std::endl;// 输出读取到的端口号信息std::cout rdinfo._port std::endl;return 0;
}1.4 sstream
在 C 中sstream 是一个非常实用的输入输出流相关的头文件它提供了对字符串进行类似流操作的功能主要涉及 stringstream、istringstream 和 ostringstream 这几个类以下为你详细介绍
要使用 sstream 相关功能需在代码中包含 sstream 头文件。
1.4.1 ostringstream
ostringstream 类的功能侧重于向一个字符串中写入数据它可以将不同类型的数据按照指定的格式转换为字符串并存储起来方便后续对生成的字符串进行统一的使用或处理常用于动态生成字符串内容比如根据程序运行中的各种变量值拼凑出特定格式的字符串等场景。
以下示例展示了如何使用 ostringstream 生成一个包含特定格式信息的字符串
#include iostream
#include sstream
#include string
using namespace std;int main() {ostringstream oss;int age 25;string name Alice;oss 姓名: name , 年龄: age;string result oss.str(); // 获取ostringstream对象中存储的字符串cout result endl;return 0;
}在上述代码中
先创建了 ostringstream 对象 oss。接着通过流插入操作符 将一个字符串 姓名: 、变量 name 的值、字符串 , 年龄: 和变量 age 的值依次写入到 oss 中此时 oss 内部就根据这些写入的内容拼凑出了一个符合特定格式的字符串。最后通过调用 oss 的 str() 方法获取存储在 oss 中的字符串并将其赋值给变量 result 后输出显示在屏幕上。
1.4.2 istringstream
istringstream 类主要用于从字符串中提取数据也就是将一个字符串当作输入流来解析其中的内容按照特定的格式和数据类型规则读取相应的值常被用于对已经存在的字符串进行信息提取和数据拆分等操作。
假设我们有一个包含多个用空格隔开的整数的字符串想要把这些整数提取出来分别处理示例代码如下
#include iostream
#include sstream
#include string
using namespace std;int main() {string inputStr 1 2 3 4 5;istringstream iss(inputStr);int num;while (iss num) { // 从istringstream对象中不断提取整数直到读完所有整数cout num ;}cout endl;return 0;
}在这个示例中
首先定义了一个包含多个整数用空格隔开的字符串 inputStr。然后创建了 istringstream 对象 iss并将 inputStr 作为参数传入这样 iss 就可以把这个字符串当作输入流来处理了。通过 while 循环和流提取操作符 不断从 iss 中读取整数并输出显示直到读完字符串中所有的整数。
1.4.3 stringstream
首先stringstream 类兼具输入和输出的功能它可以基于一个字符串对象创建流然后在这个流上进行数据的读取类似从输入流提取数据和写入类似向输出流插入数据操作使得字符串能够像普通的输入输出流如 iostream 中的标准输入输出流、fstream 中的文件输入输出流一样被灵活操作。
以下是创建 stringstream 对象并进行简单操作的示例代码
#include iostream
#include sstream
#include string
using namespace std;int main() {stringstream ss;int num 10;double d 3.14;string str Hello, World!;// 将不同类型的数据插入到stringstream对象中相当于写入操作ss num d str;// 从stringstream对象中提取数据还原出原来插入的数据类型和值int extractedNum;double extractedD;string extractedStr;ss extractedNum extractedD extractedStr;cout 提取出的整数: extractedNum endl;cout 提取出的小数: extractedD endl;cout 提取出的字符串: extractedStr endl;return 0;
}在上述代码中
首先创建了一个 stringstream 对象 ss。接着通过流插入操作符 将一个整数 num、一个双精度浮点数 d 和一个字符串 str 依次写入到 ss 中此时这些不同类型的数据被组合到了同一个字符串流里以特定的格式这里是用空格隔开暂存起来。然后使用流提取操作符 从 ss 中依次读取数据将读取到的值赋给相应的变量 extractedNum、extractedD 和 extractedStr。