锁定老帖子 主题:输入输出IO
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-02-12
每一个 IO 头文件都定义了 char 和 wchar_t 类型的类和标准输入/输出对象。 IO 对象不可复制或赋值 由于流对象不能复制,因此不能存储在 vector(或其他)容器中。 形参或返回类型也不能为流类型。如果需要传递或返回 IO 对象,则必须传递或返回指向该对象的指针或引用 对 IO 对象的读写会改变它的状态,因此引用必须是非 const 的。 检测流是否用的最简单的方法是检查其真值 所有流对象都包含一个条件状态成员,该成员由 setstate 和 clear 操作管理。这个状态成员为 iostate 类型,这是由各个 iostream 类分别定义的机器相关的整型。 每个 IO 类还定义了三个 iostate 类型的常量值,分别表示特定的位模式: 流的状态由 bad、fail、eof 和 good 操作提示。如果 bad、fail 或者 eof 中的任意一个为 true,则检查流本身将显示该流处于错误状态。类似地,如果这三个条件没有一个为 true,则 good 操作将返回 true。 clear 操作将条件重设为有效状态。 使用 setstate 操作可打开某个指定的条件,用于表示某个问题的发生。除了添加的标记状态,setstate 将保留其他已存在的状态变量不变。 rdstate 成员函数返回一个 iostate 类型值,该值对应于流当前的整个条件状态 常常会出现需要设置或清除多个状态二进制位的情况。此时,可以通过多次调用 setstate 或者 clear 函数实现。另外一种方法则是使用按位或(OR)操作符在一次调用中生成“传递两个或更多状态位”的值 每个 IO 对象管理一个缓冲区,用于存储程序读写的数据 下面几种情况将导致缓冲区的内容被刷新,即写入到真实的输出设备或者文件: 输出缓冲区的刷新 如果需要刷新所有输出,最好使用 unitbuf 操纵符,这个操纵符在每次执行完写操作后都刷新流 nounitbuf 操纵符将流恢复为使用正常的、由系统管理的缓冲区刷新方式。 警告:如果程序崩溃了,则不会刷新缓冲区 为了确保用户看到程序实际上处理的所有输出,最好的方法是保证所有的输出操作都显式地调用了 flush 或 endl。 当输入流与输出流绑在一起时,任何读输入流的尝试都将首先刷新其输出流关联的缓冲区 交互式系统通常应确保它们的输入和输出流是绑在一起的。这样做意味着可以保证任何输出,包括给用户的提示,都在试图读之前输出。 tie 函数可用 istream 或 ostream 对象调用,使用一个指向 ostream 对象的指针形参。 如果一个流调用 tie 函数将其本身绑在传递给 tie 的 ostream 实参对象上,则该流上的任何 IO 操作都会刷新实参所关联的缓冲区。 一个 ostream 对象每次只能与一个 istream 对象绑在一起。如果在调用 tie 函数时传递实参 0,则打破该流上已存在的捆绑。 fstream 头文件定义了三种支持文件 IO 的类型: fstream 类型除了继承下来的行为外,还定义了两个自己的新操作—— open 和 close,以及形参为要打开的文件名的构造函数。 由于历史原因,IO 标准库使用 C 风格字符串而不是 C++ strings 类型的字符串作为文件名。 假设要使用的文件名保存在 string 对象中,则可调用 c_str 成员获取 C 风格字符串。 打开文件后,通常要检验打开是否成功,这是一个好习惯 这个条件与之前测试 cin 是否到达文件尾或遇到某些其他错误的条件类似。 在尝试打开新文件之前,必须先关闭(close)当前的文件流。 关闭流并不能改变流对象的内部状态。如果最后的读写操作失败了,对象的状态将保持为错误模式,直到执行 clear 操作重新恢复流的状态为止。调用 clear 后,就像重新创建了该对象一样。 如果打算重用已存在的流对象,那么 while 循环必须在每次循环进记得关闭(close)和清空(clear)文件流 如果程序员需要重用文件流读写多个文件,必须在读另一个文件之前调用 clear 清除该流的状态。 在打开文件时,无论是调用 open 还是以文件名作为流初始化的一部分,都需指定文件模式(file mode)。 out、trunc 和 app 模式只能用于指定与 ofstream 或 fstream 对象关联的文件;in 模式只能用于指定与 ifstream 或 fstream 对象关联的文件。所有的文件都可以用 ate 或 binary 模式打开。ate 模式只在打开时有效:文件打开后将定位在文件尾。以 binary 模式打开的流则将文件以字节序列的形式处理,而不解释流中的字符。 默认时,与 ifstream 流对象关联的文件将以 in 模式打开,该模式允许文件做读的操作:与 ofstream 关联的文件则以 out 模式打开,使文件可写。以 out 模式打开的文件会被清空:丢弃该文件存储的所有数据。 对于用 ofstream 打开的文件,要保存文件中存在的数据,唯一方法是显式地指定 app 模式打开 默认情况下,fstream 对象以 in 和 out 模式同时打开。当文件同时以 in 和 out 打开时不清空。 如果打开文件时指定了 trunc 模式,则无论是否同时指定了 in 模式,文件同样会被清空。 模式是文件的属性而不是流的属性 只要调用 open 函数,就要设置文件模式,其模式的设置可以是显式的也可以是隐式的。如果没有指定文件模式,将使用默认值。 添加 ate 只会改变文件打开时的初始化定位,在第一次读或写之前,将文件定位于文件末尾处。 标准库定义了三种类型的字符串流: 定义了名为 str 的成员,用来读取或设置 stringstream 对象所操纵的 string 值。 stringstream 对象的一个常见用法是,需要在多种数据类型之间实现自动格式化时使用该类类型。 为了读取 input_string,必须把该 string 对象分解为若干个部分。我们要的是数值型数据;为了得到它们,必须读取(和忽略)处于所需数据周围的标号。 一般情况下,使用输入操作符读 string 时,空白符将会忽略。于是,在读与 format_message 关联的 string 时,忽略其中的换行符。 #include <iostream> #include <fstream> #include <sstream> #include <stdexcept> #include <string> using namespace std; // opens in binding it to the given file ifstream& open_file(ifstream &in, const string &file) { in.close(); // close in case it was already open in.clear(); // clear any existing errors // if the open fails, the stream will be in an invalid state in.open(file.c_str()); // open the file we were given return in; // condition state is good if open succeeded } // print function: parameter is copied ofstream print(ofstream); int main() { ofstream out1, out2; //out1 = out2; error: cannot assign stream objects //out2 = print(out2); error: cannot copy stream objects int ival; cout << "input zero to exit" << endl; // read cin and test only for EOF; loop is executed even if there are other IO failures while (cin >> ival, !cin.eof()) { if(0 == ival) { break; } if (cin.bad()) // input stream is corrupted; bail out throw runtime_error("IO stream corrupted"); if (cin.fail()) { // bad input cerr<< "bad data, try again" << endl; // warn the user cin.clear(); // reset the stream cin.ignore(255,'\n'); continue; // get next input } // ok to process ival cout << "your input is : " << ival << endl; } // remember current state of cin istream::iostate old_state = cin.rdstate(); cout << "the old_state is " << old_state << endl; cin.clear(); int i; cout << "plz input a integer > " << endl; cin >> i; cout << "your input is " << i << endl; cin.clear(old_state); // now reset cin to old state cout << "hi!" << flush; // flushes the buffer; adds no data cout << "hi!" << ends; // inserts a null, then flushes the buffer cout << "hi!" << endl; // inserts a newline, then flushes the buffer cout << unitbuf << "first" << " second" << nounitbuf; cout << endl; cout << "first" << flush << " second" << flush; //the same as above cout << endl; cin.tie(&cout); // illustration only: the library ties cin and cout for us ostream *old_tie = cin.tie(); cin.tie(0); // break tie to cout, cout no longer flushed when cin is read cin.tie(&cerr); // ties cin and cerr, not necessarily a good idea! // ... cin.tie(0); // break tie between cin and cerr cin.tie(old_tie); // restablish normal tie between cin and cout cin.tie(0); // break tie to cout, cout no longer flushed when cin is read string ifile("in.h"); string ofile("ofile.txt"); // construct an ifstream and bind it to the file named ifile ifstream infile(ifile.c_str()); // check that the open succeeded if (!infile) { cerr << "error: unable to open input file: " << ifile << endl; return -1; } // ofstream output file object to write file named ofile ofstream outfile(ofile.c_str()); ifstream infile2; // unbound input file stream ofstream outfile2; // unbound output file stream infile2.open("my.h"); // open file named "in" in the current directory outfile2.open("out2"); // open file named "out" in the current directory // output mode by default; truncates file named "file1" ofstream outfile3("file1"); // equivalent effect: "file1" is explicitly truncated ofstream outfile4("file1", ofstream::out | ofstream::trunc); // append mode; adds new data at end of existing file named "file2" ofstream appfile("file2", ofstream::app); // open for input and output fstream inOut("copyOut", fstream::in | fstream::out); int val1 = 512, val2 = 1024; ostringstream format_message; // ok: converts values to a string representation format_message << "val1: " << val1 << "\n" << "val2: " << val2 << "\n"; // str member obtains the string associated with a stringstream istringstream input_istring(format_message.str()); string dump; // place to dump the labels from the formatted message // extracts the stored ascii values, converting back to arithmetic types input_istring >> dump >> val1 >> dump >> val2; cout << val1 << " " << val2 << endl; // prints 512 1024 string line, word; // will hold a line and word from input, respectively while (getline(cin, line)) { // read a line from the input into line // do per-line processing istringstream stream(line); // bind to stream to the line we read while (stream >> word){ // read a word from line // do per-word processing cout << word << endl; } } return 0; }
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 2531 次