您的位置:首页 > 编程语言 > C语言/C++

C++编程思想(卷二):输入输出流

2009-11-09 09:54 204 查看
ostream的成员函数fill()用于更换填充字符,当输出域的宽度大于输出数据长度时,使用填充字符填充超出部分,默认的填充值是一个空格符。可以通过操纵算子setfill()设置这个值。

有3种可选方法来实现按行输入:

1.成员函数get()

2.成员函数getline()

3.定义在头文件<string>中的全局函数getline()

前两个函数有3个参数:

1.指向字符缓冲区的指针,用于保存结果。

2.缓冲区的大小。

3.结束字符,根据结束字符判断何时停止读入操作。

结束字符默认情况下为'/n',当在输入过程中遇到结束字符时, 这两个函数都会在结束缓冲区末尾存储一个零。

get()和getline()两个函数区别:

1.当遇到输入流中的结束字符时get()停止执行,但是并不从输入流中提取结束字符。这时,如果再次调用get()会遇到同一个结束字符,函数将立即返回而不会提取输入。

2.函数getline()则相反,它将从输入流中提取结束字符,但仍然不会把它存储到结果缓冲区中。

get()和getline()在处理完结束字符后均会在缓冲区中写入字符零(并非结束字符)。

<string>中定义的函数getline():它从输入流中读取字符直到遇到第1个结束字符并且丢弃这个结束字符。优点在于它把数据读入一个string对象中,所以不用担心缓冲区的大小。

4个标志位来测试流的状态:

标志位 意义

badbit 发生了(或许是物理上的)致命性错误,流将不能继续使用

eofbit 输入结束

failbit I/O操作失败,主要原因是非法数据。流可以继续使用。输入结束时也将设置failbit标志

goodbit 一切正常;没有错误发生。也没有发生输入结束。

可在程序中调用clear()函数来清空标志位。

文件的打开模式:

标志 功能

ios::in 打开输入文件。将这种打开模式应用于ofstream可以使得现存文件不被截断

ios::out 打开输出文件。将这种模式应用于ofstream,而且没有使用ios::app、ios::ate或ios::in时,意味着使用的是ios::trunc模式

ios::app 打开一个仅用于追加的输出文件

ios::ate 打开一个已存在文件(输入或输出),并把文件指针指向文件末尾

ios::trunc 如果文件存在,则截断旧文件

ios::binary 以二进制方式打开文件。默认打开为文本方式

每个输出流对象包含一个指向streambuf对象的指针,并且streambuf对象拥有一些可供调用的成员函数。对于文件流类和字符串流类,它们有特殊的流缓冲区类型。

每个输入输出流对象有一个成员函数rdbuf(),它返回一个指向对象streambuf的指针,通过这个指针可以 streambuf对象进行存取。

例:

#include <fstream>
#include <iostream>
#include "../require.h"
using namespace std;
int main() {
ifstream in("Stype.cpp");
assure(in, "Stype.cpp");
cout << in.rdbuf(); // Outputs entire file
}


流定位的两种方法:

1.使用称为streampos的流指针进行绝对流位置定位。

2.实现从文件头、文件尾、当前位置移动某个给定的字节数进行相对流定位。

用streampos进行绝对流定位,需要先调用一个“告知”函数,以便知道流指针在流中的确切位置:对于ostream调用tellp(),对于istream调用tellg()。这个函数返回一个streampos,当要回到流中定位流指针时要用到它,对ostream对象调用seekp(),对istream对象调用seekg()。

相对定位,使用重载版本的seekp()和seekg()函数,一参是要移动的字符数目(可负),二参是移动方向。

ios::beg 流的开始位置

ios::cur 流的当前位置

ios::end 流的末端位置

例:

#include <cassert>
#include <cstddef>
#include <cstring>
#include <fstream>
#include "../require.h"
using namespace std;
int main() {
const int STR_NUM = 5, STR_LEN = 30;
char origData[STR_NUM][STR_LEN] = {
"Hickory dickory dus. . .",
"Are you tired of C++?",
"Well, if you have,",
"That's just too bad,",
"There's plenty more for us!"
};
char readData[STR_NUM][STR_LEN] = {{ 0 }};
ofstream out("Poem.bin", ios::out | ios::binary);
assure(out, "Poem.bin");
for(int i = 0; i < STR_NUM; i++)
out.write(origData[i], STR_LEN);
out.close();
ifstream in("Poem.bin", ios::in | ios::binary);
assure(in, "Poem.bin");
in.read(readData[0], STR_LEN);
assert(strcmp(readData[0], "Hickory dickory dus. . .")
== 0);
// Seek -STR_LEN bytes from the end of file
in.seekg(-STR_LEN, ios::end);
in.read(readData[1], STR_LEN);
assert(strcmp(readData[1], "There's plenty more for us!")
== 0);
// Absolute seek (like using operator[] with a file)
in.seekg(3 * STR_LEN);
in.read(readData[2], STR_LEN);
assert(strcmp(readData[2], "That's just too bad,") == 0);
// Seek backwards from current position
in.seekg(-STR_LEN * 2, ios::cur);
in.read(readData[3], STR_LEN);
assert(strcmp(readData[3], "Well, if you have,") == 0);
// Seek from the begining of the file
in.seekg(1 * STR_LEN, ios::beg);
in.read(readData[4], STR_LEN);
assert(strcmp(readData[4], "Are you tired of C++?")
== 0);
}


例:同时对一个文件进行读和写

