目录

  • C++ 命名空间;流和文件I/O
    • 命名空间
      • 定义命名空间
      • using指令
      • 不连续的命名空间
      • 嵌套的命名空间
    • 流和文件I/O
      • 流的概念
      • C++的标准IO流
      • C++的文件IO流

C++ 命名空间;流和文件I/O

命名空间

假设这样一种情况,当一个班上有两个名叫王明的学生时,为了明确区分他们,我们在使用名字之外,不得不使用一些额外的信息,比如他们的家庭住址,或者他们父母的名字,或者大家经常做的,起一个外号:大明,小明。
C++中也会出现这样的情况。
例如,如果我们写了一个名为 xyz() 的函数,在另一个可用的库中也存在一个相同的函数 xyz()。这样,编译器就无法判断我们所使用的是哪一个 xyz() 函数。
为了解决这个问题,就引入了命名空间的概念。
命名空间是通过作为附加信息来起到区分不同库中相同名称的函数、类、变量的作用的。
其实,使用了命名空间,就相当于定义了上下文,或者说,就是定义了一个范围,这个范围内,对含有相同名称的,只使用其中一种指定的函数、类、变量。
举一个最简单的例子,在计算机系统中,一个文件夹可以有多个文件夹,而且他们不能重名,但不同文件夹中的文件就可以重名了。

定义命名空间

使用关键字namespace来定义命名空间

namespace namespace_name {// 代码声明
}

在调用带有命名空间的函数或者变量时,需要在前面加上命名空间的名称,如下:

name::code;//code指函数、类或变量

下面我们来看一个实例

#include <iostream>
using namespace std;//第一个命名空间
namespace namespace_one
{void func(){cout<<"这是第一个命名空间的函数"<<endl;}int x=1;class myclass{public:myclass(){cout<<"这是第一个命名空间的类"<<endl;}};
}//第二个命名空间
namespace namespace_two
{void func(){cout<<"这是第二个命名空间的函数"<<endl;}int x=2;class myclass{public:myclass(){cout<<"这是第二个命名空间的类"<<endl;}};
}
int main()
{namespace_one::func();// 调用第一个命名空间中的函数namespace_two::func();// 调用第二个命名空间中的函数cout<<namespace_one::x<<endl;//输出第一个命名空间的变量cout<<namespace_two::x<<endl;//输出第二个命名空间的变量namespace_one::myclass zz;//实例化第一个命名空间的类的对象namespace_two::myclass qq;//实例化第二个命名空间的类的对象return 0;
}

运行结果如下,很容易就能理解,这里不再细讲

这是第一个命名空间的函数
这是第二个命名空间的函数
1
2
这是第一个命名空间的类
这是第二个命名空间的类

using指令

我们可以使用using namespace 指令,这样在使用命名空间时就可以不用在前面加上命名空间的名称。这个指令会告诉编译器,后续的代码将使用指定的命名空间中的名称。
其实我们在刚刚接触C++时用到的using namespace std;就是使用了该指令,它告诉编译器,后续的函数,诸如coutcin都是属于std命名空间,如果我们不用该代码,那么调用这两个函数时:
std::cout<<"whatever"<<std::endl;
下面是另一个简单的实例

#include <iostream>
using namespace std;//第一个命名空间
namespace namespace_one
{void func(){cout<<"这是第一个命名空间的函数"<<endl;}int x=1;class myclass{public:myclass(){cout<<"这是第一个命名空间的类"<<endl;}};
}//第二个命名空间
namespace namespace_two
{void func(){cout<<"这是第二个命名空间的函数"<<endl;}int x=2;class myclass{public:myclass(){cout<<"这是第二个命名空间的类"<<endl;}};
}
using namespace namespace_two;
int main()
{func();// 调用第二个命名空间中的函数cout<<x<<endl;//输出第二个命名空间的变量myclass qq;
}

运行结果如下

这是第二个命名空间的函数
2
这是第二个命名空间的类

不连续的命名空间

事实上,命名空间可以定义在几个不同的部分中,即命名空间可以由几个单独定义的部分组成的,一个命名空间的各个组成部分可以分散在多个文件中。

所以,如果命名空间中的某个组成部分需要请求定义在另一个文件中的名称,则仍然需要声明该名称。下面的命名空间定义可以是定义一个新的命名空间,也可以是为已有的命名空间增加新的元素:

