C++的标准类库被修订了两次,有两个标准 C92和C99,这两个库现在都在并行使用,用 .h 包含的是c92 ,不带 .h 的是c99的头文件,对于普通用户来说这两者没有什么区别,区别是在内部函数的具体实现上。旧的C++头文件是官方明确反对使用的,但旧的C头文件则没有(以保持对C的兼容性)。据说从 Visual C++ .NET 2003 开始,移除了旧的 iostream 库。其实编译器制造商不会停止对客户现有软件提供支持,所以在可以预计的将来,旧的C++头文件还会嚣张一段时间。如果能明白字符串头文件的使用,举一反三,其他的也差不多会用了:
<string.h>是旧的C/C++头文件,对应的是基于char*的字符串处理函数;
<string>是包装了std的C++头文件,对应的是新的strng类;
<cstring>是对应旧的C头文件的std版本。
如果编译器都同时支持< iostream >和< iostream.h >,那使用#include < iostream >,得到的是置于名字空间std下的iostream库的元素;如果使用#include < iostream.h >,得到的是置于全局空间的同样的元素。在全局空间获取元素会导致名字冲突,而设计名字空间的初衷正是用来避免这种名字冲突的发生。
出现的问题时:
vc7.1<fstream> 已经不支持 filebuf::sh_read等关键字,不知在vc7下若要用文件流来对文件进行非独占读和写操作该如何实现?
而:
vc6.0中的iostream.h <fstream.h>
filebuf::sh_read
filebuf::sh_write
filebuf::sh_note
filebuf::sh_openprot
无论自己是用vc6或者vc7的IDE
当用到标准的输入输出和文件流时都是:
include<iostream>
include<fstream>
using namespace std;
有两种用法:
A:
include<iostream.h>
include<fstream.h>
B:
include<iostream>
include<fstream>
A是标准用法,B是老式用法。
如果用了<iostream>,则一定要引入命名空间,即"using namespace std;".
如果用了<iostream.h>,则不那引入命名空间,否则会引起编译错误,提示
找不到命名空间,例程如下:
//情况一:使用<iostream>和命名空间
#include <iostream>
using namespace std;
int main()
{
cout<<"<iostream> need to use namespace std!/n";
return 0;
}
输出:
<iostream> need to use namespace std!
Press any key to continue
//情况二:使用<iostream.h>,不引入命名空间
#include <iostream.h>
//using namespace std;
int main()
{
cout<<"<iostream> need to use namespace std!/n";
return 0;
}
输出:
<iostream> need to use namespace std!
Press any key to continue
//情况三:使用<iostream.h>,引入命名空间,这时候编译出错
#include <iostream.h>
using namespace std;
int main()
{
cout<<"<iostream> need to use namespace std!/n";
return 0;
}
编译错误信息:
error C2871: 'std' : does not exist or is not a namespace
标准 C++ 库和以前的运行时库之间的主要差异在于 iostream 库。iostream 实现的具体细节已经更改,如果想链接标准 C++ 库,可能有必要重写代码中使用 iostream 的部分。
必须移除任何包含在代码中的旧 iostream 头文件(fstream.h、iomanip.h、ios.h、iostream.h、istream.h、ostream.h、streamb.h 和 strstrea.h),并添加一个或多个新的标准 C++ iostream 头文件(<fstream>、<iomanip>、<ios>、<iosfwd>、<iostream>、<istream>、<ostream>、<sstream>、<streambuf> 和 <strstream>,所有头文件都没有 .h 扩展名)。
下表描述新的标准 C++ iostream 库不同于旧 iostream 库的行为。
在新的标准 C++ iostream 库中:
- open 函数不采用第三个参数(保护参数)。
- 无法从文件句柄创建流。
- 除了几个例外,新的标准 C++ 库中的所有名称都在 std 命名空间中。有关更多信息,请参见使用 C++ 库头。
- 单独用 ios::out 标志无法打开 ofstream 对象。ios::out 标志必须在逻辑 OR 中和另一个 ios 枚举数组合;比如,和 ios::in 或 ios::app 组合。
- 因为设置了 eofbit 状态,到达文件尾后 ios::good 不再返回非零值。
- 除非知道当前没有设置基标志,否则 ios::setf(_IFlags) 不应和 ios::dec、ios::oct 或 ios::hex 的标志值一起使用。格式化的输入/输出函数和运算符假定只设置了一个基。改用 ios_base。例如,setf( ios_base::oct, ios_base::basefield ) 清除所有基信息并将基设置成八进制。
- ios::unsetf 返回 void 而不是以前的值。
- 若出现错误,istream::get( char& _Rch ) 不分配给 Rch。
- istream::get( char* _Pch, int _Ncount, char _Delim ) 有三点不同:
- 没读取任何内容时设置 failbit。
- 提取的字符后总是存储一个 eos(与结果无关)。
- 值为 -1 时 _Ncount 是一个错误。
- 具有无效参数的 istream::seekg 不设置 failbit。
- 返回类型 streampos 是具有重载运算符的类。在返回 streampos 值(比如 istream::tellg、ostream::tellp、strstreambuf::seekoff 和 strstreambuf::seekpos)的函数中,应将返回值转换成所需的类型:streamoff、fpos_t 或 mbstate_t。
- strstreambuf::strstreambuf( _Falloc, _Ffree ) 中的第一个函数参数采用 size_t 参数而不是 long。
- filebuf、fstream ifstream 和 ofstream 的 attach 成员函数
- filebuf、fstream ifstream 和 ofstream 的 fd 成员函数
- filebuf::openprot
- filebuf::setmode
- ios::bitalloc
- ios::nocreate
- ios::noreplace
- ios::sync_with_stdio
- streambuf::out_waiting
- streambuf::setbuf(相同的行为使用 rdbuf -> pubsetbuf)
<string.h>
<string.h>是C版本的头文件,包含比如strcpy、strcat之类的字符串处理函数。string.h中不包含“string”这个数据类型,只有一些常用字符串处理函数。如果试图使用string定义变量,会出现“string”未定义的错误。在使用string.h时不需要使用命名空间。
#include <string.h>
using namespace std;
class CSimpleClass
{
public:
void InitConst();
CSimpleClass(int i);
virtual ~CSimpleClass();
const int m_cstI;
string strSample; //error!string未定义
};
<cstring>
在C++标准化(1998年)过程中,为了兼容以前,标准化组织将所有这些文件都进行了新的定义,加入到了标准库中,加入后的文件名就新增了一个"c"前缀并且去掉了.h的后缀名,所以string.h头文件成了cstring头文件。但是其实现却是相同的或是兼容以前的,这就是<cstring>的来源,不要觉得又多了一个东西。相当于标准库组织给它盖了个章,说“你也是我的标准程序库的一份子了”。cstring.h中同样不包含“string”这个数据类型,如果试图使用string定义变量,会出现“string”未定义的错误。在使用cstring时需要使用命名空间。
#include <cstring>
using namespace std;
class CSimpleClass
{
public:
void InitConst();
CSimpleClass(int i);
virtual ~CSimpleClass();
const int m_cstI;
string strSample; //error!string未定义
};
<string>
<string>是C++标准定义的头文件,它定义了一个string的字符串类,里面包含了string类的各种操作,如s.size(), s.erase(), s.insert()等。但<string>又包含了老的C版本的字符串操作如strcpy、strcat等,这就相当于,在<string>的文件中除了定义自己的string类之外,还加了一个#include<string.h>一句包含了C版本的字符串操作。故包含string时需要使用命名空间,并且可以使用数据类型string定义变量。
#include <string>
using namespace std;
class CSimpleClass
{
public:
void InitConst();
CSimpleClass(int i);
virtual ~CSimpleClass();
const int m_cstI;
string strSample; //正确
};
<CString>
在MFC中,还有CString类,它与cstring是有本质区别的,前者是类名,使用时包含头文件afx.h,后者是文件名,两者实现的方法也大相径庭。
CString应该包含的头文件:<atlstr.h>(控制台)或<afxstr.h>(MFC),一般在使用MFC As Shared Dll之后不需要包含
1、<atlstr.h>
非MFC版本,控制台程序就用这个
<afx.h>、<afxcoll.h>都可以。//要在项目->属性->常规里设置为使用MFC(动/静).
2、<afxstr.h>// only be used in MFC projects.
MFC版本,需要链接MFC的dll或静态库。网上很多人说要包含<afx.h>,<afx.h>包含的东西就比较多了CObject及其派生类,还有文件类、时间类、异常类、字符串类等等(700多行的位置包含了afxstr.h),如果仅仅需要cstring的话,包含<afxstr.h>就够了。