基于C语言的C++学习(三)
这是作者的学习经历和学习笔记,如有错误,欢迎指正。
学习网址是黑马程序员的C++
文件操作
C++中对文件操作需要包含头文件
文件类型分为两种:
- 文本文件
- 二进制文件
操作文件的三大类:
ofstream:写操作ifstream:读操作fstream:读写操作
文本文件
写文件
- 包含头文件:
#include<fstream - 创建流对象:
ofstream ofs; - 打开文件:
ofs.open("文件路径", 打开方式); - 写数据:
ofs << "写入的数据" - 关闭文件:
ofs.close();
| 打开方式 | 解释 |
|---|---|
ios::in | 为读文件而打开文件 |
ios::out | 为写文件而打开文件 |
ios::ate | 初始位置:文件尾 |
ios::app | 追加方式写文件 |
ios::trunc | 如果文件存在,先删除,再创建 |
ios::binary | 二进制方式 |
**注意:**文件打开方式可以配合使用,用|操作符
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
void test01()
{
ofstream ofs;
ofs.open("test.txt", ios::out);
ofs << "姓名:张三" << endl;
ofs << "性别:男" << endl;
ofs.close();
}
int main()
{
test01();
system("pause");
return 0;
}
读文件
- 包含头文件:
#include<fstream - 创建流对象:
ifstream ifs; - 打开文件:
ifs.open("文件路径", 打开方式); - 读数据:四种方式读取,见代码
- 关闭文件:
ifs.close();
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
void read_mode_1(ifstream& ifs)
{
char buf[1024] = { 0 };
cout << "第一种读取方式" << endl;
while (ifs >> buf)
{
cout << buf << endl;
}
}
void read_mode_2(ifstream& ifs)
{
char buf[1024] = { 0 };
cout << "第二种读取方式" << endl;
while (ifs.getline(buf, sizeof(buf)))
{
cout << buf << endl;
}
}
void read_mode_3(ifstream& ifs)
{
string buf;
cout << "第三种读取方式" << endl;
while (getline(ifs, buf))
{
cout << buf << endl;
}
}
void read_mode_4(ifstream& ifs)
{
char c;
cout << "第四种读取方式" << endl;
while ((c = ifs.get()) != EOF)
{
cout << c;
}
}
void test01()
{
ifstream ifs;
ifs.open("test.txt", ios::in);
if (!ifs.is_open())
{
cout << "文件打开失败" << endl;
return;
}
//read_mode_1(ifs);
//read_mode_2(ifs);
//read_mode_3(ifs);
read_mode_4(ifs);
ifs.close();
}
int main()
{
test01();
system("pause");
return 0;
}
二进制文件
写文件
二进制方式写文件主要利用流对象调用成员函数write
函数原型:ostream& write(char * buffer, int len);
参数解释:字符指针buffer指向内存中一段存储空间,len是读写的字节数
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
class Person
{
public:
char m_Name[64];
int m_Age;
};
void test01()
{
ofstream ofs;
ofs.open("Person.txt", ios::out | ios::binary);
Person p = { "张三", 18 };
ofs.write((const char*)&p, sizeof(Person));
ofs.close();
}
int main()
{
test01();
system("pause");
return 0;
}
读文件
二进制方式写文件主要利用流对象调用成员函数read
函数原型:ostream& read(const char * buffer, int len);
参数解释:字符指针buffer指向内存中一段存储空间,len是读写的字节数
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
class Person
{
public:
char m_Name[64];
int m_Age;
};
void test01()
{
ifstream ifs;
ifs.open("Person.txt", ios::in | ios::binary);
if (!ifs.is_open())
{
cout << "文件打开失败" << endl;
return;
}
Person p;
ifs.read((char*)&p, sizeof(Person));
cout << "姓名:" << p.m_Name << "年龄:" << endl;
ifs.close();
}
int main()
{
test01();
system("pause");
return 0;
}
模板
C++另一种编程思想称为泛型编程,主要利用的技术就是模板
C++提供两种模板机制:函数模板和类模板
模板的特点:
- 模板不可以直接使用
- 模板不是通用的
函数模板
函数模板的基本用法
**函数模板作用:**建立一个通用函数,其返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表。
语法:
template<typename T>
函数定义或声明
template:声明创建模板typename:表明其后面的符号是一种数据类型,可以用class代替T:通用的数据类型,名称可以替换,通常为大写字母
#include<iostream>
using namespace std;
template<typename T>
void Swap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
void test01()
{
int a = 10;
int b = 20;
//1.自动类型推导
Swap(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
double c = 0.1;
double d = 0.2;
//显示指定类型
Swap<double>(c, d);
cout << "c = " << c << endl;
cout << "d = " << d << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
函数模板注意事项
- 自动类型推导,必须推导出一致的数据类型T才可以使用
- 模板必须要确定出T的数据类型,才可以使用
#include<iostream>
using namespace std;
template<typename T>
void Swap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
//自动类型推导,必须推导出一致的数据类型T才可以使用
void test01()
{
int a = 10;
int b = 20;
Swap(a, b); //错误,a和b应该要统一数据类型
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
template<typename T>
void func()
{
cout << "func的调用" << endl;
}
void test02()
{
func(); //错误,编译器无法推导出T的类型
func<int>(); //正确
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
函数模板案例
- 利用函数模板封装一个排序函数,可以对不同类型的数据数组进行排序
- 排序从小到大,选择排序
#include<iostream>
using namespace std;
template<typename T>
void Swap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
template<typename T>
void Sort(T arr[], int n)
{
for (int i = 0; i < n - 1; i++)
{
int min = i;
for (int j = i + 1; j < n; j++)
{
if (arr[min] > arr[j])
{
min = j;
}
}
if (min != i)
{
Swap(arr[min], arr[i]);
}
}
}
template<typename T>
void Printf(T arr[], int n)
{
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
void test01()
{
int intArray[5] = { 2, 5, 4, 3, 1 };
char charArray[] = "icnwljf";
int num1 = sizeof(intArray) / sizeof(int);
int num2 = sizeof(charArray) / sizeof(char) - 1;
Sort(intArray, num1);
Sort(charArray, num2);
Printf(intArray, num1);
Printf(charArray, num2);
}
int main()
{
test01();
system("pause");
return 0;
}
普通函数和函数模板的区别
- 普通函数在调用时可以发生隐式类型转换
- 函数模板用自动类型推导,不可以发生隐式类型转换
- 函数模板用显示指定类型,可以发生隐式类型转换
普通函数与函数模板的调用规则
- 如果函数模板和普通函数都可以调用,优先调用普通函数
- 可以通过空模板的参数列表,强制调用函数模板
- 函数模板可以发生重载
- 如果函数模板可以产生更好的匹配,优先调用函数模板
模板的具体化
模板不是万能的,有时候模板无法对自定义数据类型进行操作,可以通过运算符重载或模板具体化
语法:
// 1. 先声明通用函数模板
template<typename T>
返回值类型 函数名(参数列表) {
// 通用实现
}
// 2. 再声明针对特定类型的具体化版本
template<> // 必须添加 template<> 关键字
返回值类型 函数名<具体类型>(参数列表) { // 显式指定具体类型
// 针对该类型的定制实现
}
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(int age, string name)
{
this->age = age;
this->name = name;
}
int age;
string name;
};
//比较相同函数
template<typename T>
bool compare(const T& a, const T& b)
{
if (a == b)
{
return true;
}
else
{
return false;
}
}
template<>
bool compare(const Person& a, const Person& b) //具体化
{
if (a.age == b.age && a.name == b.name)
{
return true;
}
else
{
return false;
}
}
void test01()
{
Person p1(18, "Ton");
Person p2(18, "Ton");
if (compare(p1, p2))
{
cout << "p1 == p2" << endl;
}
else
{
cout << "p1 != p2" << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
类模板
**作用:**建立一个通用类,类中的成员数据类型可以不具体定制,用一个虚拟的类型来代表
语法:
template<class T>
类
#include<iostream>
#include<string>
using namespace std;
template<class NameType, class AgeType>
class Person
{
public:
Person(NameType name, AgeType age)
{
this->m_Name = name;
this->m_Age = age;
}
void showPerson()
{
cout << "name:" << this->m_Name << "\tage:" << this->m_Age << endl;
}
private:
NameType m_Name;
AgeType m_Age;
};
void test01()
{
Person<string, int>p1("张三", 19);
p1.showPerson();
}
int main()
{
test01();
system("pause");
return 0;
}
类模板和函数模板的区别
- 类模板没有自动类型推导的使用方式
- 类模板在模板参数列表中可以有默认参数
#include<iostream>
#include<string>
using namespace std;
template<class NameType, class AgeType = int>
class Person
{
public:
Person(NameType name, AgeType age)
{
this->m_Name = name;
this->m_Age = age;
}
void showPerson()
{
cout << "name:" << this->m_Name << "\tage:" << this->m_Age << endl;
}
private:
NameType m_Name;
AgeType m_Age;
};
void test01()
{
//Person p1("张三", 19); //错误
Person<string, int>p1("张三", 19);
p1.showPerson();
}
void test02()
{
Person<string>p2("李四", 18);
p2.showPerson();
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
类模板中成员函数创建时机
- 普通类中的成员函数一开始就可以创建
- 类模板中的成员函数在带哦应时才创建
#include<iostream>
#include<string>
using namespace std;
class Person1
{
public:
void showPerson1()
{
cout << "Person1的调用" << endl;
}
};
class Person2
{
public:
void showPerson2()
{
cout << "Person2的调用" << endl;
}
};
template<class T>
class MyClass
{
public:
T obj;
void func1()
{
obj.showPerson1(); //因为没有确定obj的类型,所以不会报错
}
void func2()
{
obj.showPerson2();
}
};
void test01()
{
MyClass<Person1>m1; //指定m1为Person1类型
m1.func1();
MyClass<Person2>m2; //指定m2为Person2类型
m2.func2();
}
int main()
{
test01();
system("pause");
return 0;
}
类模板对象做函数参数
一共有三种传入方式:
- 指定传入的类型——直接显示对象的数据类型
- 参数模板化——将对象中的参数变为模板进行传递
- 整个类模板化——将这个对象类型模板化进行传递
#include<iostream>
#include<string>
using namespace std;
template<class T1, class T2>
class Person
{
public:
Person(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
void showPerson()
{
cout << "name:" << m_Name << "\tage:" << m_Age << endl;
}
private:
T1 m_Name;
T2 m_Age;
};
//1.指定传入类型
void printPerson1(Person<string, int>& p)
{
p.showPerson();
}
void test01()
{
Person<string, int>p("孙悟空", 100);
printPerson1(p);
}
//2.参数模板化
template<class T1, class T2>
void printPerson2(Person<T1, T2>& p)
{
p.showPerson();
cout << "T1的类型为:" << typeid(T1).name() << endl;
cout << "T2的类型为:" << typeid(T2).name() << endl;
}
void test02()
{
Person<string, int>p("猪八戒", 99);
printPerson2(p);
}
//3.整个类模板化
template<class T>
void printPerson3(T & p)
{
p.showPerson();
cout << "T的类型为:" << typeid(T).name() << endl;
}
void test03()
{
Person<string, int>p("唐僧", 1000);
printPerson3(p);
}
int main()
{
test01();
test02();
test03();
system("pause");
return 0;
}
类模板与继承
- 当子类继承父类是一共类模板时,子类在声明的时候,要指定出父类中T的类型
- 如果不指定,编译器无法给子类分配内存
- 如果想灵活指定出父类中T的类型,子类也要变为类模板
#include<iostream>
#include<string>
using namespace std;
template<class T>
class Base
{
T m;
};
//class Son : public Base //错误,必须要知道父类中的T类型,才能继承给子类
class Son1 : public Base<int>
{
};
void test01()
{
Son1 S1;
}
template<class T1, class T2>
class Son2 : public Base<T2>
{
public:
Son2()
{
cout << "T1的数据类型为:" << typeid(T1).name() << endl;
cout << "T2的数据类型为:" << typeid(T2).name() << endl;
}
T1 obj;
};
void test02()
{
Son2<int, char> S2;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
类模板成员函数类外实现
#include<iostream>
using namespace std;
template<class T1, class T2>
class Person
{
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_Name;
T2 m_Age;
};
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
cout << "name:" << this->m_Name << "\tage:" << this->m_Age << endl;
}
void test01()
{
Person<string, int>P("Tom", 20);
P.showPerson();
}
int main()
{
test01();
system("pause");
return 0;
}
类模板分文件编写
**问题:**类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
解决:
- 直接包含.cpp源文件
- 将声明和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称
方法一:
Person.cpp
#include"Person.h"
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
cout << "name:" << m_Name << "\tage:" << m_Age << endl;
}
Person.h
#pragma once
#include<iostream>
using namespace std;
template<class T1, class T2>
class Person
{
public:
Person(T1 name, T2 age);
void showPerson();
private:
T1 m_Name;
T2 m_Age;
};
main.cpp
#include<iostream>
using namespace std;
#include<string>
#include"Person.cpp"
void test01()
{
Person<string, int>P("Tom", 18);
P.showPerson();
}
int main()
{
test01();
system("pause");
return 0;
}
方法二:
Person.hpp
#pragma once
#include<iostream>
using namespace std;
template<class T1, class T2>
class Person
{
public:
Person(T1 name, T2 age);
void showPerson();
private:
T1 m_Name;
T2 m_Age;
};
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
cout << "name:" << m_Name << "\tage:" << m_Age << endl;
}
main.cpp
#include<iostream>
using namespace std;
#include<string>
#include"Person.hpp"
void test01()
{
Person<string, int>P("Tom", 18);
P.showPerson();
}
int main()
{
test01();
system("pause");
return 0;
}
类模板与友元
- 全局函数类内实现:直接在类内声明友元即可
- 全局函数类外实现:需要提前让编译器知道全局函数的存在
类内实现:
#include<iostream>
#include<string>
using namespace std;
template<class T1, class T2>
class Person
{
friend void printPerson(Person<T1, T2>& p)
{
cout << "name:" << p.m_Name << "\tage:" << p.m_Age << endl;
}
public:
Person(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
private:
T1 m_Name;
T2 m_Age;
};
void test01()
{
Person<string, int> p("Tom", 18);
printPerson(p); // 调用友元函数
}
int main()
{
test01();
system("pause");
return 0;
}
类外实现:
#include<iostream>
#include<string>
using namespace std;
// 提前声明模板类(供友元函数声明使用)
template<class T1, class T2>
class Person;
// 提前声明友元函数(模板函数)
template<class T1, class T2>
void printPerson(Person<T1, T2>& p);
template<class T1, class T2>
class Person
{
// 声明友元函数,并指定其模板参数
friend void printPerson<>(Person<T1, T2>& p);
// 注意:<> 表示使用与类相同的模板参数
public:
Person(T1 name, T2 age)
{
this->m_Name = name;
this->m_Age = age;
}
private:
T1 m_Name;
T2 m_Age;
};
// 定义友元函数(全局模板函数)
template<class T1, class T2>
void printPerson(Person<T1, T2>& p)
{
cout << "name:" << p.m_Name << "\tage:" << p.m_Age << endl;
}
void test01()
{
Person<string, int> p("Tom", 18);
printPerson(p); // 调用友元函数
}
int main()
{
test01();
system("pause");
return 0;
}
STL初识
STL基本概念
- STL(Standard Template Library,标准模板库)
- STL广义上分为:容器(container)算法(algorithm)迭代器(iterator)
- 容器和算法之间通过迭代器进行无缝链接
- STL几乎所有的代码都采用了类模板或者函数模板
STL六大组件:
- 容器:各种数据结构,如vector、list、deque、set、map等
- 算法:各种常用的算法,如sort、find、copy、for_each等
- 迭代器:扮演了容器与算法之间的胶合剂
- 仿函数:行为类似函数,可以作为算法的某种策略
- 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
- 空间配置器:负责空间的配置与管理
vector容器
功能:
- vector数据结构和数组非常相似,也称为单端数组
vector与普通数组的区别:
- 不同之处在于数组是静态空间,而vector可以动态扩展
动态扩展:
- 并不是在原有空间之后继续接新空间,而是找更大的内存空间,然后将原数据拷贝到新空间,释放原空间
vector构造函数
vector<T> v;——采用模板实现类实现,默认构造函数vector(v.begin(), v.end());——将v[begin(), end()]区间中的元素拷贝给本身vector(n, elem);——构造函数将n个elem拷贝vector(const vector &vec);
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void printVector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int>v1; //默认构造,无参构造
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
vector<int>v2(v1.begin(), v1.end());
printVector(v2);
vector<int>v3(10, 100);
printVector(v3);
vector<int>v4(v3);
printVector(v4);
}
int main()
{
test01();
system("pause");
return 0;
}
vector赋值操作
vector& operator=(const vector &vec);——重载等号操作符assign(beg, end);——将[beg, end]区间中的数据拷贝赋值给本身assign(n, elem);——将n个elem拷贝赋值给本身
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void printVector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
vector<int>v2;
v2 = v1;
printVector(v2);
vector<int>v3;
v3.assign(v1.begin(), v1.end());
printVector(v3);
vector<int>v4;
v4.assign(10, 100);
printVector(v4);
}
int main()
{
test01();
system("pause");
return 0;
}
vector容量和大小
empty();——判断容器是否为空capacity();——容器的容量size();——返回容器中元素的个数resize(int num);——重新指定容器的长度num,若容器变长, 则以默认值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除resize(int num, elem);——重新指定容器的长度num,若容器变长, 则以elem填充新位置,如果容器变短,则末尾超出容器长度的元素被删除
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void printVector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
if (v1.empty())
{
cout << "v1为空" << endl;
}
else
{
cout << "v1不为空" << endl;
cout << "v1容量为:" << v1.capacity() << endl;
cout << "v1大小为:" << v1.size() << endl;
}
v1.resize(15);
printVector(v1); //默认用0填充
v1.resize(20, 99);
printVector(v1);
v1.resize(5);
printVector(v1);
}
int main()
{
test01();
system("pause");
return 0;
}
vector插入和删除
push_back(ele);——尾部插入元素elepop_back();——删除最后一个元素insert(const_iterator pos, ele);——迭代器指向位置pos插入元素eleinsert(const_iterator pos, int count, ele)——迭代器指向位置pos插入count个元素eleerase(const_iterator pos);——删除迭代器指向位置的元素erase(const_iterator start, const_iterator end);——删除迭代器从start到end之间的元素clear();——删除容器中所有的元素
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void printVector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int>v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
printVector(v1);
//尾删
v1.pop_back();
printVector(v1);
//插入
v1.insert(v1.begin(), 100);
printVector(v1);
v1.insert(v1.begin(), 2, 200);
printVector(v1);
//删除
v1.erase(v1.begin());
printVector(v1);
v1.clear();
printVector(v1);
}
int main()
{
test01();
system("pause");
return 0;
}
vector存放数据
at(int idx);——返回索引idx所指的数据operator[];——返回索引idx所指的数据front();——返回容器第一个数据元素back();——返回容器最后一个数据元素
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void printVector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
for (int i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl;
for (int i = 0; i < v1.size(); i++)
{
cout << v1.at(i) << " ";
}
cout << endl;
cout << "第一个元素为:" << v1.front() << endl;
cout << "最后一个元素为:" << v1.back() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
vector互换容器
swap(vec);——将vec与本身的元素互换
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void printVector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
vector<int>v2;
for (int i = 10; i > 0; i--)
{
v2.push_back(i);
}
printVector(v2);
cout << "交换后:" << endl;
v1.swap(v2);
printVector(v1);
printVector(v2);
}
//实际用途
//巧用swap可以收缩内存空间
void test02()
{
vector<int>v;
for (int i = 0; i < 10000; i++)
{
v.push_back(i);
}
cout << "v的容量为:" << v.capacity()<< endl;
cout << "v的大小为:" << v.size() << endl;
v.resize(3);
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
vector<int>(v).swap(v);
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
}
int main()
{
test02();
system("pause");
return 0;
}
vector预留空间
reverse(int len);——容器预留len个元素长度,预留位置不初始化,元素不可访问
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void printVector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int>v1;
v1.reserve(10000);
int num = 0;
int* p = NULL;
for (int i = 0; i < 10000; i++)
{
v1.push_back(i);
if (p != &v1[0])
{
p = &v1[0];
num++;
}
}
cout << "num = " << num << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
vector存放内置数据
-
容器:vector -
算法:for_each -
迭代器:vector<int> iterator#include<iostream> #include<vector> #include<algorithm> using namespace std; void myPrint(int val) { cout << val << endl; } void test01() { //创建一个vector容器,数组 vector<int> v; //向容器中插入数据 v.push_back(10); v.push_back(20); v.push_back(30); v.push_back(40); v.push_back(50); vector<int>::iterator itBegin = v.begin(); //起始迭代器,指向容器中第一个元素 vector<int>::iterator itEnd = v.end(); //结束迭代器,指向容器中最后一个元素的下一个位置 while (itBegin != itEnd) { cout << *itBegin << endl; itBegin++; } for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << endl; } for_each(v.begin(), v.end(), myPrint); } int main() { test01(); system("pause"); return 0; }
vector存放自定义数据
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void test01()
{
vector<Person> v;
Person p1("aaa", 10);
Person p2("bbb", 20);
Person p3("ccc", 30);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
vector<Person*> v1;
Person p4("ddd", 40);
Person p5("eee", 50);
Person p6("fff", 60);
v1.push_back(&p4);
v1.push_back(&p5);
v1.push_back(&p6);
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
{
cout << (*it).m_Name << (*it).m_Age << endl;
}
for (vector<Person*>::iterator it = v1.begin(); it != v1.end(); it++)
{
cout << (*it)->m_Name << (*it)->m_Age << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
vector容器嵌套容器
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void test01()
{
vector< vector<int> >v;
vector<int>v1;
vector<int>v2;
vector<int>v3;
vector<int>v4;
for (int i = 0; i < 4; i++)
{
v1.push_back(i + 1);
v2.push_back(i + 2);
v3.push_back(i + 3);
v4.push_back(i + 4);
}
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
v.push_back(v4);
for (vector< vector<int>>::iterator it = v.begin(); it != v.end(); it++)
{
for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
{
cout << *vit << " ";
}
cout << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
string容器
string构造函数
- 本质:string本质上是一个类
- 特点:
- string类内部封装了很多成员方法
- string管理char*所分配的内存,不用担心复制越界和取值越界,由类内部进行负责
#include<iostream>
#include<string>
using namespace std;
void test01()
{
string s1;//默认构造
const char* str = "hello world";
string s2(str);
cout << "s2 = " << s2 << endl;
string s3(s2);
cout << "s3 = " << s3 << endl;
string s4(10, 'a');
cout << "s4 = " << s4 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
string赋值操作
string& operator=(const char* s);——char*类型字符串赋值给当前字符串string& operator(const string &s);——把字符串s赋值给当前的字符串string& operator=(char C);——字符赋值给当前的字符串string& assign(const char *s);——把字符串s赋值给当前的字符串string& assign(const char *s, int n);——把字符串s的前n个字赋值给当前的字符串string& assign(const string &s);——把字符串s赋给当前字符串string& assign(int n, char C);——用n个字符c赋值给当前字符串
#include<iostream>
#include<string>
using namespace std;
void test01()
{
string str1;
str1 = "hello world";
cout << "str1 = " << str1 << endl;
string str2;
str2 = str1;
cout << "str2 = " << str2 << endl;
string str3;
str3 = 'a';
cout << "str3 = " << str3 << endl;
string str4;
str4.assign("hello C++");
cout << "str4 = " << str4 << endl;
string str5;
str5.assign("hello C++", 5);
cout << "str5 = " << str5 << endl;
string str6;
str6.assign(str5);
cout << "str6 = " << str6 << endl;
string str7;
str7.assign(10, 'w');
cout << "str7 = " << str7 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
string拼接
string& operator+=(const char* str);——重载+=操作符string& operator+=(const char c);——重载+=操作符string& operator=+(const string& str);——重载+=操作符string& append(const char *s);——把字符串s连接到当前字符串结尾string& append(const char *s, int n);——把字符串s的前n个字符连接到当前字符串的结尾string& append(const string &s);——同operator+=(const string& str)string& append(const string &s, int pos, int n);——字符串s中从pos开始的n个字符串连接到字符串结尾
#include<iostream>
#include<string>
using namespace std;
void test01()
{
string str1 = "wo";
str1 += "爱玩游戏";
cout << "str1 = " << str1 << endl;
str1 += ':';
cout << "str1 = " << str1 << endl;
string str2 = "LOL DNF";
str1 += str2;
cout << "str1 = " << str1 << endl;
string str3 = "I";
str3.append(" love");
cout << "str3 = " << str3 << endl;
str3.append(" game abcde", 6);
cout << "str3 = " << str3 << endl;
str3.append(str2);
cout << "str3 = " << str3 << endl;
str3.append(str2, 4, 6);
cout << "str3 = " << str3 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
string查找和替换
int find(const string& str, int pos = 0) const;——查找str带一次出现位置,从pos开始查找int find(const char* s, int pos = 0) const;——查找s第一次出现位置,从pos开始查找int find(const cahr* s, int pos, int n) const;——从pos位置查找s的前n个字符int find(const char c, int pos = 0) const;——查找字符c第一次出现位置int rfind(const string& str, int pos = npos) const;——查找int rfind(const char* s, int pos = npos) const;int rfind(const char* s, int pos, int n) const;int rfind(const char* c, int pos = 0) const;string& replace(int pos, int n, const string& str);string& replace(int pos, int n, const char* s);
#include<iostream>
#include<string>
using namespace std;
//查找
void test01()
{
string str1 = "abcdefg abcdefg";
int pos = str1.find("bc"); //从0开始索引
if (pos == -1)
{
cout << "未找到字符串" << endl;
}
else
{
cout << "找到字符串,pos = " << pos << endl;
}
pos = str1.rfind("ab"); //从后面开始查找,返回第一次遇到的索引
cout << "pos = " << pos << endl;
}
//替换
void test02()
{
string str2 = "abcdefgh";
str2.replace(1, 3, "1111"); //从一号位置到三号位置,替换为四个1
cout << "str2 = " << str2 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
string字符串比较
比较方式:
字符串比较是按字符的ASCLL码进行对比
- = 返回 0
>返回1<返回-1
int comapre(const string &s) const;——与字符串s比较int compare(const char *s) const;——与字符串s比较
#include<iostream>
#include<string>
using namespace std;
void test01()
{
string str1 = "hello";
string str2 = "hello";
string str3 = "sello";
string str4 = "aello";
if (str1.compare(str2) == 0)
{
cout << "str1 == str2" << endl;
}
if (str1.compare(str3) < 0)
{
cout << "str1 < str3" << endl;
}
if (str1.compare(str4) > 0)
{
cout << "str1 > str4" << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
string字符存取
char& operator[](int n);char& at(int n);
#include<iostream>
#include<string>
using namespace std;
void test01()
{
string str1 = "hello";
cout << "str1 = " << str1 << endl;
//读取
for (int i = 0; i < str1.size(); i++)
{
cout << str1[i] << " ";
}
cout << endl;
for (int i = 0; i < str1.size(); i++)
{
cout << str1.at(i) << " ";
}
cout << endl;
//修改
str1[0] = 'x';
cout << "str1 = " << str1 << endl;
str1.at(1) = 'x';
cout << "str1 = " << str1 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
string插入和删除
string& insert(int pos, const char* s);——在pos位置插入字符串sstring& insert(int pos, const string& str);——在pos位置插入字符串string& insert(int pos, int n, char C);——在指定位置插入n个字符Cstring& erase(int pos, int n = npos);——删除从pos开始的n个字符
#include<iostream>
#include<string>
using namespace std;
void test01()
{
string str = "hello";
//插入
str.insert(1, "111");
cout << "str = " << str << endl;
//删除
str.erase(1, 3);
cout << "str = " << str << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
string子串
string substr(int pos = 0, int n = npos) const;——返回从pos开始的n个字符组成的字符串
#include<iostream>
#include<string>
using namespace std;
void test01()
{
string str = "hello";
string subStr = str.substr(1, 3);
cout << "subStr = " << subStr << endl;
}
//实用操作
void test02()
{
string email = "zhangsan@sina.ocm";
int pos = email.find('@');
string usename = email.substr(0, pos);
cout << "usename = " << usename << endl;
}
int main()
{
test02();
system("pause");
return 0;
}
&spm=1001.2101.3001.5002&articleId=160218128&d=1&t=3&u=60f0cbfd6b534e5b92d2528059ee64bd)
1386

被折叠的 条评论
为什么被折叠?



