c++输入输出流和C++工具-lesson15


前言

之前的内容已经将c++的基本只是讲完了,现在学习一些c++编程的其他知识,主要是输入输出、异常处理、命名空间等等,这两个内容很有意思,是前面基础内容的应用,主要是类库的使用,C++和硬件打交道等等,具有代表性。


一、输入和输出–具体机制需要了解操作系统和它的交互

1.含义和分类

从操作系统的角度来看,每一个和主机相连的输入和输出设备都看作一个文件,因此键盘是输入文件、显示器和打印机是输出文件,磁盘即使输入文件也是输出文件,程序的输入是将数据传送给程序,程序的输出是将程序中的数据传送给输出文件。
C++的输入和输出包括3个分类:
①标准I/O:键盘、显示器
②文件I/O:以外存(磁盘和光盘、u盘)
③串I/O:以内存中指定空间进行输入和输出

2.C++对C输入输出的扩展

以前C也有I/O,如printf、scanf,但是输入错误时也能输出,类型是不安全的,C++保留了C的输入和输出机制,而且进行扩展,
①凡是输入数据类型是不正确的编译都不能通过,因此C++的I/O操作时类型安全(type safe)
②C中printf、sacnf输入和输出只能是标准类型的数据(int,float,double、char等等),用户的类型(数组、结构体、类)的数据不能输出,C++提供一套面向对象的输入输出系统
③c++的类机制使它建立了一套可扩展的I/O系统,这里的理解就是重载不知道对不对?),系统根据不同的数据类型,自动选择对应的方法,而且方法名称使一样的,提高代码的重用性;
④c++通过I/O的类库来实现丰富的I/O功能,不像c那样printf,但是也注定了使用起来比较复杂,如C++采用类对象实现输入和输出,C采用函数实现输入和输出。

3.C++的输入输出流

①前言
这涉及到输入输出流,参考C语言中的printf(内部的核心是putchar)和scanf(getchar),这个地方你替换成cout和cin即可,内部的核心是下面的这张图,这个地方有几点说明一下:
1)缓冲区中的数据就是流,当遇到cin>>a>>b>>…这条语句时;
2)键盘输入的数据会先放入输入缓冲区中,当输入回车键时,这句话cin>>a>>b>>…才起作用,从输入缓冲区将数据提取到变量a、b、…中,看起来cin就是设备和输入缓冲区中数据流入程序的输入流;
3)当遇到cout<<…<<endl时,现将…输出到输出缓冲区中,遇到endl时,将缓冲区的数据输出到设备显示,看起来cout就是流向输出缓冲区以及设备的数据流;
4)以上的一切都是建立在cin和cout定义的情况下,后面我们知道cin和cout是系统定义的流类(I/O类)的对象,在定义的时候有一个参数就是设备,这样,cin和cout就和设备以及设备输入输出缓冲区联起来了。
在这里插入图片描述
②流库
前言4)中说了流类,许多流类在一起变成流库,这里所说的流类库要和.lib区分开,源文件也可以是流类库,.lib只是一种形式而已,c++会提供这个类库,C++中I/O库中的类被称为流类,这些类都有两个基类:ios类和streambuf类,其他的类都是从中两个基类继承过来的,ios类是输入输出操作在用户端的接口,为用户输入和输出提供服务,streambuf输入输出缓冲区的类,对缓冲区做操作的,是底层物理端,我们一般只关心ios类。
ios类直接派生:
—>istream类(输入流类)
—>ostream类(输出流类)
—>fstreambase类(文件流类基类)—>ifstream(输入文件流类)、ofstream(输出文件流类)和fstream(输入输出文件流类)
—>strstreambase类(字符串类基类)—>istrstream(输入串流类)、ostrstream(输出串流类)和strstream(输入输出串流类)
在这里插入图片描述

流库接口–头文件
我们要用到流库中的类时,需要include他的头文件,编译的时候将.lib链接进程序中生成.exe,流类库是很大,包括各类.h文件和.lib或者源文件,当要用到相应的流类时,直接include头文件(流库的接口)即可,有很多头文件,常用的有以下头文件:
iostream:包含了对输入输出流进行操作所需的基本信息
fstream:用于用户管理的文件I/O操作
strstream:用于字符串流I/O
stdiostream:不知道!
iomanip:在使用格式化I/O时应包含此文件

