本 Wiki 开启了 HTTPS。但由于同 IP 的 Blog 也开启了 HTTPS,因此本站必须要支持 SNI 的浏览器才能浏览。为了兼容一部分浏览器,本站保留了 HTTP 作为兼容。如果您的浏览器支持 SNI,请尽量通过 HTTPS 访问本站,谢谢!
第 7 章笔记
std::cin
)IOstream
指定的外部设备:比如终端,文件,内存)等会有不同的处理逻辑
int x = 100;
// 通过格式化的方式,将二进制的形式转换成了相应的字符序列的表示
std::cout << x << std::endl;
// 使用一块内存
// 用于保存 x 或者 y
union
{
int x;
float y;
};
x = 100;
// 使用不同的方式去解析同一内存中的内容
// float 与 int 的解析方式不同
std::cout << x << std::endl;
std::cout << y << std::endl;
std::basic_stream
:std::basic_ifstream<char>
处理 char
类型字符)get
/ read
/ getline
/ gcount
put
/ write
float
就只会最多输出 4个字节的内容)
int x;
//对指定地址的内容的字符进行读取
//不解析,直接放入 x
//一共读取 4个字符 100加上回车,对应的就是每个字符的 ascii 值
//注意:read 要求 4个字符,在没有满足条件之前,系统会一直等待用户输入
std::cin.read(reinterpret_cast<char*>(&x), sizeof(x));
»
和 «
的重载来输入输出
char c = '0';
// 针对 char 输出字符 0
std::cout << c << std::endl;
// 针对 Int 输出 ascii 48
int ci = static_cast<int>(c);
std::cout << ci << std::endl;
showpos
,改变的是格式化的行为
char c = '0';
// 显示正负,输出 +48
// 只对数值产生影响
std::cout.setf(std::ios_base::showpos);
width()
// 让输出占10个字符,默认往左边加空格
// 默认只生效一次,读取后会被 reset 为 0
std::cout.width(10);
fill
// 使用 * 占位
std::cout.fill('*');
// 等同与之前的 showpos 用法,输出 +48
// witdh 的替换,需要使用 iomanip 头文件,使用 setw()
// fill 的替换,使用 setfill()
std::cout << std::showpos << std::setw(10) << std::setfill('*') << ci << std::endl;
std::endl
std::cin
时,空格+10,+10,+010 都会被提取为 10
char y[5];
// 输入长度超过 4字节 (4+\0) 均会导致内存越界
// std::string 存在缓存机制,不受限制
std::cin >> y;
// 使用 setw() 控制输入的长度,提取前 4 个字符
std::cin >> std::setw(5) >> y;
basic_ifstream
/ basic_ofstream
/ basic_fstream
:别名 i/f stream
,类模板,流中单位为 char
// 传入参数为文件名
// 输出流
std::ofstream outFile("test_file");
// 输出到文件 test_file
outFile << "hello";
// 输入流
std::ifstream inFile("test_file");
std::string x;
inFile >> x;
std::cout << x << std::endl;
std::basic_ostream::isopen()
outFile.open(“test_file”);
outFIle.close();
文件流会处于打开 / 关闭状态:
ostream
的析构函数会在析构其对象时自动销毁ostream
对象的生存周期,使用其析构函数自动关闭文件流
{
// outFile 会在大括号之后自动关闭流
std::ostream outFile.open("test_file");
}
标记名 | 作用 |
---|---|
in | 打开供读取 |
out | 打开供写入 |
ate | 起始位置位于文件末尾 |
app | 附加文件,总是向文件末尾写入 |
trunc | 截断文件,删除文件中内容 |
binary | 二进制模式 |
上述的打开方式都是以二进制的形态设计的,其中每一种打开方式占一位。如果组合使用,则是以两种方式的按位或运算进行:
// in & ate
// 按位 或进行组合
std::ios_base::in; // 0010
std::ios_base::ate; // 0001
// 得到 0011,在文件末尾进行读写
in
/ out
默认起始为文件开始的位置ate
表示起始读写位置处于文件末尾,但该位置可以移动app
表示起始读写位置处于文件末尾,但该位置不可移动
// 将文件中的 hello 替代为 word
std::ofstream outFile("test_file", std::ios_base::out | std::ios_base::trunc);
outFile << "word";
打开方式 | 效果 | 加结尾标记 | 加二进制标记 |
---|---|---|---|
in | 只读打开(读) | 初始位置位于末尾 | 禁止系统转换 |
out|trunc / out | 文件存在则覆盖之前内容,否则建立文件(写) | 初始位置位于末尾 | 禁止系统转换 |
out|app | 在文件末尾写入(写) | 初始位置位于末尾 | 禁止系统转换 |
in|out | 打开文件供更新使用(读写) | 初始位置位于末尾 | 禁止系统转换 |
in|out | trunc | 打开文件,删除已存在内容,并建立文件更新使用(读写) | 初始位置位于末尾 | 禁止系统转换 |
out|trunc
和 out
行为一致。
都定义于 <sstream>
中:
basic_istringstream
:读basic_ostringstream
:写basic_stringstream
:读写char
,也受打开模式的影响(in
/out
/ate
/app
)
int main(int argc, char const *argv[])
{
std::ostringstream myObj;
// 写入内容到流 (整数)
// 转换整数到字符串(格式化)
myObj << 1234;
// 获取 myObj 所对应内存,使用配套的 str() 返回内容(字符串)
std::string ret = myObj.str();
std::cout << ret << std::endl;
//读取字符串,并格式化(转换字符串为 int)
std::istringstream myObj2(ret);
int x;
//将 int 赋值给 x 并打印
myObj2 >> x;
std::cout << x << std::endl;
return 0;
}
// 默认的模式是从起始位置开始替换
// 默认输出流中的内容是 test
// 所有输出都会基于 test 输出
std::ostringstream myObj3("test", std::ios_base::ate);
myObj3 << '1';
// 打印结果为 test1
// stringstream 会自动管理内存
std::cout << myObj3.str();
std::string
str().c_str()
将字符串转换为 C 风格的字符串:该行为未定义str()
返回的是右值c_str()
指向了返回右值的内部的首地址,由于返回的是临时值,所以该访问未定义
// 类似 vector 的空间申请
// 可能每次都会进行 allocate
std::string s;
s += "hello";
s += "world";
s += "hello";
// 改良
// 利用 ostringstream 的大缓存进行拼接
// 不会频繁的 allocate
std::ostringstream word;
word << "hello";
word << "world";
word << "hello";
// 结果相同
std::cout << s;
std::cout << word.str();
std::io_base::iostate
维护状态0
,几种错误可以同时出现(通过 bit 之间的按位或, BitMaskType)badbit
:不可恢复的流错误(比如读写未关联的流)failbit
:可恢复的流错误:读 / 写类型不匹配且无法转换(格式化错误),双重关闭一个流eofbit
:输入序列达到了文件尾部// 使用 cin 的成员检测
std::cout << std::cin.good()
<< std::cin.fail()
<< std::cin.bad()
<< std::cin.eof();
// 转换为 bool 值检测
<<static_cast<bool>(std::cin) << std::endl;
fail
和 eof
可能会被同时设置,但意义不同eof
// 判断之前的输入提取是否成功
if(std::cin >> x) { //}
clear()
:设置当前流的指定状态(默认为 goodbit
)setstate()
:将某个状态附加到指定流上,
std::cin.clear();
exception()
捕获流的异常提取写入时,需要考虑提取写入的位置(定位)。C++ 为此引入了流的定位:
tellg()
:获取输入流中,接下来要读取的字符的位置tellp()
:获取输出流中,当前可以写入的位置(读的是 white space)pos_type
类型。获取失败时,返回 pos_type(-1)
fail() == true
时seekg()
/ seep()
:用于设置输入 / 输出流(覆盖输出)pos_type
的版本beg
,end
,cur
)+ 位移系统默认的 “缓冲区满再输入到设备的” 行为很可能带来一些问题:
// 如果 some test 所在流没有满,导致没有被输出到终端
std::cout << "some test";
std::string name;
// 导致输入时没有提示
std::cin >> name;
这种情况下需要刷新缓冲区,也就是强制输出缓冲区内容送到设备上。
flush()
:输出流同步,刷新缓冲区
// 成员调用
std::cout.flush();
// 操纵符
std::cout << x << std::flush;
sync()
:输入流同步,实现由编译器定义std::unitbuf
:std::cerr
(标准错误输出)联用,因为错误信息必须及时更新C++ 中,任意流都可以绑定到一个输出流上。当绑定时,绑定流会记录被绑定流中的信息。当绑定时:
这种方法实际上从另外的角度解决了之前提到过的问题:
// 如果 some test 所在流没有满,导致没有被输出到终端
std::cout << "some test";
std::string name;
// 导致输入时没有提示
std::cin >> name;
此时如果 std::cin
绑定了 std::cout
,那么当 std::cin
输入时,就会直接情况输出流的缓存,将我们需要的 some test
文本输入终端。
sync_with_stdio
关闭同步