#include <fstream>
#include <iostream>
#include "../require.h"
using namespace std;
int main() {
ifstream in("Iofile.cpp");
assure(in, "Iofile.cpp");
ofstream out("Iofile.out");
assure(out, "Iofile.out");
out << in.rdbuf(); // Copy file
in.close();
out.close();
// Open for reading and writing:
ifstream in2("Iofile.out", ios::in | ios::out);
assure(in2, "Iofile.out");
ostream out2(in2.rdbuf());
cout << in2.rdbuf();  // Print whole file
out2 << "Where does this end up?";
out2.seekp(0, ios::beg);
out2 << "And what about this?";
in2.seekg(0, ios::beg);
cout << in2.rdbuf();
}


一般来说,当知道输入流中数据的顺序并把它转换成除字符串之外的数据类型时,最好使用输入输出流提示符。然而,如果想一次性提取一个串中剩余的部分并把它输出到另一个输入输出流中,可以使用函数rdbuf()。

例:

#include <cassert>
#include <cmath>  // For fabs()
#include <iostream>
#include <limits> // For epsilon()
#include <sstream>
#include <string>
using namespace std;
int main() {
istringstream s("47 1.414 This is a test");
int i;
double f;
s >> i >> f; // Whitespace-delimited input
assert(i == 47);
double relerr = (fabs(f) - 1.414) / 1.414;
assert(relerr <= numeric_limits<double>::epsilon());
string buf2;
s >> buf2;
assert(buf2 == "This");
cout << s.rdbuf(); // " is a test"
}


为了将输出结果格式化为string对象,可以调用成员函数str(),每次调用str()函数都会返回一个新的string对象,所以字符串流内置的stringbuf对象不会被破坏。

#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main() {
cout << "type an int, a float and a string: ";
int i;
float f;
cin >> i >> f;
cin >> ws; // Throw away white space
string stuff;
getline(cin, stuff); // Get rest of the line
ostringstream os;
os << "integer = " << i << endl;
os << "float = " << f << endl;
os << "string = " << stuff << endl;
string result = os.str();
cout << result << endl;
}


格式化标志: 使用setf(fmtflags)函数打开标志,使用unsetf(fmtflags)函数关闭标志

开/关标志 作用

ios::skipws 跳过空格(输入流的默认情况)

ios::showbase 打印整型值时指出数字的计数(比如,为dec、oct或hex),showbase标志处于开状态时,输入流也能识别前缀基数

ios::showpoint 显示浮点值的小数点并截断数字末尾的零

ios::uppercase 显示十六进制值时使用大写A~F,显示科学计数中的E

ios::showpos 显示正数前的加号(+)

ios::unitbuf “单元缓冲区”。每次插入后刷新流

默认情况下,标准错误输出流cerr的单元缓冲区处于打开状态。使用单元缓冲会导致大量的系统开销,所有如果程序中频繁使用输出流,则不要使用单元缓冲区,除非不需要考虑程序的执行效率。

格式化域:

ios::basefield 作用

ios::dec 使整型数值的基数为10(十进制)

ios::hex 使整型数值的基数为16(十六进制)

ios::oct 使整型数值的基数为8(八进制)

ios::floatfield 作用

ios::scientific 以科学基数形式显示浮点数

ios::fixed 以固定格式显示浮点数

“automatic” 精度域指示所有有效数字的位数

ios::adjustfield 作用

ios::left 使数值左对齐。使用填充字符填充右边空位

ios::right 使数值右对齐。使用填充字符填充左边空位,此为默认对齐方式

ios::internal 把填充字符放到前导正负号或基数指示符之后,数值之前

宽度、填充和精度设置:

函数 作用

int ios::width() 返回当前宽度。默认为0。用于插入符和提取符

int ios::width(int n) 设定宽度,并返回先前的宽度

int ios::fill() 返回当前填充字符。默认为空格符

int ios::fill(int n) 设定填充字符,并先前的填充字符

int ios::precision() 返回当前浮点数精度。默认情况下,精确到小数点后6位。

int ios::precision(int n) 设定浮点数精度,返回先前的精度

cin >> ws; 可以“吃掉”空格

不带参数的操纵算子在头文件<iostream>中定义,包括dec、oct、hex、ws、endl和flush及以下操纵算子:

操纵算子 作用

showbase 输出整型数时显示数字的基数

noshowbase

showpos 显示正数前面的正号

noshowpos

uppercase 用大写的A~F显示十六进制数,在科学计数型数字中使用大写的E

nouppercase

showpoint 显示浮点数的十进制小数点和尾部的0

noshowpoint

skipws 跳过输入中的空格

noskipws

left 左对齐,向右边填充字符

right 右对齐,向左边填充字符

internal 把填充字符放到引导符或基数指示符和数值之间

scientific 指出浮点数的优先输出格式

fixed

带参数的操纵算子在头文件<iomanip>中定义

操纵算子 作用

setiosflags(fmtflags n) 相当于调用函数setf(n),设置后会一直起作用,知道下一次设置将其改变

resetiosflags(fmtflags n) 清除由n代表的格式化标志,本次设置一直有效,直到进行下一次设置

setbase(base n) 将数的基数设为n,n的取值为10、8或16

setfill(char n) 将填充字符设为n

setprecision(int n) 将数字精度设为n

setw(int n) 将宽度设为n

对输入流使用setw()函数进行设置,只在读 字符串 时有意义。

rand()函数:该函数返回一个零到依赖于操作平台的常量RAND_MAX之间的伪随机数,RAND_MAX常量(一般为所在操作平台的无符号整型最大值)在文件<cstdlib>中定义。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: