C++之IO类,文件输入输出,string流练习题

目录
  • 前面已经在用的IO库设施
  • IO类
  • IO对象不能拷贝或赋值
    • 条件状态
    • 管理输出缓冲
  • 文件输入输出
    • fstream特有的操作
    • 文件模式
  • string流
    • stringstream特有的操作
  • 练习
    • 练习1
    • 练习2
    • 练习3
    • 练习4
    • 练习5
    • 练习6
    • 练习7
    • 练习8
    • 练习9
  • 总结

前面已经在用的IO库设施

  • istream:输入流类型,提供输入操作。
  • ostream:输出流类型,提供输出操作
  • cin:一个istream对象,从标准输入读取数据。
  • cout:一个ostream对象,向标准输出写入数据。
  • cerr:一个ostream对象,向标准错误写入消息。
  • >>运算符:用来从一个istream对象中读取输入数据。
  • <<运算符:用来向一个ostream对象中写入输出数据。
  • getline函数:从一个给定的istream对象中读取一行数据,存入到一个给定的string对象中。

IO类

  • iostream头文件:从标准流中读写数据,istream,ostream
  • fstream头文件:从文件中读写数据,ifstream,ofstream
  • sstream头文件:从字符串中读写数据,istringstream,ostringstream

IO对象不能拷贝或赋值

由于不能拷贝IO对象,因此不能将 形参 或 返回类型 设置为 流类型。进行 IO 操作的函数通常以 引用方式 传递和 返回流。读写一个IO对象会改变其状态,因此 传递和返回的引用不能用const。

  • IO对象不能存在容器里.
  • 形参和返回类型也不能是流类型。
  • 形参和返回类型一般是流的引用。
  • 读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的。

条件状态

状态 解释
strm:iostate 是一种机器无关的类型,提供了表达条件状态的完整功能
strm:badbit 用来指出流已经崩溃
strm:failbit 用来指出一个IO操作失败了
strm:eofbit 用来指出流到达了文件结束
strm:goodbit 用来指出流未处于错误状态,此值保证为零
s.eof() 若流s的eofbit置位,则返回true
s.fail() 若流s的failbit置位,则返回true
s.bad() 若流s的badbit置位,则返回true
s.good() 若流s处于有效状态,则返回true
s.clear() 将流s中所有条件状态位复位,将流的状态设置成有效,返回void
s.clear(flags) 将流s中指定的条件状态位复位,返回void
s.setstate(flags) 根据给定的标志位,将流s中对应的条件状态位置位,返回void
s.rdstate() 返回流s的当前条件状态,返回值类型为strm::iostate

上表中,strm是一种IO类型,(如istream), s是一个流对象。

管理输出缓冲

  • 每个输出流都管理一个缓冲区,用来保存程序读写的数据。文本串可能立即打印出来,也可能被操作系统保存在缓冲区内,随后再打印。
  • 刷新(即,数据真正写到输出设备或文件)缓冲区的IO操纵符
    • endl:输出一个换行符并刷新缓冲区
    • flush:刷新流,但不添加任何字符
    • ends:在缓冲区插入空字符null,然后刷新
    • unitbuf:告诉流接下来每次操作之后都要进行一次flush操作。
    • nounitbuf:回到正常的缓冲方式

文件输入输出

头文件fstream定义了三个类型来支持文件IO:

  • ifstream从一个给定文件读取数据。
  • ofstream向一个给定文件写入数据。
  • fstream可以读写给定文件。

fstream特有的操作

操作 解释
fstream fstrm; 创建一个未绑定的文件流。
fstream fstrm(s); 创建一个文件流,并打开名为s的文件,s可以是string也可以是char指针
fstream fstrm(s, mode); 与前一个构造函数类似,但按指定mode打开文件
fstrm.open(s) 打开名为s的文件,并和fstrm绑定
fstrm.close() 关闭和fstrm绑定的文件
fstrm.is_open() 返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭

上表中,fstream是头文件fstream中定义的一个类型,fstrm是一个文件流对象。

文件模式

文件模式 解释
in 以读的方式打开
out 以写的方式打开
app 每次写操作前均定位到文件末尾
ate 打开文件后立即定位到文件末尾
trunc 截断文件
binary 以二进制方式进行IO操作。

string流

头文件sstream定义了三个类型来支持内存IO:

  • istringstream从string读取数据。
  • ostringstream向string写入数据。
  • stringstream可以读写给定string。

stringstream特有的操作

操作 解释
sstream strm 定义一个未绑定的stringstream对象
sstream strm(s) 用s初始化对象
strm.str() 返回strm所保存的string的拷贝
strm.str(s) 将s拷贝到strm中,返回void