#include <iostream>
using namespace std;//第一个命名空间
namespace namespace_one
{void func(){cout<<"这是第一个命名空间的函数"<<endl;}int x=1;class myclass{public:myclass(){cout<<"这是第一个命名空间的类"<<endl;}};
}//第二个命名空间
namespace namespace_two
{void func(){cout<<"这是第二个命名空间的函数"<<endl;}int x=2;class myclass{public:myclass(){cout<<"这是第二个命名空间的类"<<endl;}};
}namespace namespace_one//对第一个命名空间的补充
{int addnum=123;
}int main()
{namespace_one::func();// 调用第一个命名空间中的函数namespace_two::func();// 调用第二个命名空间中的函数cout<<namespace_one::x<<endl;//输出第一个命名空间的变量cout<<namespace_two::x<<endl;//输出第二个命名空间的变量namespace_one::myclass zz;namespace_two::myclass qq;cout<<namespace_one::addnum<<endl;//输出补充的第一个命名空间的变量return 0;
}

运行结果如下

这是第一个命名空间的函数
这是第二个命名空间的函数
1
2
这是第一个命名空间的类
这是第二个命名空间的类
123

嵌套的命名空间

我们可以在一个命名空间中定义另一个命名空间,即进行命名空间的嵌套。
我们在下面的代码中,通过namespace_one::namespace_two来访问第二个命名空间的函数、变量以及类。

#include <iostream>
using namespace std;//第一个命名空间
namespace namespace_one
{void func(){cout<<"这是第一个命名空间的函数"<<endl;}int x=1;class myclass{public:myclass(){cout<<"这是第一个命名空间的类"<<endl;}};//第二个命名空间
namespace namespace_two
{void func(){cout<<"这是第二个命名空间的函数"<<endl;}int x=2;class myclass{public:myclass(){cout<<"这是第二个命名空间的类"<<endl;}};
}
}namespace namespace_one//对第一个命名空间的补充
{int addnum=123;
}int main()
{namespace_one::func();// 调用第一个命名空间中的函数namespace_one::namespace_two::func();// 调用第二个命名空间中的函数cout<<namespace_one::x<<endl;//输出第一个命名空间的变量cout<<namespace_one::namespace_two::x<<endl;//输出第二个命名空间的变量namespace_one::myclass zz;namespace_one::namespace_two::myclass qq;cout<<namespace_one::addnum<<endl;//输出补充的第一个命名空间的变量return 0;
}

运行结果

这是第一个命名空间的函数
这是第二个命名空间的函数
1
2
这是第一个命名空间的类
这是第二个命名空间的类
123

流和文件I/O

流的概念

流是什么?流即是指流动,是物质从一处向另一处流动的过程,它是信息流动的一种抽象,负责在数据的生产者和数据的消费者之间建立联系,并管理数据的流动。

C++流是指信息从外部输入设备(如键盘)向计算机内部(如内存) 输入和从内存向外部输出设备(显示器)输出的过程。这种输入输出的过程被形象的比喻为

流的特性:有序且连续,具有方向性

为了实现这种流动,C++定义了I/O标准类库,这些每个类都称为流/流类,用以完成某方面的功能。

C++的标准IO流

C++标准库提供了4个全局流对象cin、cout、cerr、clog

  • cin : 标准输入, 即数据通过键盘输入到程序中
  • cout : 标准输出,即数据从内存流向控制台(显示器)
  • cerr : 标准错误的输出
  • clog : 日志的输出

cin和cout是我们熟知的,也是最常用的。
而cout,cerr和clog都是输出流。在早期, 他们是有所区别的, 在输出的优先级有所不同
显然,cerr 级别最高,程序一旦出错,报错一定是优先级最高的。
但今天这三种输出的差别越来越小,他们都可以输出数据,不过我们还是习惯使用cout而已。
如下

#include <iostream>
#include <string>
using namespace std;//别忘了这是指定使用std的命名空间void makeout()
{string str = "你看过倚天屠龙记吗?";string str2 = "倚天屠龙记是金庸写的吗?";string str3 = "不错,倚天屠龙记的主角是张无忌。";cout << str << endl;cerr << str2 << endl;clog << str3<< endl;
}int main()
{makeout();return 0;
}

结果如下,结果表明这三个函数都能输出数据

你看过倚天屠龙记吗?
倚天屠龙记是金庸写的吗?
不错,倚天屠龙记的主角是张无忌。

