1.标准输入的不足
<span style="font-family:SimSun;font-size:14px;">#include<iostream>
using namespace std;
int main()
{
int i;
char str[20];
cout<<"请输入一个整型数及一个字符串:";
cin>>i>>str;
cout<<"i="<<i<<endl;
cout<<"str="<<str<<endl;
return 0;
}</span><span style="font-size: 18px;">
</span>
若在命令行上输入1 how are you ? ,按Enter键后执行结果为:
i=1 str=how
原因在于命令行中各参数默认是以空格为界定符的,可以用get系列函数解决这个问题。
2.get系列函数
常用的有3个函数。
(1)int get() ;返回输入流一个字符的ASCII值。
(2)istream& get(unsigned char* pszBuf, int nBufLen, char delim=’\n’);
pszBuf:指向字符缓冲区的指针,用于保存结果
nBufLen:缓冲区长度
delim:结束字符,根据结束字符判断何时停止读入操作
(3)istream& getline(unsigned char* pszBuf, int nBufLen, char delim=’\n’);
get ,getline函数简单示例
<span style="font-size:14px;">#include<iostream>
using namespace std;
int main()
{
char str[60];
cout<<"请输入一个字符串:";
int n=cin.get();
cin.getline(str,60);
cout<<n<<endl;
cout<<str<<endl;
return 0;
}
</span>
若输入How are you?
输出:
72
ow are you?
H的ASCII码为72. getline()函数第三个参数默认结束标志符是“\n”.
3. 处理流错误
获取状态信息的函数如下:
int rdstate();无参数,返回值既是状态信息特征值。
使用下面函数来检测相应输入/输出状态:
bool good();若返回值true,一切正常,没有错误发生。
bool eof(); 若返回值true,表明已到达流的末尾。
bool fail();若返回值true,表明I/O操作失败,主要原因是非法数据(例如读取数字时遇到字母)。但流可以继续使用。
bool bad(); 发生了(或许是物理上的)致命性错误,流将不能继续使用。
1.判断是否输入整形数。
#include <iostream>
using namespace std;
int main() {
int a;
cout << "请输入一个数据: ";
cin>>a;
cout<<"状态值为: " <<cin.rdstate()<<endl;
if(cin.good())
{
cout<<"输入数据的类型正确,无错误!"<<endl;
}
if(cin.fail())
{
cout<<"输入数据类型错误,非致命错误,可清除输入缓冲区挽回!"<<endl;
}
return 0;
}
2.确保输入一个整形数给变量a
#include <iostream>
using namespace std;
int main() {
int a;
while(1)
{
cin>>a; //赋值给整形数a
if(cin.fail()) //如果输入数据非法,则:
{
cout<<"输入有错!请重新输入"<<endl;
cin.clear();//清空状态标识位
cin.get(); //清空流缓冲区
}
else //如果输入数据合法,则:
{
cout<<a<< endl; //直接在屏幕上输出数据
break; //跳出while循环
}
}
return 0;
}
4.文件输入输出流
C++对文件的读写使用的是ifstream、ofstream和fstream流类,同样是依照“打开-->读写-->关闭”原语进行操作。文件读写所用到的很多常数都在基类ios中被定义出来。ifstream类只用于读取文件数据,ofstream类只用于写入数据到文件,fstream则可用于读取和写入文件的数据。
ios::in 以读取方式打开文件
ios::out 以写入方式打开文件
ios::app 每次写入数据时,先将文件指针移到文件尾,以追加数据到尾部
ios::ate 仅初始时将文件指针移到文件尾,仍可在任意位置写入数据
ios::trunc 写入数据前,先删除文件原有内容(清空文件),当文件不存在时会创建文件
ios::binary以二进制方式打开文件,不作任何字符转换.
(1)读文本文件并显示在屏幕上
#include <fstream>
#include <iostream>
using namespace std;
int main(){
char szBuf[80];
ifstream in("a.txt");//通过构造函数创建文件读入流
if(!in) return 0; //若文件不存在,返回
while(in.getline(szBuf, 80)) //通过getline函数按行读取内容
{
cout << szBuf << endl; //将读入缓冲区内容输出到屏幕上,判断是否正确
}
in.close();
return 0;
}
(2)写文本文件:把学生成绩信息保存至文件
<span style="font-size:14px;">#include <fstream>
#include <iostream>
using namespace std;
struct STUDENT //学生成绩结构体
{
char strName[20]; //姓名
int nGrade; //成绩
};
int main() {
ofstream out;
out.open("d:\\a.txt"); //打开或创建a.txt文本文件
STUDENT st1 ={"张三", 90};//用结构体产生两名学生的成绩信息
STUDENT st2 ={"李四", 80};
out << st1.strName << "\t" << st1.nGrade << endl;//把成绩信息存到文本文件
out << st2.strName << "\t" << st2.nGrade << endl;
out.close();
return 0;
} </span><span style="font-size: 24px;">
</span>
可以看出,通过“<<”完成写文本文件是一个较好的方法,这是因为“<<”操作符可把不同类型的数据直接输出。结构体中strName是
字符串,nGrade是整形数,但均可直接输出到文件上即可。此外strName与nGrade之间采用“\t”输出是为了数据对齐,
而“endl”保证输出“\n”回车符,保证了文本文件的换行,是必须的。
(3)读写二进制文件
主要是通过read()、write()函数完成读写二进制文件功能的,原型如下所示
ostream& write(const char *, int nSize)
istream& read(char *, int nSize)
第1个参数表明读写缓冲区的头指针,第二个参数表明读写缓冲区的大小
(4)写二进制文件:把学生成绩信息保存至文件中
<span style="font-size:14px;">#include <fstream>
#include <iostream>
using namespace std;
struct STUDENT //学生成绩结构体
{
char strName[20]; //姓名
int nGrade; //成绩
};
int main() {
ofstream out;
out.open("d:\\a.txt"); //打开或创建a.txt文本文件
STUDENT st1 ={"张三", 90};//用结构体产生两名学生的成绩信息
STUDENT st2 ={"李四", 80};
out.write((const char *)&st1, sizeof(STUDENT)); //把成绩信息存到二进制 文件
out.write((const char *)&st2, sizeof(STUDENT));
out.close();
return 0;
}
</span>
(5)读二进制文件,并把结果显示在屏幕上。
<span style="font-size:14px;">#include <fstream>
#include <iostream>
using namespace std;
struct STUDENT
{
char strName[20]; //姓名
int nGrade; //成绩
};
int main() {
ifstream in;
in.open("d:\\a.txt");
if(!in) return 0;
STUDENT st1;
STUDENT st2;
in.read((char *)&st1, sizeof(STUDENT));
in.read((char *)&st2, sizeof(STUDENT));
cout << st1.strName << "\t" << st1.nGrade << endl;
cout << st2.strName << "\t" << st2.nGrade << endl;
in.close();
return 0;
} </span><span style="font-size: 24px;">
</span>
(3) 输入输出流缓冲
C++标准库封装了一个缓冲区类streambuf,以供输入输出流对象使用。每个标准C++输入输出流对象都包含一个指向streambuf的指针,
用户可以通过调用rdbuf()成员函数获得该指针,从而直接访问底层streambuf对象,可以直接对底层缓冲区进行数据读写,从而跳过上层
的格式化输入输出操作。但由于类似的功能均可由上层缓冲区类实现,所以就不再加以论述了。streambuf最精彩的部分在于它重载了
operator <<及operator >>。对operator <<来说,它以streambuf指针为参数,实现把streambuf对象中的所有字符输出到输出流出中;对
operator >>来说可把输入流对象中的所有字符输入到streambuf对象中。
(6)打开一个文件并把文件中的内容送到标准输出中。
<span style="font-size:14px;">#include <fstream>
#include <iostream>
using namespace std;
int main() {
ifstream fin("d:\\my.txt");
if(fin !=NULL) //判断文件是否存在
{
cout<<fin.rdbuf(); //把文件所有内容输出到屏幕上
}
fin.close();
}</span><span style="font-size: 24px;">
</span>
(4)定位输入输出流
流的位置标识有3个:
ios::beg流的开始位置
ios::cur流的当前位置
ios::end流的结束位置
定位函数主要有两个:
·istream& seekg(long relativepos, ios::seek_dir dir)
针对输入流。第1个参数是要移动的字符数目,可正可负;第2个参数是移动方向,是ios::begin, ios::cur, ios::end中的一
个值。含义是:字符指针相对于移动方向移动了向前或向后移动了多少个字符。
ostream& seekp(long relativepos, ios::seek_dir dir)
针对输出流。参数含义同seekg.
下面示例先写文件,然后再把文件内容读出显示在屏幕上。
<span style="font-size:32px;"> </span><span style="font-size:24px;">#include <fstream>
#include <iostream>
using namespace std;
int main() {
fstream in_out;
in_out.open("d:\\my.txt",ios::in|ios::out|ios::trunc);
in_out.write("Hello", 5);
in_out.seekg(0, ios::beg); //读指针移到文件头
cout << in_out.rdbuf();
in_out.close();
return 0;
}</span><span style="font-size:32px;">
</span>
5.字符串输入输出流
标准库定义了三种类型的字符串流。
istringstream输入流,提供读string功能
ostringstream输出流,提供写string功能
stringstream输入输出流,读写string功能
(1)反解字符串给各变量赋值
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
int n;
float f;
string strHello;
string strText = "1 3.14 hello";
istringstream s(strText);
s >> n;
s >> f;
s >> strHello;
cout << "n= " << n << endl;
cout << "f= " << f << endl;
cout << "strHello= " << strHello << endl;
return 0;
}
(2)合并不同类型的数据到字符串
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
cout << "type an int,a float and a string: ";
int i;
float f;
string stuff;
cin >> i >> f;
getline(cin, stuff);
ostringstream os;
os << "integer= " << i << endl;
os << "float= " << f << endl;
os << "string= " << stuff << endl;
string result = os.str();
cout << result << endl;
return 0;
}