C++ 类库学习总结

文章详细介绍了C++标准模板库(STL)中的几种容器,包括String的使用,以及vector、deque和list的特点和操作,如插入、删除、内存管理等。同时,对比了这几种容器的优缺点和适用场景。此外,还讲解了set和multiset作为关联式容器的特性,如自定义排序规则,并给出了实例演示。
摘要由CSDN通过智能技术生成

String类

追加

void test_string(void)
{
    MyTime myTime;
    string filepath = "my_file_";

    filepath += myTime.timeDate();
    filepath += ".txt";

    cout << filepath << endl;
}

测试结果
在这里插入图片描述

C++ STL

vector

特点
连续存储结构;与数组相比,内存空间可动态宽展;支持高效的随机访问、在尾部插入/删除操作,但在其他位置插入/删除效率较低。
内存空间扩展的实现原理:
(1)配置一块新空间
(2)将旧元素逐一搬到新址
(3)释放原来的空间

push_back()

作用:在尾部插入数据

pop_back()

作用:删除容器最后一个元素,该容器size会减1,但capacity不会变化。

erase(pos)

作用:删除容器中pos迭代器指定位置处的元素,并返回下一个位置元素的迭代器。容器size会减1,capacity不变。

swap()

作用:交换容器的内容;引申用法为,释放内存空间。

clear()

作用:删除容器中所有元素,使其变成空容器。容器size减1,capacity不变。

//注:在封装类似printfVector()这样的函数时,尽量使用const关键字,防止数据被异常篡改
void printfVector(const vector<int> &v)
{
    for (vector<int>::const_iterator it = v.begin(); it < v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
    cout << "size: " << v.size() << " ; ";
    cout << "capacity: " << v.capacity() << endl;

    return;
}

void test_vector(void)
{
    vector<int> v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }
    printfVector(v);

    v.pop_back();
    printfVector(v);

    vector<int>::iterator pos = v.begin();
    v.erase(pos);
    printfVector(v);

    vector<int> temp_v;
    for (int i = 0; i < 5; i++) {
        temp_v.push_back(i);
    }
    cout << "交换前:" << endl;
    cout << "v:" ;
    printfVector(v);
    cout << "tem_v:";
    printfVector(temp_v);

    temp_v.swap(v);
    cout << "交换后:" << endl;
    cout << "v:";
    printfVector(v);
    cout << "temp_v:";
    printfVector(temp_v);

    //延申用法:压缩v的内存空间
    vector<int>(v).swap(v);
    printfVector(v);

    //延申用法:压缩v的内存空间
    v.resize(2);
    printfVector(v);
    vector<int>(v).swap(v);
    printfVector(v);

    //延申用法:释放v的内存空间
    v.resize(0);
    printfVector(v);
    vector<int>(v).swap(v);
    printfVector(v);

    temp_v.clear();
    printfVector(temp_v);

    return;
}

测试结果:
在这里插入图片描述

deque

概念
双端队列,在功能上合并了vector和list。
特点
连续存储结构;deque提供了两级数据结构,第一级同vector,代表实际容器,另一级用于维护容器的首地址;和vector相比,支持高效的首/尾端插入/删除操作。
缺点
相比于vector,占用内存较多。

list

特点
非连续存储结构;双链表结构,支持向前、向后遍历;支持高效的随机插入/删除操作;
缺点
随机访问效率低下,需要额外维护指针,开销也比较大;
相比于vector,占用内存多;

vector、deque和list的使用区别

(1)使用vector:需要高效的随机存取,而不在乎插入/删除效率
(2)使用list:需要大量的插入/删除操作,而不关心随机存取
(3)使用deque:需要随机存取,又要支持两端数据的插入/删除

set & multiset

特点
关联式容器;内部采用高效的红黑树;
区别

  • set:不可插入重复数据
  • multiset:可插入重复数据

erase()

erase(val):删除set容器中存储的元素。

find()

find(val):在set容器中查找值为val的元素。成功-返回该元素的双向迭代器;失败-返回和end()方法一样的迭代器。

自定义排序规则

需要借助仿函数实现。
示例:

struct FileInfo
{
	string fileName;
	long writeTime;
};

//仿函数(类)
class setCompareByName
{
public:
	//重载小括号()
	bool operator()(const FileInfo& a, const FileInfo& b) const
	{
		return (a.fileName < b.fileName);
	}
};

class FileProcess
{
public:
	FileProcess() {};
	~FileProcess() {};

	void printfSet(set<FileInfo, setCompareByName>& files)
	{
		if (!files.empty())
		{
			for (set<FileInfo>::iterator it = files.begin(); it != files.end(); it++)
			{
				cout << "fileName: " << it->fileName << "; " << "writeTime: " << it->writeTime << endl;
			}
		}
		else
		{
			cout << "set is empty" << endl;
		}
	}

	void getFileInfoBySet(string path, set<FileInfo, setCompareByName>& files)
	{
		DIR* pDir;
		struct dirent* ptr;
		FileInfo fileInfo;
		struct stat buf;
		FILE* pFile = NULL;

		if (!(pDir = opendir(path.c_str())))
		{
			cout << "opendir error" << endl;
			return;
		}

		while ((ptr = readdir(pDir)) != 0)
		{
			if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)// 跳过.和..文件
			{
				continue;
			}
			fileInfo.fileName = ptr->d_name;

			string pathName = path + "/" + ptr->d_name;
			pFile = fopen(pathName.c_str(), "r");
			if (pFile)
			{
				int fd = fileno(pFile);
				fstat(fd, &buf);
				fileInfo.writeTime = buf.st_mtime;
				fclose(pFile);
			}
			else
			{
				cout << "pFile is null" << endl;
				fileInfo.writeTime = 0;
			}

			files.insert(fileInfo);
		}
		closedir(pDir);
	}
};

void custom_file_process_task()
{
	FileProcess fileProcess;
	string path = "/home/lx/test/video";

	while (1)
	{
		cout << "i am custom_file_process_task" << endl;

		set<FileInfo, setCompareByName> filesSet;
		fileProcess.getFileInfoBySet(path, filesSet);
		cout << "______ [set] files ______" << endl;
		fileProcess.printfSet(filesSet);

		sleep(5);
	}
}

测试结果
在这里插入图片描述

实例

获取指定目录下所有文件信息并排序(文件名和修改时间)

要求:获取指定指定目录下所有文件的信息,包括文件名和修改时间,并根据不同因素进行排序。

使用C++ vector实现

.hpp

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <dirent.h>
#include <algorithm>
#include <sys/stat.h>

using namespace std;

struct FileInfo
{
	string fileName;
	long writeTime;

	static bool LessThanByName(FileInfo a, FileInfo b)
	{
		return (a.fileName < b.fileName);
	}

	static bool LessThanByWriteTime(FileInfo a, FileInfo b)
	{
		return (a.writeTime < b.writeTime);
	}
};

class FileProcess
{
public:
	FileProcess() {};
	~FileProcess() {};
	
	void printfVec(vector<FileInfo> &files)
	{
		if (!files.empty())
		{
			for (vector<FileInfo>::iterator it = files.begin(); it != files.end(); it++)
			{
				cout << "fileName: " << it->fileName << "; "<< "writeTime: " << it->writeTime << endl;
			}
		}
		else
		{
			cout << "vector is empty" << endl;
		}
	}

	void getFileInfo(string path, vector<FileInfo> &files)
	{
		DIR* pDir;
		struct dirent* ptr;
		FileInfo fileInfo;
		struct stat buf;
		FILE* pFile = NULL;

		if (!(pDir = opendir(path.c_str())))
		{
			cout << "opendir error" << endl;
			return ;
		}

		while ((ptr = readdir(pDir)) != 0)
		{
			if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)// 跳过.和..文件
			{
				continue;
			}
			fileInfo.fileName = ptr->d_name;
			
			string pathName = path + "/" + ptr->d_name;
			pFile = fopen(pathName.c_str(), "r");
			if (pFile)
			{
				int fd = fileno(pFile);
				fstat(fd, &buf);
				fileInfo.writeTime = buf.st_mtime;
				fclose(pFile);
			}
			else
			{
				cout << "pFile is null" << endl;
				fileInfo.writeTime = 0;
			}

			files.push_back(fileInfo);
		}
		closedir(pDir);
	}

private:

};

.cpp

void custom_file_process_task()
{
	FileProcess fileProcess;
	string path = "/home/lx/test/video";

	while (1)
	{
		cout << "i am custom_file_process_task" << endl;
		
		vector<FileInfo> filesVec;
		fileProcess.getFileInfo(path, filesVec);
		fileProcess.printfVec(filesVec);
		
		sort(filesVec.begin(), filesVec.end(), FileInfo::LessThanByName);
		cout << "______ after sort LessThanByName ______" << endl;
		fileProcess.printfVec(filesVec);

		sort(filesVec.begin(), filesVec.end(), FileInfo::LessThanByWriteTime);
		cout << "______ after sort LessThanByWriteTime ______" << endl;
		fileProcess.printfVec(filesVec);

		sleep(5);
	}
}