关于cin,cin为缓冲流,键盘输入数据后,数据会保存在缓冲区中,当要提取时,是从缓冲区中拿。如果一次输入过多,会按顺序从缓冲区一个一个取出数据,如果输入错了,必须在回车之前修改,如果回车键按下就无法挽回了。只有把输入缓冲区中的数据取完后,才要求输入新的数据。
如下

#include <iostream>
#include <string>
using namespace std;//别忘了这是指定使用std的命名空间void makein()
{string a,b,c;cout<<"请输入一个你最喜欢的歌手"<<endl;cin>>a;cerr<<"请输入一首你最喜欢的歌曲"<<endl;cin>>b;clog<<"你想去那"<<endl;cin>>c;cout<<a<<endl;cout<<b<<endl;cout<<c<<endl;
}int main()
{makein();return 0;
}

输入和输出如下

请输入一个你最喜欢的歌手
周杰伦 七里香 北京
请输入一首你最喜欢的歌曲
你想去那
周杰伦
七里香
北京

我们可以看到,我们接连输入了三个字符串,以空格进行分隔,但之后就不需要再次输入了,因为后面的cin函数会从缓冲区内取数据。但也正因为我们输入空格时计算机会将其认为分隔符,所以cin无法读取空格符作为输入,但我们可以使用getline(cin, str)读取一行字符串

#include <iostream>
#include <string>
using namespace std;//别忘了这是指定使用std的命名空间void makein()
{string a,b,c;cout<<"请输入一个你最喜欢的歌手"<<endl;cin>>a;cerr<<"请输入一首你最喜欢的歌曲"<<endl;cin>>b;clog<<"你想去那"<<endl;cin>>c;cout<<a<<endl;cout<<b<<endl;cout<<c<<endl;
}int main()
{string a;cout<<"请输入一行字符串"<<endl;getline(cin,a);//使用getline函数读取一行字符串,他能够读取空格cout<<a<<endl;return 0;
}

输入和输出如下

请输入一行字符串
1+2=3 3+4=7
1+2=3 3+4=7

如果想输入输出自己定义的对象,则可以使用用前面讲到的重载和友元。
如下:

#include <iostream>
#include <string>
using namespace std;//别忘了这是指定使用std的命名空间
class student
{public:student(string name,int x,int y){this->name=name;this->age=x;this->height=y;}friend ostream& operator<<(ostream& cout, const student& s);
private:    int age,height;string name;
};
ostream& operator<<(ostream& cout, const student& s)
{cout<<"姓名:"<<s.name<<",年龄:"<<s.age<<",身高:"<<s.height<<endl;
}
int main()
{student ming("ming",15,180);cout<<ming<<endl;
}

结果如下:

姓名:ming,年龄:15,身高:180

C++的文件IO流

C++根据文件内容的格式,将其分为二进制文件和文本文件,对他们的读写方式也不一样。
二进制文件:字节流,读写效率高, 可读性差 (没有经过编码的二进制数据, 看起来都是乱码)
文本文件:字符流,读写效率低, 可读性好 (编码后的可读字符)

我们通过文件流对象操作文件:

  • 定义一个文件流对象:
    ifstream ifile(只输入用);
    ofstream ofile(只输出用);
    fstream iofile(既输入又输出用);
  • 使用文件流对象的成员函数打开一个磁盘文件,使得文件流对象和磁盘文件之间建立联系
  • 使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写
  • 关闭文件

下面是关于C++读写文本文件的基本知识:
文件打开模式:

  • ios::in 读
  • ios::out 写
  • ios::app 行文件末尾
  • ios::binary 二进制模式
  • ios::nocreate 打开一个文件时,如果文件不存在,不创建文件。
  • ios::noreplace 打开一个文件时,如果文件不存在,创建该文件。
  • ios::trunc 打开一个文件,然后清空内容。
  • ios::ate 打开一个文件时,将位置移动到文件尾。

文件指针位置在C++中的用法:它主要在seekg()函数中使用

  • ios::beg 文件头
  • ios::end 文件尾
  • ios::cur 当前位置

常用的错误判断方法

  • good()如果文件打开成功
  • bad()打开文件时发生错误
  • eof()到底文件尾

下面我们看几个读写文本文件的例子