一些重要的流对象–针对iostream头文件中
iostream头文件声明的类有很多ios、istream、ostream等等,比较全,因此大多数C++程序都包含iostream,同时在这个头文件中还定义了4种流对象,如下图所示:
在这里插入图片描述
上面4个流对象是这么定义的:

//定义cout为ostream_withassign流类对象,把标准输出设备stdout做参数,
//c语言中printf底层也是stdout为参数,这样
//cout就和标准输出设备(显示器)联系起来,如果有cout << 3,就会在显示器的
//屏幕上输出3,这是精髓!!!!!!
ostream_withassign cout(stdin)

如果在程序中include iostream头文件,那么在程序允许时,会自动建立以上全局的4个标准流对象,自然就会分别执行4个流对象的构造函数,把流和标准设备联系起来。

一些重要的重载运算符–针对iostream头文件中
我们都知道<<和>>在c++中本来是左移和右移运算符,由于在iostream头文件中对他们进行了重载,使他们的能用作数据的输入和输出运算符,所以在程序中必须#include 指令把iostream包含到程序中,在istream和ostream类中(都在iostream头文件中声明),分别有一组成员函数对位移运算符进行重载,以便可以输出和输入各种数据类型:

ostream operator  << (int);//用于向输出流插入一个int数据
ostream operator  << (float);//用于向输出流插入一个float数据
ostream operator  << (char);//用于向输出流插入一个char数据
ostream operator  << (char *);//用于向输出流插入一个字符串数据
......

如果在程序中有以下的表达式:

cout << "C++";//相当于调用cout.operator << ("C++");自动调用上面最后
//一个运算符重载函数,将字符串插入到cout中,
//同时此函数的返回值使cout。

同理cin,如果想要输出自己定义的数据类型,则需要进行"<<“和”>>"运算符重载,因为iostream头文件中的可能不适合你。

4.C++的输入输出流分类:流在这里有流类和流对象的意思

①标准输入输出流:标准输入输出流是标准输入设备(键盘)和流向标准输出设备(显示器)的数据。
1)标准输出流(cout、cerr、clog)
有4点需要注意:a)输入格式化有两种方式:控制符和类成员函数方法:b)用流类的成员函数put输出单个字符;c) c++里面保留了putchar函数(但是c语言是在stdio.h头文件中定义的),他在iostream头文件中定义,而且是个普通函数,不用使用对象.putchar()的方式调用,直接putchar();d)ostream类的成员函数在他的对象中都可以调用,cout只是他的对象而已;
e)cout << ‘I’ << 10 << “c++” << f;这一句话其实调用了4次<<运算符重载函数,即cout << ‘I’ 、cout << 10 、cout << “c++”、cout << f

2)标准输入流(cin)
注意istream类的成员函数;(用的时候在去查一查)

②文件I/O
常用的文件包括程序文件(.c、.h、.obj、.exe)和数据文件,这里讲的文件主要是数据文件。根据的文件的组织形式,分为ASCII和二进制文件。

从之前的文件我们知道,在iostream头文件中定义了cout和cin流对象,所以用户不用自己定义,但是没有定义文件流对象(是通过文件流类定义的),需要用户自己定义,此外,对磁盘文件(光盘文件、u盘文件也是一样的,这里用磁盘文件做讲解)的操作是通过文件流对象(而不是cin和cout)实现的。

用法:
1)首先定义一个文件流对象:

//定义一个输出文件流对象
ofstream outfile;
//定义一个输入文件流对象
ifstream infile;
//定义一个输入输出文件流对象
fstream iofile;

2)使实际的文件和文件流对象建立关联:

//第一种方式:定义一个输出文件流对象,之后建立关联
ofstream outfile;
outfile.open("f1.dat", ios::out);

//第二种方式:定义一个输出文件流对象直接使用参数调用构造函数
ofstream outfile("f1.dat", ios::out);

3)不用对这个文件操作了,直接关闭,而且这个对象可以重新和别的文件建立关联:

//和file1解除关联
outfile.close();
//重新和file2建立关联
outfile.open("f2.dat", ios::out);

③字符串I/O
1)我们要注意,在严格意义上讲,字符串I/O不属于输入输出,称为读写比较合适,,因为输入输出一般实指计算机内存和计算机外的文件(外部设备也被视为文件),这里主要C++字符串流采用C++流的输入输出机制,所以被划分到这里了,而且建立关联的不是文件,是内存中的数组,不用调用成员函数open和close。

2)使用方法

char c[50];//用户定义的字符数组
ostrstream strout(c, 30);//建立暑促字符串流,与数组c建立关联,缓冲区长30

二、C++工具(新增功能)

1.前言

在c++的发展过程中,有些c++编译系统根据实际需要,增加了一些功能,作为附加工具来使用,主要有模板(函数模板和类模板)、异常处理、命名空间和运行时类型识别(这个不知道是啥??),后来c++标准觉着挺好,就纳入新的标准,建议其他c++编译系统也实现,因此慢慢变成了c++新的功能,由于他们最初的目的是作为附加工具的,不起到代码的功能,所以一直叫做c++工具了。

2.异常处理

1)原理是什么
程序的错误分为两类:语法错误和运行错误
异常包括:运行错误和不符合预期的情况

2)语法

throw 语句的形式为:
throw 表达式;

try-catch块结构:
try
{
被检查的语句
}
//catch异常处理快或者叫catch异常处理器
catch(异常信息类型1[变量名1])
{
进行异常处理的语句
}
catch(异常信息类型2[变量名2])
{
进行异常处理的语句
}
catch(异常信息类型3[变量名3])
{
进行异常处理的语句
}
.......

//说明:
//1、被检测部分必须放在try块中;
//2、try-catch必须紧紧连在一起;
//3、可以只有try没有catch,一个try-catch结构只能有一个try和多个catch;
//4、catch(异常信息类型),可以是标准类型,也可以是类和结构体类型;
//5、catch(异常信息类型 变量名),即传出异常信息类型,也传出数值;
//6、catch(...),没有异常信息类型,而用了删节符...,表示可以捕获任何异常类型异常信息;
//7、try-catch和throw可以出现在同一个函数中,也可以不在一个函数中,就近的没有就往上传;
//8、throw后面可以没有表达式,如果是在catch中,则表示将捕获的异常信息再次原样抛出;
//9、如果找了一圈都没有,系统自动调用系统函数terminate,是程序停止。

3)执行过程是什么

void main()
{
  float sum = 0;
  try
  {
    fun(0, 52);
    cout << "hello "<< endl;
  }
  catch(float m)
  {
  	cout << "num = " << m << endl;
  }
  cout << "ok "<< endl;
}

float fun(float a, float b)
{
	if(a == 0)
	{
		throw a;
	}
	float s;
	s = a + b;
}

在try中调用函数fun,a = 0,直接throw a ,后面的s = a + b等不执行,回到main中,立即离开try块,系统直接寻找和double 匹配的catch子句,执行cout << "num = " << m << endl;之后执行cout << "ok "<< endl;不会执行cout << "hello "<< endl;语句。

4)函数的声明有什么不同
为了便于阅读,使用户在看程序时就能知道所用的函数是否会抛出异常信息以及异常信息的类型,C++允许在说明函数的时候列出抛出的类型,相当于对以前的函数进行改造,在接口处表明函数信息。,而且声明和定义都要表明,以下时3种情况:

//第一种情况:
float fun(float a, float b) throw(double);//只能抛出来double类型
float fun(float a, float b) throw(double, int, char);//可以抛出double、int、char类型
//第二种情况:
float fun(float a, float b); //可以抛出任何类型
//第三种情况:
float fun(float a, float b) throw(); //即使有throw语句,遇到但不执行,程序非正常终止,没有玩过!!!!

5)异常处理中析构函数如何处理
在离开包含throw函数以前,自动调用局部对象的构造函数,进行对象离开作用域的后续处理工作。–这句话好好理解一下

6)例程代码

#include "stdafx.h"
#include <iostream>
#include <cmath>
using namespace std;

//求解一元二次方程ax2 + bx + c = 0的实根,如果方程没有实根,则输出有关警告信息

//计算平方根的函数,b2 - 4ac < 0,表示没有实根,抛出异常
float calc_root(float a, float b, float c) throw(float)
{
	if((b * b - 4 * a * c) < 0)
	{
		throw a;
	}
	return sqrt(b * b - 4 * a * c);
}

int main(int argc, char* argv[])
{
	float a = 0.0f, b = 0.0f, c = 0.0f, root = 0.0f;
	cout << "please intput a = " << endl;
	cin >> a;
	cout << "please intput b = " << endl;
	cin >> b;
	cout << "please intput c = " << endl;
	cin >> c;

	try
	{
		root = calc_root(a, b, c);
	}
	//匹配异常,接收异常信息类型和数值
	catch(float r)
	{
		cout << "parents is error!" << endl;
		cout << "r = " << r << endl;
	}

	return 0;
}

