初探ifstream与回车换行及类型匹配等几个问题

来源:http://blog.csdn.net/shellching/archive/2009/08/12/4438099.aspx

#include <iostream>
#include<fstream>
using namespace std;

/*本例:
	1、练习ifstream、ofstream读写文件基本方法;
	2、验证回车换行符号在文件读写中的状态和作用;
	3、验证几种判断文件末尾的方法;
	4、验证几种解决ifstream对读入类型不匹配数据的处理方法

回车与换行符:	
	字符    名称                   ASCII值    控制字符 
	'\n'    换行New line)           010     LF Line Feed)
	'\r'    回车Carriage return)    013     CR Carriage Return) 
	
杨小进 0:31 2009-8-12
*/

//创建输入文件,为练习准备
void createFilechar *fname)
{
	ofstream ofsfname);
	ofs << "aaaaa\n";
	ofs << "bbbbb\n";
	ofs << "11111\n";
	ofs << "22222\n";
	ofs.close);
}

//获取文件长度字节,会得到比输入更多的字节,因为 \n 被转换为 \r\n
int getFileLenchar *fname)
{
	ifstream ifsfname);
	ifs.seekg0, ios::end);		//移动文件指针到末尾
	int n = ifs.tellg);		//获取文件长度字节
	ifs.seekgios::beg);		//恢复指针到开始,对于接下来继续读有用
	ifs.close);
	return n;
}

//用read函数文本模式下读取文件,读到字节数小于真实文件大小,
//因为系统读 \r\n 时又转换为 \n, 只是\n被读进来了
//若是binary模式,则会读到实际文件大小的字节
void readFileReadchar *fname, ios_base::openmode om = ios_base::in)
{
	int n = getFileLenfname);
	ifstream ifsfname, om);

	char *pc = new char[n+1];
	memsetpc, 0, sizeofchar)*n+1) );
	ifs.readpc, n);
	ifom & ios_base::binary)
	{
		cout << " binary模式";
	}
	cout << " read)读取了"<< ifs.gcount) << "字节:\n";	
	cout << pc;
	delete pc;
	ifs.close);
}

//使用流提取符号读取文件,不管是何种模式,空白字符都会被 >> 略过
void readFileExtranctionchar *fname)
{
	ifstream ifsfname, ios_base::binary);
	char c;
	cout << "binary模式 >>读取:\n";
	while!ifs.eof))
	{
		ifs >> c;				
		cout << c << "_";
	}
	ifs.close);
}

//使用Get在文本模式下读取文件内容,对于"\r\n"多跳过一个字符只读进'\n',指针移到'\n'后
//若在binary模式则是按照真实数据读取'\r','\n';
void readFileGetchar *fname, ios_base::openmode om = ios_base::in)
{
	ifstream ifsfname, om);
	char c;
	ifom & ios_base::binary)
	{
		cout << " binary模式";
	}
	cout << " get)从第5字节开始读取3个字符:\n十进制:";
	ifs.seekg4, ios::beg);			
	ifs.getc);		        //读取第5字节,为'a'
	cout << intc) << "_";	
	ifs.getc);		//读取下一个字节应为13 = '\r',实际读进10 = '\n'
	cout << intc) << "_";	//若在binary模式下则是13 ='\r'
	ifs.getc);		//读取下一个字节,为'b',若是binary则是10='\n'
	cout << intc) << "_";
	ifs.close);
}

//使用Peek读取文件内容,文本模式下对于"\r\n"读进'\n';
//在binary模式下,对于"\r\n"则会读进'\r',peek始终都不会移动文件指针
void readFilePeekchar *fname, ios_base::openmode om = ios_base::in)
{
	ifstream ifsfname, om);
	//ifstream ifs3"input.txt", ios_base::binary);
	char c;
	ifom & ios_base::binary)
	{
		cout << " binary模式";
	}
	cout << " peek)读取第6、7、8字节:\n";
	ifs.seekg5, ios::beg);			
	c = ifs.peek);			//读取第6字节应为13 = '\r',实际上读进10 ='\n'
	cout << intc) << "_";	        //若在binary模式则是13 ='\r'
	ifs.seekg6, ios::beg);			
	c = ifs.peek);			//读取第7字节,为10 ='\n'
	cout << intc) << "_";
	ifs.seekg7, ios::beg);			
	c = ifs.peek);			//读取第8字节,为'b'
	cout << intc) << "_";
	ifs.close);
}