#include <iostream>
#include <fstream>
using namespace std;void TextFileWrite()
{ofstream out;//定义一个只输出的ofstream对象out.open("letter.txt",ios::trunc);//iso::trunc表示在打开文件前将文件清空,//由于是写入,文件不存在则创建,创建时命名为letter.txtchar a = 'a';for (int i = 1; i <= 26; i++){if (i < 10){out<<"0"<<i<<"\t"<<a<<"\n";} else{out<<i<<"\t"<<a<<"\n";}a++;}out.close();//别忘了最后要close创建的对象
}
int main()
{TextFileWrite();return 0;
}

得到txt文件如下

01   a
02  b
03  c
04  d
05  e
06  f
07  g
08  h
09  i
10  j
11  k
12  l
13  m
14  n
15  o
16  p
17  q
18  r
19  s
20  t
21  u
22  v
23  w
24  x
25  y
26  z

加入一个读文件的函数

#include <iostream>
#include <fstream>
using namespace std;void TextFileWrite()
{ofstream out;//定义一个ofstream对象out.open("letter.txt",ios::trunc);//iso::trunc表示在打开文件前将文件清空,由于是写入,文件不存在则创建char a = 'a';for (int i = 1; i <= 26; i++){if (i < 10){out<<"0"<<i<<"\t"<<a<<"\n";} else{out<<i<<"\t"<<a<<"\n";}a++;}out.close();//别忘了最后要close创建的对象
}void TextFileRead()
{fstream in;//创建一个既可以输入也可以输出的fstream对象char ch;in.open("letter.txt",ios::in);while (!in.eof()){in>>ch;cout<<ch;//一个字符一个字符的读取,并且输出在终端cout<<'\n';}in.close();//最终一定要close
}int main()
{TextFileWrite();TextFileRead();return 0;
}

写文件操作不变,但写完后一个字符一个字符地读取文件并输出
由于输出结果太长,这里不再列出
下面我们再看一个相对比较复杂的示例,它能够读取一个文本文件的数字,并且排序后写入到另一个文件

#include <iostream>
#include <fstream>
#include <cstdlib> //qsort在此头文件中声明
using namespace std;
const int MAX_NUM = 1000;
int a[MAX_NUM]; //存放文件中读入的整数
int MyCompare(const void * e1, const void * e2)
{ //用于qsort的比较函数return *((int *)e1) - *((int *)e2);
}
int main()
{int total = 0;//读入的整数个数ifstream srcFile("in.txt",ios::in); //以文本模式打开in.txt备读if(!srcFile) { //打开失败cout << "无法打开文件" << endl;return 0;}ofstream destFile("out.txt",ios::out); //以文本模式打开out.txt备写if(!destFile) {srcFile.close(); //程序结束前不能忘记关闭以前打开过的文件cout << "无法打开文件" << endl;return 0;}int x;   while(srcFile >> x) //可以像用cin那样用ifstream对象a[total++] = x;//在数组中存储读到的整数qsort(a,total,sizeof(int),MyCompare); //排序for(int i = 0;i < total; ++i)destFile << a[i] << " "; //可以像用cout那样用ofstream对象destFile.close();srcFile.close();return 0;
}

看一个读写二进制文件的例子

#include <iostream>
#include <fstream>
using namespace std;int BinaryFileWrite()
{//创建fstream对象,可以读写nums.dat文件fstream file("test2/num.dat", ios::out | ios::binary);if (!file){cout << "无法打开文件";return 0;}//将该整数数组写入到二进制文件int buffer[ ] = {12, 2, 3, 4, 5, 6, 7, 8};int size = sizeof(buffer) / sizeof(buffer[0]);file.write(reinterpret_cast<char *>(buffer), sizeof(buffer));file.close ();return 0;
}
int BinaryFileRead()
{ifstream fin("test2/num.dat",ios::binary);int nNum;//读取二进制文件中第一个int对象的值fin.read((char*)&nNum,sizeof(int));cout<<"int = "<<nNum<<endl;//输出读到的数字fin.close();return 0;
}int main()
{BinaryFileWrite();BinaryFileRead();return 0;
}

输出如下:

int = 12

