►泛型编程
►面向过程PO(procedure oriented)、面向对象OO(object oriented)、泛型编程GP(generic programming)是三种重用的 编程方法。
►早期的C++语言泛型编程思想仅仅体现于简单的模板技术,之后的 标准模板库STL(standard template library)是泛型编程思想的实 际体现和具体实现。
►面向过程是通过将代码段封装在一个函数中,通过函数调用来实现 目标代码的重用。
►面向对象是通过类的继承来实现对象目标代码的重用。
如果需要编写一个可用于不同数据类型的算法,可以采用的方法有:
►①面向过程的方法:对源代码进行复制和修改,生成不同数据类型 版本的算法函数,调用时需要对数据类型进行人工的判断;
►②面向对象的方法:在一个类中,编写多个同名函数,它们的算法 一致,但是所处理数据的类型不同,当然函数的参数类型也不同, 通过函数重载来自动调用对应数据类型版本的函数。
显然,以上两种方法都需编写多个相同算法的不同函数,不能做到 代码真正的重用。它们二者之间的主要差别,只是调用方便与否。 如果采用泛型编程,就可以实现源代码级的重用。
泛型(generic)是一种允许一个数据取不同类型的技术,与操作 对象数据类型独立的算法称为泛型算法,独立于任何特定类型的编 程方法称为泛型编程。
►模板是泛型编程的基础。泛型编程关注于产生通用的软件组件,让 这些组件在不同的应用场合都能很容易地重用。在C++中,类模板 和函数模板是进行泛型编程极为有效的机制。
#include <iostream>
using namespace std;
template <class T> //声明一个模板,虚拟类型名为T
class Compare //类模板名为Compare
{
public :
Compare(T a,T b){x=a;y=b;}
T max(){return (x>y)?x:y;}
T min(){return (x<y)?x:y;}
private :
T x,y;
};
int main()
{
Compare<int> a(4,7);
cout<<"a:max="<<a.max()<<",min="<<a.min()<<endl;
return 0;
}
数组的类模板:
#include <iostream>
using namespace std;
template <class T>
class Array
{
public:
Array(int c){arr = new T[c];} //构造函数,返回一个长度为c的数组的地址
T& operator[](int i){return arr[i];} //重载中括号的使用,输入i,返回a[i]
private:
T *arr;
};
int main()
{
int i;
Array<int> array(5); //定义整形数组array
for (i=0; i<5;i++) cin>>array[i];//输入数组各个元素的值
for (i = 0; i < 5; i++)//输出数组各个元素的值
cout <<"array["<<i<<"]:"<<array[i]<<" ";
cout<<endl;
return 0;
}
一、库文件
►C++标准库由三组库构成:
►(1)C库:由C标准库扩展而来,强调结构、函数和过程,不支持 面向对象技术。
►(2)C++库:增加了面向对象的库,包含了具有关键功能的类。
►(3)标准模板库(STL):高效的C++程序库。该库包含了诸多在 计算机科学领域里所常用的基本数据结构和基本算法。
►以上库文件都被定义在namespace std中。
►C++库可以不规定头文件的扩展名。 即 .h math.h -> cmath
►1. C标准库
►1):<cmath> 提供给了22个不同的数学函数,如abs()、sqrt()、 exp()等。
►2):<cstdlib> 提供了常用的数学函数,3个特殊函数和2个常量。
exit() :退出程序,清除静态对象。 abort() :强制退出程序。 atexit() :将一个函数作为参数并在程序退出时调用。 EXIT_SUCCESS :程序已经正常完成。 EXIT_FAULURE :程序正常结束。
►3)<cassert> 定义了一个函数assert,用来测试一个条件,并在 条件为假时强制程序退出。通常用来判断内存分配是否成功。
►4):<cctype> 提供了确定字符类型的功能。可以判断一个字符是 否为数字字符、图形字符、小写、大写或空格,并可以将字符进行 大小写转换。
►5):<cerrno> 定义了一个变量,用它可以确定程序中发生的错误 的类型。
►2. C++类库
1):<string> 支持字符串处理的类库。
2):<complex> 提供了复数的表示和算法。 ► float_complex类 ► double_conmplex类 ► long_double_complex
3):<ios> 定义了I/O流类的虚基类ios,通常不直接用它。
4):<iostream> 标准I/O流类库,提供了cin、cout等全局对象类 来支持输入输出功能。
5):<istream> 输入流类库。
6):<ostream> 输出流类库。
7):<fstream> 读写文件的类。
►3. 标准模板库STL ►在标准库中,容器、迭代器、算法和数值操作合称为标准模板库。 ►STL被组织为以下13个头文件:
<iterator> | <functional> | <vector> | <deque> |
<list> | <queue> | <stack> | <set> |
<map> | <algorithm> | <numeric> | <memory> |
<utility> |
►几乎所有的标准模板库代码都采用了类模板和函数模板的形式,因 此相比于传统的由函数和类组成的库来说STL提供了更好的代码重 用。
<algorithm>:提供给了通用的算数算法和STL的一般算法。
► sort :以升序重新排列范围内的元素。
► swap :交换存储在两个对象中的值。
► max_element :指出序列中最大的元素。
► find :对范围内的元素进行查找 。
► copy :复制序列。
► replace :将范围内的所有等于 old_value 的元素都用 new_value 替代。
<numeric> 提供了四类对序列进行数字处理的算法:
► accumulate():累加
► product():内乘
► Partial_sum():部分和
► adjacent_difference():邻接差值
二、字符串流
►字符串流是以内存中的string对象或字符数组(C风格字符串)为输 入输出的对象,将数据输出到内存中的字符串存储区域,或者从字 符串存储区域读入数据。
►字符串流的作用是利用输入输出操作方式将各种类型的数据转换成 字符序列,或者相反。由于计算机物理的或逻辑的设备大多数能处 理的数据是字符序列(或字节序列),因此字符串流就是程序数据 与设备进行数据交换重要的桥梁。
字符串流类有(istringstream、ostringstream、stringstream)和 (istrstream、ostrstream、strstream)两种。前一种以C++ string 串对象作为字符串,定义在头文件<sstream>中;后一种以字符数 组作为字符串(即C风格字符串),定义在头文件<strstream>中。 根据C++标准的定义,strstream是过时的,未来版本的C++标准可 能不再支持strstream,因此使用前一种。
输出字符流对象,ostringstream 对象用来进行格式化的输出,可以将各种类型 转换为string类型,只支持 << 操作符,如:
ostringstream oss;
oss<<1.234; //double型转化为字符串
oss<<" "; //字符串常量转化为字符串
oss<<1234; //int型转化为字符串
oss<<endl;
cout<<oss.str(); //输出“1.234 1234”
oss.str(""); //每次使用前清空
oss<<3.114159; //double型转化为字符串
Str2=oss.str();
cout<<Str2<<endl; //输出“3.14159”
输入字符流对象,istringstream 对象用于把一个已定义字符串中的以空格隔开 的内容提取出来,只支持 >> 操作符,如
int a;
string str1;
string input="abc 123 def 456 ghi 789";
istringstream iss(input); //通过构造函数对iss进行赋值
while(iss>>str1>>a) cout<<str1<<" "<<a<<endl;
//从iss中先提出一个字符串,再提出一个整数
//运行结果
//abc 123
//def 456
//ghi 789
stringstream类是istringstream和ostringstream类的综合,支 持>> 和 <<操作符。
int a; string str1;
string input="abc 123 def 456 ghi 789";
stringstream ss;
ss<<input;
while(ss>>str1>>a) cout<<str1<<" "<<a<<endl;
计算器的实现:
#include <iostream>
#include <sstream> //使用字符串流
using namespace std; //字符串流定义在std命名空间
int main()
{ //字符串流示例
string s1, s2; //定义string对象
ostringstream oss; //字符串输出流
istringstream iss; //字符串输入流
char c1='+', c2;
double val, sum=0.0;
cin>>s2; //从键盘上输入字符串 1000+200-30+4+0.4
iss.str(s2); //复制s2内容到字符串输入流
while (c1!=' ') {
iss>>val>>c2; //读取一个值和运算符+/-
if (c1=='+') sum=sum+val; //由值前面的运算符决定运算
else if (c1=='-') sum=sum-val;
c1=c2, c2=' '; //保存当前运算符下次用
}
oss<<sum; s1 = oss.str();//运算结果输出到字符串流中,s1是其副本
cout<<s1<<endl; //输出s1到显示器
return 0;
}