//通过eof)判断文件结束,若某行只有回车也算是一行,即使在文件尾部
void getOverEofchar *fname)
{
	ifstream ifsfname);
	string str;
	int i = 0;
	cout << " eof)判断文件结束";
	while!ifs.eof))					
	{
		getlineifs, str);				
		cout << "\n第" << ++i <<"行长度 " << str.length) << " : " << str;
	}
	ifs.close);
}

//通过good)判断文件结束,同eof,若某行只有回车也算是一行,即使在文件尾部
//因为使用了binary模式,所以getline比平时多读入一个字符'\r',忽略'\n'
void getOverGoodchar *fname)
{
	ifstream ifsfname, ios_base::binary);
	int i = 0;
	string str;
	
	cout << " binary模式 good)判断文件结束";
	whileifs.good))
	{	
		getlineifs, str);
		cout << "\n第" << ++i <<"行长度 " << str.length) << " : " << str;
		cout << " 第6字节" << intstr[5]);
	}
	ifs.close);
}

//通过getline)判断文件结束,只有回车且在文件末尾的空行不算一行
void getOverGetlinechar *fname)
{
	ifstream ifs"input.txt");
	int i = 0;
	string str;
	
	cout << " getline)判断文件结束";
	whilegetlineifs, str))			
	{	
		cout << "\n第" << ++i <<"行长度 " << str.length) << " : " << str;
	}
	ifs.close);
}

//使用ifstream的提取符号从文本文件读入某种类型数据例如float或double时,
//若遇到字符串或其它非数字符号会发生错误,造成死循环,所以需要特别处理
bool readErrchar *fname)
{ 
    cout << "不匹配数据类型处理:";
    ifstream ifsfname);      
	
	if !ifs )                            
	{
		cout << "\n打开文件 " << fname << " 失败\n";
		return false;
	}
	
    int count=0;                                            
    int  dVal, sum=0;                                        
	
    while !ifs.eof) )                               
	{
		ifs >> dVal;
		
		ififs.fail))	//错误判断,使用"!ifs"也可以,但是"ifs.bad)"不行
		{
			ifs.clear);	//清楚错误标志
			ifs.ignore1);	//忽略当前非预期字符
			continue;	//继续读取下一个
		}
		else
		{
		        cout << "\n第 " << ++count << "个数: " <<  dVal; 
			  sum += dVal;                                  
		}
	}
	
        ifs.close);            
    
        cout << "\n总共 " << count << " 个数,"
         << " 和为" << sum << endl;    
        return true;
}

int main)
{
	char fname[] = "input.txt";
	createFilefname);
	
	cout << "文件长度:" << getFileLenfname) << " 字节";
	
	cout << "\n-----------------------";
	
	readFileReadfname);
	
	cout << "\n-----------------------";
	
	readFileReadfname, ios_base::binary);
	
	cout << "\n-----------------------";
	
	readFileExtranctionfname);
	
	cout << "\n-----------------------";
	
	readFileGetfname);
	
	cout << "\n-----------------------";
	
	readFileGetfname, ios_base::binary);
	
	cout << "\n-----------------------";
	
	readFilePeekfname);
	
	cout << "\n-----------------------";
	
	readFilePeekfname, ios_base::binary);
	
	cout << "\n-----------------------";
	
	getOverEoffname);
	
	cout << "\n-----------------------";
	
	getOverGoodfname);
	
	cout << "\n-----------------------";
	
	getOverGetlinefname);
	
	/*
	总结:windows系统中使用ofstream写文本文件时系统会把'\n'转换为'\n''\r'两个字符写入文件;
	若是单写入'\r'则不会做上述转换;通常读取时会相应把'\n''\r'两个字符转换为'\n';
	对于文本中单独的'\n'和'\r'读取时不会作特别转换,作为一个字符读出;
	使用流输入符号">>"读取字符时,无论使用何种模式打开文件,都会忽略空白字符\n\r等;
	使用get和peek读取时,若在文本模式下,对于文本中的"\r\n"只是作为一个字符'\n'对待;
	get和peek,若在二进制模式下,对于文本中的"\r\n"作为两个字符对待;
	getline在文本模式下忽略"\r\n",但是在binary模式下会忽略'\n',而不会忽略'\r';
	*/
	
	cout << "\n-----------------------";
	
	readErrfname);
	
	cout << endl;
	return 0;
}

Published by

风君子

独自遨游何稽首 揭天掀地慰生平