3.命名空间——是在头文件中还是源文件中呢?这个以后看到了在更新

1)为什么需要命名空间
c语言定义了3个层次的作用域:文件(编译单元)、函数和符合语句,C++又引入了类作用域,同一个作用域内不应该有两个及以上的同名实体(包括函数、变量、类、结构体、模板、枚举等等),凡是会产生编译二义性的,因此命名空间主要是解决编译的时候二义性,或者是同名冲突。

2)命名空间里面可以放什么
可以放的东西很多,可以放:
变量(可以带初始化)
常量
函数(可以是定义或声明)
结构体

模板
命名空间(嵌套命名空间)
不能放的东西:
#include 指令

3)如何使用命名空间里面的成员

//直接使用命名空间+作用域分辨符+成员名
1、命名空间名::命名空间成员名
//可以简化命名空间名
2、给命名空间取一个别名namespace TV = Television
//在using语句所在的作用域内,可以之间使用命名空间成员名,缺点,一个using只能一个
3、使用using 命名空间名::命名空间成员名
//但是也要考虑到同时使用两个空间,会不会有同名的函数或者类
4、使用using 命名空间名

4)无名的命名空间和标准命名空间

1、无名的命名空间
namespace 
{
	void fun()
	{
		cout << "ok" << endl;
	}
}
//这里的无名命名空间中的成员不能被其他文件应勇,只能在本文件中使用,类似于c语
//言中的static,但是又要注意和全局变量的区别,全局变量其实是全局命名空间,
//独立于所有命名空间之外,他不需要namespace声明,实际上是由系统隐式声明的???
2、标准命名空间
//标准头文件中(如iostream,还有其他标准头文件)函数、类、对象和类模板都是
//在命名空间中std定义的,所有库中的头文件都有下面这样的格式,所以我们在加了头
//文件之后,会加上这么一句using namespace std;
头文件iostream.h中
namespace std
{
...
}

头文件cmath.h中
namespace std
{
...
}

头文件cstring.h中
namespace std
{
...
}
注意所有的标准库公用一个命名空间标识符,他们不怕重名,因为他们都是一个团队做的,不会出现重名的现象。

renshi.h


#ifndef RENSHI_H
#define RENSHI_H
#include <iostream>
using namespace std;

namespace renshi
{
	class Student
	{
	public:
		Student(int nu, char* na, int ag, char* ad)
		{
			num = nu;
			name = na;
			age = ag;
			addr = ad;
		}

		void get_date()
		{
			cout << "num:" << num << " name:" << name << " age:" << age << " addr:" << addr << endl;
		}

	private:
		int num;
		char* name;
		int age;
		char* addr;
	};
}

#endif

jiaowu.h


#ifndef JIAOWU_H
#define JIAOWU_H
#include <iostream>
using namespace std;

namespace jiaowu
{
	class Student
	{
	public:
		Student(int nu, char* na, char se, int sc)
		{
			num = nu;
			name = na;
			sex = se;
			score = sc;
		}

		void get_date()
		{
			cout << "num:" << num << " name:" << name << " sex:" << sex << " score:" << score << endl;
		}

	private:
		int num;
		char* name;
		char sex;
		int score;
	};
}

#endif

main.c

//#include "renshi.h"
//#include "jiaowu.h"
//
//int main(int argc, char* argv[])
//{
//	renshi::Student stud1(110, "yy", 30, "beijing");
//	jiaowu::Student stud2(110, "yy", 'N', 100);
//	
//	stud1.get_date();
//	stud2.get_date();
//	
//	return 0;
//}

#include "renshi.h"
#include "jiaowu.h"
using namespace renshi;

int main(int argc, char* argv[])
{
	Student stud1(110, "yy", 30, "beijing");
	jiaowu::Student stud2(110, "yy", 'N', 100);
	
	stud1.get_date();
	stud2.get_date();
	
	return 0;
}

4.C++使用函数库的方法

c++保留继承c语言的函数库,同时c++其实还是对它进行了重新整理,如你想用某个函数,就必须包含某个头文件和lib文件,有两种方法:
①C语言头文件+C语言lib文件

②c++头文件 + c++lib文件(个人觉得是它把C语言中的库函数用c++的方法重新写了一遍)


总结

这一节的内容是具体的应用,多多练习。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值