基于C的C++学习day5

泛型编程

编写程序时不具体的写定数据类型。提高重用性

1.模板

1.1函数模板(掌握)

编译器会根据传入参数的类型 替换T

注意:系统有swap函数 。下方函数名Swap首字母大写

#include <iostream>
using namespace std;
template <class T>
void Swap(T &a,T &b){
    T t=a;
    a=b;
    b=t;
}

int main()
{
    int m=10,n=20;
    Swap(m,n);
    cout<<m<<" "<<n<<endl;
    double m2=1.5,n2=2.5;
    Swap(m2,n2);
    cout<<m2<<" "<<n2<<endl;
}

add模板函数

#include <iostream>
using namespace std;
template <class T>
T add(T a,T b){
    return a+b;
}
int main()
{
    int a=2,b=3;

    int c=add(a,b);
    cout<<c<<endl;

    string str1="he";
    string str2="llo";

    cout<<add(str1,str2);

}

除了让编译器根据传入参数类型替换Ts外,也可以告知使用何种类型,实例化模板

#include <iostream>
using namespace std;
template <class T>
T Inc(T a){
    return a+1;
}
int main()
{
    cout<<Inc<double>(4)/2<<endl;
}

1.2.类模板(掌握)

如果要创建类的形式和功能类似。可以创建类模板,提高重用性和开发效率

template <typename T> 和template <class T> 都可以

#include <iostream>
using namespace std;
template <typename T>
class Demo
{
 private:
    T value;
 public:
    Demo(T value):value(value){}
    void set_value(T value){
        this->value=value;
    }
    T get_value(){
        return value;
    }
};
int main()
{
    Demo<int> d(10);
    cout<<d.get_value()<<endl;
    d.set_value(11);
    cout<<d.get_value()<<endl;

    Demo<bool> d2(true);//true: 1  false:0
    cout<<d2.get_value()<<endl;

}

模板类 类内声明类外定义

#include <iostream>
using namespace std;
template <typename T>
class Demo
{
 private:
    T value;
 public:
    Demo(T value);
    void set_value(T value);
    T get_value();
};
template <typename T>
Demo<T>::Demo(T value):value(value){}

template <typename T>
void Demo<T>::set_value(T value){
    this->value=value;
}

template <typename T>
T Demo<T>::get_value(){
    return value;
}
int main()
{
    Demo<int> d(10);
    cout<<d.get_value()<<endl;
    d.set_value(11);
    cout<<d.get_value()<<endl;

    Demo<bool> d2(true);
    cout<<d2.get_value()<<endl;

}

2.STL

用模板实现泛型编程,泛型编程中最成功的案例就c++中的标准模板库STL

STL包括的内容:

算法 sort()

容器

迭代器

容器:存放数据的类模板

顺序容器:不是按传入数据大小排序的 而是可以指定传入的位置

关联容器: 传入的数据进行排序 没法指定传入的位置

string字符串(熟悉)

代替 c语言中的char *

#include <iostream>
using namespace  std;
int main()
{
    string s="hello";
    cout<<s[0]<<endl;
    //cout<<s.at(6)<<endl; 会有检查
    cout<<s.length()<<endl;
    cout<<s.size()<<endl;
    for(char ch:s){
        cout<<ch<<endl;
    }
}

string创建

#include <iostream>
using namespace std;
int main()
{
    //创建string
    string s1="hello";
    string s2("world");
    string s3(s1);
    //参数1:长度
    //参数2:每个字符是什么
    string s4(5,'*');
    cout<<s1<<endl;
    cout<<s2<<endl;
    cout<<s3<<endl;
    cout<<s4<<endl;
    //string s5='a'; //常字符不能直接初始化
    string s5;
    s5='s';

}

string拼接

#include <iostream>
using namespace std;
int main()
{

    string s1="hello";
    s1[0]='H';
    cout<<s1<<endl; //Hello

    //第一种拼接
    string s2="Tom";
    s1+=s2; 
    cout<<s1<<endl; //HelloTom
    //第二种拼接 支持链式调用
    s1.append(s2).append(s2); //拼接字符串多时这种效率高
    cout<<s1<<endl;  //HelloTomTomTom
     //追加一个字符
    s1.push_back('#');
    cout<<s1<<endl;  //HelloTomTomTom#


}

string字符串关系运算符比较

返回值都是bool类型。成立返回true 否则返回false

#include <iostream>
using namespace std;
int main()
{
    //比较的编码
   // == ,>, >= ,< ,<= ,!=
    string s1("hello"),s2("hello"),s3("hell");
    bool b=(s1==s2);
    cout<<b<<endl; //1

    b=(s1==s3);
    cout<<b<<endl; //0

    b=(s1>s3);
    cout<<b<<endl; //1
}

取子字符串,替换

#include <iostream>
using namespace std;
int main()
{

    string s1("hello"),s2("hello"),s3("hell");
    swap(s1,s3);
    cout<<s1<<" "<<s3<<endl; //hell hello

    //参数1:下标开始位置
    //参数2:截取的个数
    string s4=s2.substr(1,4);//ello 
    cout<<s4<<endl;

    //参数1:替换的开始位置
    //参数2:替换字符的数量
    //参数3:替换的新内容
    s2.replace(1,2,"www");  //只是替换  不会覆盖字符串后面内容
    cout<<s2<<endl;   //hwwwlo
    
    //截取
    s2.erase(5);
    cout<<s2<<endl; //hwwwl
    s2.erase(2);
    cout<<s2<<endl; //hw
}

string插入