上表中sstream是头文件sstream中任意一个类型。s是一个string。

书中演示demo使用

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
typedef struct PersonInfo
{
	string name;
	vector<string> phones;
}p;
int main() {
	string line, word;
	vector<p> people;
	while (getline(cin, line))
	{
		p info;
		istringstream record(line);
		record >> info.name;
		while (record >> word)
			info.phones.push_back(word);
		people.push_back(info);
	}

	for (auto i : people)
	{
		cout << i.name << endl;
		for (auto j : i.phones)
			cout << j << "   ";
		cout << endl;
	}
	return 0;
}

练习

练习1

编写函数,接受一个istream&参数,返回值类型也是istream&。此函数须从给定流中读取数据,直至遇到文件结束标识时停止。它将读取的数据打印在标准输出上。完成这些操作后,在返回流之前,对流进行复位,使其处于有效状态。

解:

std::istream& func(std::istream &is)
{
    std::string buf;
    while (is >> buf)
        std::cout << buf << std::endl;
    is.clear();
    return is;
}

练习2

测试函数,调用参数为cin。

解:

#include <iostream>
using std::istream;
istream& func(istream &is)
{
    std::string buf;
    while (is >> buf)
        std::cout << buf << std::endl;
    is.clear();
    return is;
}
int main()
{
    istream& is = func(std::cin);
    std::cout << is.rdstate() << std::endl;
    return 0;
}

测试

#include <iostream>
#include <string>
using namespace std;
istream& f1(istream& is)
{
	int s;
	while (is >> s)
	{
		cout << s << endl;
	}
	return is;
}
istream& f2(istream& is)
{
	int s;
	while (is >> s)
	{
		cout << s << endl;
	}
	is.clear();
	return is;
}
int main()
{
	istream& is = f1(cin);
	cout << is.rdstate() << endl;
	istream& is2 = f2(cin);
	cout << is2.rdstate() << endl;
	return 0;
}

练习3

什么情况下,下面的while循环会终止?

while (cin >> i) /*  ...    */

如badbit、failbit、eofbit 的任一个被置位,那么检测流状态的条件会失败。

练习4

编写函数,以读模式打开一个文件,将其内容读入到一个string的vector中,将每一行作为一个独立的元素存于vector中。

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
void ReadFileToVec(const string& filename, vector<string>& vec)
{
	ifstream ifs(filename);
	if (ifs)
	{
		string buf;
		while (getline(ifs, buf))
			vec.push_back(buf);
	}
}

练习5

重写上面的程序,将每个单词作为一个独立的元素进行存储。

void ReadFileToVec(const string& fileName, vector<string>& vec)
{
    ifstream ifs(fileName);
    if (ifs)
    {
        string buf;
        while (ifs >> buf)
            vec.push_back(buf);
    }
}

练习6

编写程序,将来自一个文件中的行保存在一个vector中。然后使用一个istringstream从vector读取数据元素,每次读取一个单词。

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
using namespace std;
int main()
{
	//将来自一个文件的行保存到vector中
	ifstream ifs("hello.txt");
	if (!ifs)
	{
		cerr << "no data ?" << endl;
		return -1;
	}
	vector<string> vecline;
	string line;
	while(getline(ifs, line))
		vecline.push_back(line);
	ifs.close();
	//从vector读取元素,每次只读一个单词
	for (auto &s : vecline)
	{
		istringstream iss(s);
		string word;
		while (iss >> word)
			cout << word << endl;
	}
	return 0;
}

练习7

本节的程序在外层while循环中定义了istringstream对象。如果record对象定义在循环之外,你需要对程序进行怎样的修改?重写程序,将record的定义移到while循环之外,验证你设想的修改方法是否正确。

解:

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using std::vector; using std::string; using std::cin; using std::istringstream;
struct PersonInfo {
    string name;
    vector<string> phones;
};
int main()
{
    string line, word;
    vector<PersonInfo> people;
    istringstream record;
    while (getline(cin, line))
    {
        PersonInfo info;
        record.clear();
        record.str(line);
        record >> info.name;
        while (record >> word)
            info.phones.push_back(word);
        people.push_back(info);
    }
    for (auto &p : people)
    {
        std::cout << p.name << " ";
        for (auto &s : p.phones)
            std::cout << s << " ";
        std::cout << std::endl;
    }
    return 0;
}

练习8

我们为什么没有在PersonInfo中使用类内初始化?

解:

因为这里只需要聚合类就够了,所以没有必要在PersionInfo中使用类内初始化。

