输入输出

标准输入输出

c语言使用printfwprintf作为标准输出函数;

int wprintf(const wchar_t *format, ...);

wprintf()时,要用%ls表示wchar_t的字符串,用%s表示char的字符串; Windows 的实现用%ls%s都可以正确输出wchar_t字符串。

C++使用coutwcout作为标准输出函数; 在输出Unicode编码的宽字符时,使用带前缀“w”的函数;在使用之前需要设置程序的区域,即调用setlocale函数(C语言),或使用locale类和流对象的imbue(C++)。

char * setlocale ( int category, const char * locale );

在Linux下,可以使用 locale -a 命令查看系统中所有已配置的 locale。用不带选项的 locale命令查看当前 Shell 中活动的 locale。用locale -m 命令查看locale系统支持的所有可用的字符集编码。

Linux下wcout可以输出char型字符串和wchar_t型字符串。运行环境的locale设置要和程序中setlocale()设定的locale一致,比如:终端的活动字符集、环境变量(一般用LANG),要设置为*.UTF-8,才能显示setlocale(LC_ALL, "zh_CN.UTF-8") 设定的wchar_t的中文字符。

不要混用char和 wchar_t 版本的流操作函数,否则会导致这些函数运行异常。

fscanf 在Linux下,只能正常读取UTF-8(ASCII)编码的文本,不能对其他编码格式进行自动解码。 如果是其他编码,则需要以字节方式读入,手动转换为UTF-8编码,才能正常使用。

I/O StreamsIO descDetailsOperators
std::cinstdinreads from buffer.cin >> var
std::coutstdoutoutput to console when buffer full.cout << var
std::clogstderroutput to console when buffer full.clog << var
std::cerrstderrimmediately writes to console.cerr << var
using namespace std;
getline(cin, s);      // read entire line
getline(cin, s, ch);  // read until next character ch

数据流

C++输入输出通过输入输出流类来完成,在头文件“iostream”中定义了这些类的基类:

istream:从流中读取数数据。

ostream:写入数据到流中。

iostream:对流进行读和写操作,继承自istreamostream

std iostream

所有输入输出流类,还有其宽字符版本,以支持国际化。宽字符版本在普通版本前增加“w”前缀。所有类型均由basic_xxxstream通过模板参数(charT, traits)实例化(类似于string类型)。

std::cinistream类型对象;std::coutostream类型对象

格式化

所有设置函数未接收参数时,返回当前的设置。

标识
old_flags = cout.flags(ios::right|ios::hex); // set all flags
old_flags = cout.setf(flags, mask);  //only set specified flags
void unsetf(fmtflags mask);   // clear specified flags

flags()设置流的所有标识(未给出的清空),而setf仅设置给出的标识(未给出的不变)。

标识为两种:1) 独立标识;2) 选择性标识:一组包括多个标识,但同时只能设置一个。mask用于设置选择性标识,用以清空非当前设置的同组其他标识。

标识定义在ios类中,类型为fmtflagsbitmask)。

独立标识
独立标识说明
boolalpha以字符串格式读写bool值 (true and false)
showbase输出前缀(0x,o
showpoint浮点数总是输出小数点
showpos整数输出+
skipws跳过输入内容前面的空白
unitbufflush output after each inserting operation.
uppercase替换未大写字母 in certain insertion operations.
选择性标识
选择性标识位掩码说明
left, right or internaladjustfield对齐方式
dec, oct or hexbasefield计数进制
scientific or fixedfloatfield浮点数表示法

使用操作符格式化:

cout << fixed;
cout << scientific;
cout << boolalpha;   // booleans as string
宽度
ios.width(int n);   // cout << std::setw() #include <iomanip>
ios.fill(char ch);  // 填充字符

显示数据的最小宽度,数据内容少于该宽度将填充字符,填充字符位置更具对齐方式决定(adjustfield)。

精度

精度的具体定义取决于使用定点法或科学计数法。

ios.precision(int n)  // cout << std::setprecision(n)
locale
locale loc = ios.getloc()

状态

iostate s = ios.rdstate();   // 返回内部错误状态标识
bool tf = ios.good();// goodbit: True if no errors
bool tf = ios.eof(); // eofbit:
bool tf = ios.fail();// failbit|badbit: IO逻辑错误(在输入模式下执行输出,识别内容失败)
bool tf = ios.bad(); // badbit: IO操作读写错误

badbit:标志着系统级的故障,如无法恢复的读写错误。如果出现了这类错误,则该流通常就不能再继续使用了。

failbit:出现的是可恢复的错误,如在希望获得数值型数据时输入了字符,此时则设置 failbit 标志,这种导致设置 failbit的问题通常是可以修正的。

eofbit:遇到文件结束符时设置。

当流出现错误时,缓存中的错误内容不会自动被丢弃,再该流上继续执行操作还会产生错误。

cin.clear(state=goodbit)  // 重置状态
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 清除缓存

设置异常触发:根据设置的状态触发异常。

ios.exceptions(iostate except);

读写操作符

<<”操作符(print()):将数据格式化输出到输出流。

>>”操作符:从输入流扫描并格式化读入数据。

重载运算符
std::ostream& operator << (std::ostream& os, point const& p) {
  return os << '(' << p.x << ',' << p.y << ')';
}
std::istream& operator >> (std::istream& is, point& p) {
  return is >> p.x >> p.y;
}

https://hackingcpp.com/cpp/std/istream_recover_from_errors.html

读写方法

std::getline(istream&, string&, stopat='\n')
std::istream.ignore(n, c)  // skip n chars, or until char 'c'.

流式字符串读写

ostringstreamistringstream

流式文件读写

用于普通文件读写的输入输出流类在头文件“fstream”中声明,包含以下类型:

#include <fstream>
using namespace std;
ifstream; // 继承`istream`,用于读文件。
ofstream; // 继承`ostream`,用于写文件。
fstream;  // 继承`iostream`,用于读写文件。

fstream中声明的类除了继承下来的行为外,还定义了两个新操作——openclose,以及形参为要打开的文件名的构造函数。

std::ofstream os {"squares.txt", ios::in};  // ios::binary 
os.open("squares.txt");     
os.good();    
os.close();     // file can be automatically closed