#include <iostream>
using namespace std;
int main()
{
    string s1("good");
    string s2("Tom");
    s1.insert(2,s2); //goTomod

    string s3("Jerry");
    
    //第1个参数:开始插入的下标
    //第2个参数:准备插入的内容
    //第3个参数:准备插入的内容的起始下标
    //第4个参数:个数
    s3.insert(2,s1,0,2); //Jegorry
    cout<<s1<<endl;
    cout<<s3<<endl;

}

vector向量(掌握)

内部是动态数组

删除和插入效率低,可以高效的存取

#include <iostream>
#include <vector>
using namespace std;
int main()
{
  vector<int> v(5);
  for(int i=0;i<5;i++){
      v[i]=i;
  }
  v.push_back(5); //后面追加5
  v.push_back(6); //后面再追加6
  cout<<v.size()<<endl; //7 大小动态变化
  for(int i:v){
      cout<<i<<" ";
  }

}

end()返回最后一个元素后面的迭代器

begin()返回第一个元素的迭代器

#include <iostream>
#include <vector>
using namespace std;
int main()
{
  vector<int> v(5);
  for(int i=0;i<5;i++){
      v[i]=i;
  }
  v.push_back(5); //后面追加5
  v.push_back(6); //后面再追加6
  cout<<v.size()<<endl; //7  
  //v.begin()返回第一个位置的迭代器
  v.insert(v.begin(),100);
  v.insert(v.begin()+2,200);
  v.insert(v.end()-1,300); //插入倒数第2位置
  v.erase(v.begin()+1); //删除第2个数
  v.erase(v.end()-2);//删除倒数2个

  for(int i:v){
      cout<<i<<" ";
  }

}

pop_back() 删除最后一个位置

#include <iostream>
#include <vector>
using namespace std;
int main()
{
  vector<char> vch;
  vch.push_back('a');
  vch.push_back('b');
  vch.push_back('c');
  vch.insert(vch.begin()+2,'f'); //在第3位置插入
  vch.pop_back();
  vch.erase(vch.end()-2); //af 删除倒数第2个

  vch[0]='f';  //ff
  vch.at(0)='F'; //Ff
  cout<<vch.size()<<endl; //2
  for(char ch:vch){
      cout<<ch<<" ";
  }
}

list 列表(掌握)

内部是双向链表来实现的,可以高效的插入和删除。但是存取效率较低。不支持下标操作。需要迭代指针操作元素

#include <iostream>
#include <vector>
#include <list>
using namespace std;
int main()
{
    list<string> lis;
    cout<<lis.empty()<<endl; //是空 返回1
    lis.push_back("AA");
    lis.push_back("BB");
    lis.push_back("CC");
    cout<<lis.empty()<<endl; //非空 返回0
    for(string s:lis){
        cout<<s<<" ";
    }
}

pop_back()

pop_front()

#include <iostream>
#include <vector>
#include <list>
using namespace std;
int main()
{
    list<string> lis;
    cout<<lis.empty()<<endl; //1

    lis.push_back("AA");
    lis.push_back("BB");
    lis.push_back("CC");

    //删除最后一个
    lis.pop_back();//AA BB
    //删除第一个
    lis.pop_front();//BB

    cout<<lis.empty()<<endl; //0

    for(string s:lis){
        cout<<s<<" ";
    }
}

list不能用 begin()+数字 的形式访问到元素,因为它是链式储存的,不是连续空间。用迭代器方法删除指定位置

list<string>::iterator iter

list<string>是容器类名

iter 是取的迭代器名

list<string> lis;
    cout<<lis.empty()<<endl; //是空 返回1
    lis.push_back("AA");
    lis.push_back("BB");
    lis.push_back("CC");
    lis.push_back("DD");
    lis.push_back("EE");
    cout<<lis.empty()<<endl; //非空 返回0
    //用迭代器的方式
    list<string>::iterator iter=lis.begin();
    advance(iter,2);//移动到第三位置
    lis.erase(iter);

    for(string s:lis){
        cout<<s<<" ";
    }

deque 队列

兼顾vector和list。性能在两者之间。方法是通用的,可以直接调用

关联容器(掌握)

关联容器内部存放是按一定顺序排列。物理上并不是像数组一样连续的空间。

常见的关联容器map。map是键和值对应存在的

数据是成对出现,前面的叫键,后面叫值。可以通过键访问值

可以使用迭代器遍历,比普通方式效率高

#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <map>
using namespace std;
int main()
{
    map<string,int> mp1;
    cout<<mp1.empty()<<endl; //1
    mp1.insert(pair<string,int>("age",18));
    mp1.insert(pair<string,int>("height",170));
    mp1.insert(pair<string,int>("salary",5000));
  
    //去除键对应的值
    cout<<mp1["height"]<<endl;
    cout<<mp1["salary"]<<endl;
    
    if(mp1.find("xxx")==mp1.end()) {
        cout<<"没有找到"<<endl;

    }else{
        cout<<"找到"<<endl;
    }
    if(mp1.find("age")!=mp1.end()){
        cout<<"键是存在的"<<endl;
    }
    
  //迭代器遍历  for(map<string,int>::iteratorite=mp1.begin();ite!=mp1.end();ite++)
    {
        cout<<ite->first<<":"<<ite->second<<endl;

    }
}

迭代器(掌握)

#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <map>
using namespace std;
int main()
{
    string s="abcde";
    for(string:: iterator its=s.begin(); its!=s.end();its++){
        cout<<*its<<" "<<endl;
    }
    vector<string> v(5,"hello");
    for(vector<string>::iterator itv=v.begin(); itv!=v.end();itv++){
        cout<<*itv<<endl;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值