练习9

电话号码程序

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
using namespace std;
struct PersonInfo {
	string name;
	vector<string> phones;
};
bool valid(const string& str)
{
	return isdigit(str[0]);
}
string format(const string& str)
{
	return str.substr(0, 3) + "-" + str.substr(3, 3) + "-" + str.substr(6);
}
int main()
{
	//从文件中读取信息存入vector容器
	ifstream ifs("phone.txt");
	if (!ifs)
	{
		cerr << "no phone numbers ? " << endl;
		return -1;
	}
	vector<PersonInfo> people;
	string line, word;
	istringstream record;
	while (getline(ifs, line))
	{
		PersonInfo info;
		record.clear();
		record.str(line);
		record >> info.name;
		while (record >> word)
		{
			info.phones.push_back(word);
		}
		people.push_back(info);
	}
	//逐个验证电话号码 并 改变其格式
	for (const auto& entry : people)   //对people中的每一项
	{
		//每个循环创建的对象
		ostringstream formatted, badnums;
		//对每个数
		for (const auto& nums : entry.phones)
		{
			if (!valid(nums))
			{
				badnums << " " << nums;
				//将数的字符串形式存入badnums
			}
			else
			{
				//将格式化的字符串写入formatted
				formatted << " " << format(nums);
			}
		}
		//没有错误的数
		if (badnums.str().empty())
		{
			cout << entry.name << " "
				<< formatted.str() << endl;
		}
		else
		{
			//打印名字和错误的数
			cerr << "input error: " << entry.name
				<< " invalid number(s)" << badnums.str() << endl;
		}
	}
	return 0;
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • 浅谈C++ IO流

    1.输入输出(IO)与流的概念 输入输出(IO)是指计算机同任何外部设备之间的数据传递.常见的输入输出设备有文件.键盘.打印机.屏幕等.数据可以按记录(或称数据块)的方式传递,也可以 流的方式传递. 所谓记录,是指有着内部结构的数据块.记录内部除了有需要处理的实际数据之外,还可能包含附加信息,这些附加信息通常是对本记录数据的描述. 流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列.从流中取得数据的操作称为提取操作,而向流中添加数据的操作称

  • 带你了解C++的IO流

    目录 一.C语言的输入与输出 二.C++中流的概念 三.C++IO流 1.C++标准IO流 2. C++文件IO流 四.stringstream 总结 一.C语言的输入与输出 C语言中我们最长用到的输入输出方式就是scanf ()与printf(). scanf(): 从标准输入设备(键盘)读取数据,并将值存放在变量中. printf(): 将指定的文字/字符串输出到标准输出设备(屏幕). C语言借助了相应的缓冲区来进行输入与输出.如下图所示: 其中,输入输出缓冲区的作用:可以屏蔽掉低级I/O的

  • C++  系统IO流介绍

    目录 1.iostream标准库 2.namespace 3.C和C++输出区别 4.总结 前言: 本次讲解一个小知识点,也是最常见的一个知识点:iostream:不管编写什么程序,必然会使用到IO流交互,从细节上理解简单的IO流: 1.iostream标准库 定义:标准库所提供的IO接口,用于与用户交互: 输入流:cin 输出流:cout.cerr.clog 输出流三者的一个区别: 1.首先就是输出目标的不同,cerr主要用来输出错误信息,clog主要用来输出日志信息: 2.cerr有个最大的

  • C++语言io流处理基本操作教程示例详解

    目录 一.输入输出流对象 流对象常用的处理函数 流控制字符 二.字符流操作 sstream 三. 文件流流类 四.文件指针定位 一.输入输出流对象 cout:标准输出流 cerr:标准出凑  和cout(只是用于如果是错误时要输出的) cin  :   标准输入 流对象常用的处理函数 输出字符 put() 输入字符:get() 输出字符串:write() 输入字符串getline() char ch; cin.get(ch); cout << ch<<endl; cout.put(

  • C++学习之IO流(输入输出流)详解

    目录 介绍 基本输入.输出流 freopen 字符类的处理 介绍 流: 若干字节数据从一端到另一端我们叫做流 例如:操作文件,从程序到文件,数据的流动的操作称为流操作 流类体系 专门处理输入输出流.字符流.文件流,包含有: 流对象 流运算符 >>  << 输入/出流对象 + 流运算符 >>  <<---处理输入输出的数据 字符流对象 + 流运算符 >>   <<   ---处理字符流 文件的对象 + 流运算符 >>  &l

  • C++:IO类,文件输入输出,string流练习题

    目录 前面已经在用的IO库设施 IO类 IO对象不能拷贝或赋值 条件状态 管理输出缓冲 文件输入输出 fstream特有的操作 文件模式 string流 stringstream特有的操作 练习 练习1 练习2 练习3 练习4 练习5 练习6 练习7 练习8 练习9 总结 前面已经在用的IO库设施 istream:输入流类型,提供输入操作. ostream:输出流类型,提供输出操作 cin:一个istream对象,从标准输入读取数据. cout:一个ostream对象,向标准输出写入数据. ce

  • C++之IO类,文件输入输出,string流练习题

    目录 前面已经在用的IO库设施 IO类 IO对象不能拷贝或赋值 条件状态 管理输出缓冲 文件输入输出 fstream特有的操作 文件模式 string流 stringstream特有的操作 练习 练习1 练习2 练习3 练习4 练习5 练习6 练习7 练习8 练习9 总结 前面已经在用的IO库设施 istream:输入流类型,提供输入操作. ostream:输出流类型,提供输出操作 cin:一个istream对象,从标准输入读取数据. cout:一个ostream对象,向标准输出写入数据. ce

  • Java 1.0和Java 1.1 的IO类的比较

    Java 1.0 IO系统介绍1 Java IO版本Java库的IO分为输入/输出两部分.早期的Java 1.0版本的输入系统是InputStream及其子类,输出系统是OutputStream及其子类.后来的Java 1.1版本对IO系统进行了重新设计.输入系统是Reader及其子类,输出系统是Writer及其子类.Java1.1之所以要重新设计,主要是为了添加国际化支持(即添加了对16位Unicode码的支持).具体表现为Java 1.0的IO系统是字节流,而Java 1.1的IO系统是字符

  • Java字节流 从文件输入输出到文件过程解析

    假如需要复制一张图片,一份word,一个rar包.可以以字节流的方式,读取文件,然后输出到目标文件夹. 以复制一张4M的图片举例. 每次读一个字节: ch = (char)System.in.read(); //读入一个字符,返回读到的字节的int表示方式,读到末尾返回-1 复制时候一个字节一个字节的读取.写入,这样是很慢的.设置一个用来缓冲的字符数组,会让复制的过程快很多(每次读入的字节变多). 方便阅读,类的名称用中文描述 import java.io.*; public class 字节流

  • JAVA.io读写文件方式汇总

    一.Java把这些不同来源和目标的数据都统一抽象为数据流. Java语言的输入输出功能是十分强大而灵活的. 在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流. 这里介绍几种读写文件的方式 二.InputStream.OutputStream(字节流) //读取文件(字节流) InputStream in = new FileInputStream("d:\\1.txt"); //写入相应的文件

  • Java使用NIO优化IO实现文件上传下载功能

    目录 1 NIO的一些基础预备知识 2 NIO为何较传统的io速度较快 3 NIO实战上传下载 3.1 url下载文件 3.2 通过NIO上传文件 1 NIO的一些基础预备知识 Java中IO流类的体系中BIO与NIO:https://blog.csdn.net/ZGL_cyy/article/details/104326458Java IO体系与NIO和BIO体系面试题 :https://blog.csdn.net/ZGL_cyy/article/details/122836368为什么使用N

  • Java IO 之文件读写简单实例

    Java IO 之文件读写简单实例 1.文件读 public class ReadFromFile { /** * 以字节为单位读取文件,常用于读二进制文件,如图片.声音.影像等文件. */ public static void readFileByBytes(String fileName) { File file = new File(fileName); InputStream in = null; try { System.out.println("以字节为单位读取文件内容,一次读一个字

  • C#之IO读写文件方法封装代码

    具体不做详细介绍了,直接上代码 /// <summary> /// 功能:FileStream文件流读取文件 /// </summary> /// <param name="filePath">参数:文件路径</param> /// <returns>返回值:StreamReader对象</returns> public static StreamReader ReadFileByFs(string filePat

  • Java实现文件和base64流的相互转换功能示例

    本文实例讲述了Java实现文件和base64流的相互转换功能.分享给大家供大家参考,具体如下: import java.io.FileInputStream; import java.io.FileOutputStream; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; /** * 文件与base64的互相转换操作 */ public class testFile { public static void main(S

  • java io读取文件操作代码实例

    这篇文章主要介绍了java io读取文件操作代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 主要分为字节读取和字符读取,字节读取可以一个一个读取和字节数组读取,字符读取同样之,字符读取适合文本读取,字节读取皆可以 这里直接上代码,读取文件的9个小demo package com.io; import org.junit.Test; import java.io.*; public class FileTest { //1.字节流字节一个

随机推荐