测试结果
在这里插入图片描述
在这里插入图片描述

使用C++ set实现

.hpp

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <cstring>
#include <dirent.h>
#include <algorithm>
#include <sys/stat.h>
#include <set>

using namespace std;

struct FileInfo
{
	string fileName;
	long writeTime;
};

//for set
class setCompareByName
{
public:
	bool operator()(const FileInfo& a, const FileInfo& b) const
	{
		return (a.fileName < b.fileName);
	}
};

class setCompareByTime
{
public:
	bool operator()(const FileInfo& a, const FileInfo& b) const
	{
		return (a.writeTime < b.writeTime);
	}
};

class FileProcess
{
public:
	FileProcess() {};
	~FileProcess() {};
	
	void printfSet(set<FileInfo, setCompareByName>& files)
	{
		if (!files.empty())
		{
			for (set<FileInfo>::iterator it = files.begin(); it != files.end(); it++)
			{
				cout << "fileName: " << it->fileName << "; " << "writeTime: " << it->writeTime << endl;
			}
		}
		else
		{
			cout << "set is empty" << endl;
		}
	}

	void getFileInfoBySet(string path, set<FileInfo, setCompareByName>& files)
	{
		DIR* pDir;
		struct dirent* ptr;
		FileInfo fileInfo;
		struct stat buf;
		FILE* pFile = NULL;

		if (!(pDir = opendir(path.c_str())))
		{
			cout << "opendir error" << endl;
			return;
		}

		while ((ptr = readdir(pDir)) != 0)
		{
			if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)// 跳过.和..文件
			{
				continue;
			}
			fileInfo.fileName = ptr->d_name;

			string pathName = path + "/" + ptr->d_name;
			pFile = fopen(pathName.c_str(), "r");
			if (pFile)
			{
				int fd = fileno(pFile);
				fstat(fd, &buf);
				fileInfo.writeTime = buf.st_mtime;
				fclose(pFile);
			}
			else
			{
				cout << "pFile is null" << endl;
				fileInfo.writeTime = 0;
			}

			files.insert(fileInfo);
		}
		closedir(pDir);
	}

	void printfSet(set<FileInfo, setCompareByTime>& files)
	{
		if (!files.empty())
		{
			for (set<FileInfo>::iterator it = files.begin(); it != files.end(); it++)
			{
				cout << "fileName: " << it->fileName << "; " << "writeTime: " << it->writeTime << endl;
			}
		}
		else
		{
			cout << "set is empty" << endl;
		}
	}

	void getFileInfoBySet(string path, set<FileInfo, setCompareByTime>& files)
	{
		DIR* pDir;
		struct dirent* ptr;
		FileInfo fileInfo;
		struct stat buf;
		FILE* pFile = NULL;

		if (!(pDir = opendir(path.c_str())))
		{
			cout << "opendir error" << endl;
			return;
		}

		while ((ptr = readdir(pDir)) != 0)
		{
			if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)// 跳过.和..文件
			{
				continue;
			}
			fileInfo.fileName = ptr->d_name;

			string pathName = path + "/" + ptr->d_name;
			pFile = fopen(pathName.c_str(), "r");
			if (pFile)
			{
				int fd = fileno(pFile);
				fstat(fd, &buf);
				fileInfo.writeTime = buf.st_mtime;
				fclose(pFile);
			}
			else
			{
				cout << "pFile is null" << endl;
				fileInfo.writeTime = 0;
			}

			files.insert(fileInfo);
		}
		closedir(pDir);
	}
};

.cpp

void custom_file_process_task()
{
	FileProcess fileProcess;
	string path = "/home/lx/test/video";

	while (1)
	{
		cout << "i am custom_file_process_task" << endl;
	
		//compare by name
		set<FileInfo, setCompareByName> filesSetByName;
		fileProcess.getFileInfoBySet(path, filesSetByName);
		cout << "______ [set by name] files ______" << endl;
		fileProcess.printfSet(filesSetByName);

		//compare by time
		set<FileInfo, setCompareByTime> filesSetByTime;	
		fileProcess.getFileInfoBySet(path, filesSetByTime);
		cout << "______ [set by time] files ______" << endl;
		fileProcess.printfSet(filesSetByTime);

		sleep(5);
	}
}

测试结果
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值