C++程序设计——十二相关推荐

  1. c++程序设计十二章第5题5 写一个程序,定义抽象基类shape由它派生出5个派生类:Circle(圆形),Square(正方形),Rectangle(矩形),Trapezoid(梯形),Tr

    写一个程序,定义抽象基类shape由它派生出5个派生类:Circle(圆形),Square(正方形),Rectangle(矩形),Trapezoid(梯形),Triangle(三角形).用虚函数分别计 ...

  2. 201771010101白玛次仁《面向对象程序设计(java)》第十二周实验总结

    实验十二  图形程序设计 实验时间 2018-11-14 学习总结: 1.Java的抽象口工具箱( Abstract WindowToolkit, AWT)包含在java.awt包中,它提供了许多用来 ...

  3. c语言压缩文本文件北京理工大学,北京理工大学C语言程序设计第十二章文件.ppt...

    北京理工大学C语言程序设计第十二章文件 2000年1月25日 北京理工大学 / 第十二章 文件 第一节 文件概述 第二节 文件的处理 第三节 文件的顺序读写操作 第四节 文件的随机读写操作 第五节 文 ...

  4. 面向对象程序设计上机练习十二(运算符重载)

    面向对象程序设计上机练习十二(运算符重载) Time Limit: 1000MS  Memory Limit: 65536KB Submit  Statistic Problem Descriptio ...

  5. Java程序设计 图形用户界面 【十二】下拉列表JComboBox

    Java程序设计 图形用户界面 [十二]下拉列表JComboBox 下拉列表JComboBox JList是以列表框的形式进行显示的 有列表又可以自己输入数据这种组件就称为下拉列表框 JComboBo ...

  6. Js高级程序设计第三版学习(十二章)

                                  Js高级程序设计第三版学习(十二章) 第十二章 DOM2和DOM3   1.样式: 访问样式属性 任何支持style特性的HTML元素都有一 ...

  7. 《C++程序设计实践》实验十二

    <C++程序设计实践>实验十二 一.课内实验题(共5小题,50分) 题型得分 50 [描述] 声明并实现一个Student类,表示学生信息.Student类包括: int类型的私有数据成员 ...

  8. 《Kotlin 程序设计》第十二章 Kotlin的多线程:协程(Coroutines)

    第十二章 Kotlin的多线程:协程(Coroutines) Kotlin 1.1 introduced coroutines, a new way of writing asynchronous, ...

  9. 程序设计第二十二题 空心三角形

    Problem Description 把一个字符三角形掏空,就能节省材料成本,减轻重量,但关键是为了追求另一种视觉效果.在设计的过程中,需要给出各种花纹的材料和大小尺寸的三角形样板,通过电脑临时做出 ...

最新文章

  1. 腾讯广告广点通API接入文档(Android)
  2. Knockout学习之前言
  3. Oracle存储过程中执行DDL操作
  4. 《基于张量网络的学习入门》学习笔记3
  5. spring注解源码分析--how does autowired works?
  6. ZZ:Business Analysis Career Path
  7. Python使用socket实现局域网传输数据(附加json数据传输及解析)以及判断socket是否断开连接
  8. linux安装RabbitMQ和amqp扩展(这个安装rabbitmq通过了但是代码测试没有通过)
  9. 【Redis】3. Redis数据类型 Hash
  10. 为何说国内云桌面已经步入成熟期
  11. 空白DirectX11应用程序
  12. 实战分享丨MySQL 与Django版本匹配相关经验
  13. VS中代码格式及样式的统一处理
  14. 七月算法机器学习笔记2--机器学习中的数学之矩阵分析与应用
  15. maven配置私服后Cannot download sources, 无法下载源码
  16. 怀念经理用鼠标线联网的1990年代当时
  17. 你写的api接口代码真是_有哪些好玩的免费的API接口?
  18. 糖尿病11年的隔壁老王
  19. FPGA—多路选择器(简单逻辑组合电路)
  20. 25个常用的防火墙规则

热门文章

  1. linux 显卡扩展坞,Ubuntu18.04上外接显卡扩展坞安装Nvidia驱动和CUDA10.0及cuDNN
  2. html制作宣传页面
  3. MySQL保姆级下载安装与配置(新手)
  4. python3.9安装wordcloud报错:ERROR: Command errored out with exit status 1: ....
  5. 电脑反应速度慢的原因及解决方法
  6. mysql集群-ndb
  7. FOC——9.三相逆变桥
  8. 关于文件文件夹加密隐藏原理的一点想法
  9. Ponds(拓扑 + 优先队列)
  10. 提高网速软件_修改几个数字就能提升网速?你应该要了解DNS的误区及正确使用方法...