1.输入输出流
流:若干个字符从一端到另一端我们叫做流。
输入流:istream类
输出流:ostream类
输出流的对象有三种。
预先定义的三个输出流对象
cout
标准输出,可以文件重定位(从文件中读取数据)cerr
标准错误输出,没有缓冲,发送给他的内容立即输出,不能文件重定位clog
类似于cerr
,但是有缓冲,缓冲区满时被输出,可以文件重定位
解释一下文件重定向:通过freopen函数重定位输出输入流。
freopen("1.txt", "r", stdin);
int a, b;
cin >> a >> b; //从1.txt中读取数据,并赋值freopen("2.txt", "w", stdout);
cout<<a+b<<endl; //把a+b的结果输入到2.txt中
clog<<a+b<<endl; //和clog一样 可以重定向输入输出 cerr不行
输入输出的成员函数
- cin的成员函数
- get 函数
- cin.get(‘ a ’) //字符处理函数 获取一个字符a,返回值为获取的字符
- char c=cin.get(‘ a ’)
- getline() 函数
- cin.getline(str,20) //字符串处理函数,获取20个字符并赋值到str字符数组中
- 处理的必须是字符串(char*) ,string类型不能处理
- cout的成员函数
- put 函数
- cout.put(ch) //字符输出函数,只能输出字符,这里ch是一个char类型变量
- write 函数
- cout.write(str,20) //字符串处理函数,输出指定长度字符串(char* 类型)
格式控制字符( 包含头文件 iomanip)
- 常用的格式控制,一种是调用成员函数方式,一种流控制字符去做
- 设置有效位数: setprecision(n)
- 设置精度: fixed结合setprecision使用
setiosflags 操纵符
- 这个程序中,通过使用带参数的 setiosflags 操纵符来设置左对齐,setiosflags 定义在头文件 iomanip 中
- 参数ios_base::left是ios_base静态常量,因此引用时必须包括ios_base::前缀。
- 这里需要用resetiosflags操纵符关闭左对齐标志。setiosflags不同于width和setw,它的影响是持久的,直到resetiosflags重新恢复默认为止
- setiosflags 的参数是该流的格式标志值,可用按位或 (|) 运算符进行组合
精度
- 浮点数输出精度默认值是6,例如:3466.98
- 要改变精度:setprecision操作符(定义在iomanip中)
- 如果不指定fixed或scientific,精度值表示有效数字位数
- 如果设置了ios_base::fixed或ios_base::scientific精度值表示小数点之后的位数
//精度
double pi = 34.12343;
cout << "设置有效位数是:" << setprecision(4) << pi << endl; //一共四位数
cout << "有效小数位:" << fixed << setprecision(4) << pi << endl; //小数点后四位数//进制输出
cout << hex << 32 << endl; //十六进制
cout << oct << 15 << endl; //8进制输出
cout << setbase(10) << 15 << endl; //8-16
cout << setiosflags(ios::left); //ios::right 设置左对齐(右对齐)
cout << resetiosflags << endl; //可以通过resetionsflags来重置格式标识
2.字符流
用的是头文件:sstream类
-
istringstream类 (输入流)
-
ostringstream类 (输出流)
-
一般用时stringstream类对象即可 (既可输入又可输出,综合了上述两种)
-
获取字符流对象中的数据
-
string str() //获取string
-
void str(const string& str); 重新设置字符流对象的数据
-
两种创建字符流对象并赋值的操作
stringstream sso(string("ILoveyou"));
cout << sso.str() << endl; //通过str成员函数输出 流对象中的字符串
//或者构建无参字符流对象
stringstream ssnull;
ssnull<<"iLoveYou"<<endl; //通过流运算符流入对象
cout << ssnull.str() << endl;
//没有等号直接赋值的写法
//stringstream ss = string("iLoveYou");
通过str成员函数的重写来修改流对象中的字符串
stringstream sso(string("ILoveyou"));
cout << sso.str() << endl; //通过str成员函数获取流对象中的字符串
sso.str("xxLL"); //通过void str(const string& str); 重新设置字符流对象的数据
-
一般字符流对象做字符串处理
-
字符串分割:示例 分割23,132,3443,54,54,65
-
stringstream sData("23,123,5,454,7,388");
int data[6];
char cData[5];
for (int i = 0; i < 6; i++){
if (i == 5){
sData >> data[i];
}
else
//流入一个到整型数组 再流入一个到字符数组
sData >> data[i] >> cData[i];
}
-
字符串转换数字问题
具体:创建流对象 把字符或者数字流入对象,然后再作相应的输出。
//字符串与数字之间转换
//数字转字符
int num = 1234;
char input[20] = "";
stringstream transs(input);
transs << num;
transs >> input;
cout << input << endl;
//字符转数字
stringstream snum("12345");
int temp = 0;
snum >> temp;
cout << temp << endl;
3.文件流
头文件: #include <fstream>
文件输入流:istream类
文件输出流:ostream类
综合输入输出流:fstream
打开关闭文件
打开文件: void open(const char* URL,ios::openmode mode);
关闭文件: void close()
读写方法(ios::openmode)
ios::in 读的方式打开文件
ios::out 写方式打开文件 具有创建功能
ios::app 追加模式 具有创建功能呢
ios::ate 追加模式,文件指针指向末尾
ios::trunc 具备创建功能(一般组合使用)
ios::nocreate 不具备创建(一般组合使用)
ios::noreplace 不替换,保留文件原内容 (一般组合使用)
ios::binary 二进制的形式(一般组合使用)
读写的组合方式用的是 |
可读可写可创建: ios::in | ios::out | ios::trunc
二进制的可读可写课创建: ios::in | ios::out | ios::trunc | ios::binary
文件指针定位
ifstream类的对象
istream& seekg(long int pos);
istream& seekg(long int pos,ios_base::seekdir position);
ofstream类的对象
ostream& seekp(long int pos);
ostream& seekp(long int pos,ios_base::seekdir position);
一般直接使用 fstream 类,对象即可使用 seekg ,也可使用 seekp
ios_base::seekdir (本质是枚举类型)
ios::beg 文件开始位置 //SEEK_SET
ios::end 文件结束位置
ios::cur 文件当前位置
判断文件是否打开成功
fstream file;
//调用成员函数打开文件
file.open("1.txt", ios::in);
//1.判断文件是否成功(调用成员函数)
if (!file.is_open()) {
cout << "打开文件失败" << endl;
}
//2.判断文件是否成功(运算符重载)
if (!file) {
cout << "打开文件失败" << endl;
}
//调用成员函数关闭文件
file.close();
文件读写的两种方式:1.流读写
2.二进制读写
注意 用下面这种流操作符对文件输入输出时,会有一个弊端:输入时会跳过空格和换行符。
fstream read(readFileName, ios::in);
fstream write(writeFileName, ios::out);
//成员函数eof() 判断是否在文件末尾
//注意 这种<< >>流入流出的方法没法获取文件中的空格和换行 原理类似于cin遇到空格和换行表示输入结束
while (1) {
char key;
read >> key;
if (read.eof()) {
break;
}
write << key;
}
用get() put()的成员方法就不会有这样的弊端
//用get() put()成员函数方法则没有这个弊端
while (1) {
char key;
key = read.get();
if (read.eof()) {
break;
}
write.put(key);
}
上面是通过字符一个一个输入输出流,也可以通过字符串一个个输入输出文件流。
输入流通过对象调用成员函数 getline() 来读取字符串(一行一行读取),输出流通过成员函数 write() 来写入字符串。
注:默认的 getline() 遇到”\n“才停止,且”\n“不会被接受
fstream read(readFileName, ios::in);
fstream write(writeFileName, ios::out);
//上述两种都是以字符的形式读取
//下面以字符串的形式读取
while (1) {
char str[1024] = "";
read.getline(str, 1024); //getline() 一行一行读取 不设定终止符默认为"\n" 遇到"\n"停止 但"\n"不会被存储
if (read.eof()) {
break;
}
write.write(str, strlen(str));
}
read.close();
write.close();
以上都是流的方式读写。流的方式读写需要注意用流运算符时的弊端,而二进制读写就没这么多问题了。二进制通过read() 和 write() 方法来读写
//二进制直接读取写入 不需要考虑这么多问题
fstream readFile(readFileName, ios::in|ios::binary);
fstream writeFile(writeFileName, ios::out | ios::binary);
while (!readFile.eof()) {
char str[1024] = "";
readFile.read(str, 1024);
writeFile.write(str, 1024);
}
readFile.close();
writeFile.close();
文件指针
-
ifstream类的对象
-
istream& seekg(long int pos);
-
istream& seekg(long int pos,ios_base::seekdir position);
-
-
ofstream类的对象
-
ostream& seekp(long int pos);
-
ostream& seekp(long int pos,ios_base::seekdir position);
-
-
ios_base::seekdir
-
ios::beg 文件开始位置 //SEEK_SET
-
ios::end 文件结束位置
-
ios::cur 文件当前位置
-
fstream readFile(readFileName, ios::in);
fstream writeFile(writeFileName, ios::out);
readFile.seekg(2, ios::beg);
char key = readFile.get(); //读取的是文件指针后面的那个字符
writeFile.put(key);
readFile.seekp(-3, ios::end);
key = readFile.get();
writeFile.put(key);
readFile.seekg(1, ios::cur);
key = readFile.get();
writeFile.put(key);
readFile.close();
writeFile.close();
注:读取是从文件指针后面一个字符开始读取的。