前言
平时在我们编写c++代码的时候,常常会有一些基本函数需要进行一个定义,这样子方便我们后续的工程代码的编写。特别是在使用过java后,转c++时,会觉得很多的不适应,因为java中是拥有很多的辅助的方法。所以,如果我们能事先把这些基础的自定义函数进行编写,那么可以大大提高后续工程的编写效率。下面将从几个方便介绍一下我平时常用的自定义函数。
在此之前,我们需要导入一些头文件。
#include <algorithm>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <memory>
#include <io.h>
#include <locale>
#include <codecvt>
#include <Windows.h>
一、文件处理中的自定义函数
1.读取文件中的所有内容
static std::string& ReadPathFileToString(std::string& filePath)
{
setlocale(LC_CTYPE, ".936");
std::ifstream fin(filePath);
std::string str((std::istreambuf_iterator<char>(fin)), std::istreambuf_iterator<char>());
setlocale(LC_CTYPE, 0);
return str;
}
2.读取文件夹中的所有文件名字以及文件地址
static void GetFileNames(const std::string& filePath, std::vector<std::string>& fileNames)
{
long long hFile = 0;
struct _finddata_t fileinfo;
string p;
int i = 0;
if ((hFile = _findfirst(p.assign(filePath).append("\\*").c_str(), &fileinfo)) != -1)
{
do
{
if ((fileinfo.attrib & _A_SUBDIR))
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
GetFileNames(p.assign(filePath).append("\\").append(fileinfo.name), fileNames);
else
fileNames.push_back(fileinfo.name);
} while (_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}
3.格式化文件地址
提示:代码中使用到的Replace函数下面字符串处理中会写
static void FormatFilePath(std::string& path)
{
ReplaceAll(path, "/", "\\");
ReplaceAll(path, "\\\\", "\\");
}
二、字符串处理中的自定义函数
1.将字符串中所有key替换成replace
static void ReplaceAll(std::string& str, const std::string& key, const std::string& replace)
{
while (true)
{
int ret = str.find(key);
if (ret > str.size())break;
str.replace(ret, key.length(), replace);
}
}
2.将所有字符串进行大(小)写操作
//大写操作
static void StrToupper(char* buf, int size)
{
std::transform(buf, buf + size, buf, ::toupper);//将字符串全部转换为大写字母
}
static string StrToUpper(const string& inputStr)
{
string str = inputStr;
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
return str;
}
//小写操作
static string StrToLower(const string& inputStr)
{
string str = inputStr;
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
return str;
}
3.去掉字符串首尾的空字符串
static string& Trim(string& s)
{
string str = s;
str.erase(0, str.find_first_not_of(" \t")); // 去掉头部空格
str.erase(str.find_last_not_of(" \t") + 1); // 去掉尾部空格
return str;
}
4.检查是否以ending字符串结尾
static bool StrEndsWith(const string& value, const string& ending)
{
if (value.size() < ending.size()) return false;
std::string tstr = value.substr(value.size() - ending.size());
if (tstr.length() == ending.length())
{
return tstr == ending;
}
return false;
}
5.字符串分割
//传参1函数
static void Split(const std::string& s, char delim, std::vector<std::string>& elems)
{
elems.clear();
if (s == "")return;
std::string strs = s + delim;
int pos = strs.find(delim);
while (pos < strs.size())
{
std::string temp = strs.substr(0, pos);
elems.push_back(temp);
strs = strs.substr(pos + 1, strs.size());
pos = strs.find(delim);
}
}
//传参2函数
static vector<string> Split(const std::string& s, char delim)
{
vector<std::string> res;
if (s == "")return res;
std::string strs = s + delim;
int pos = strs.find(delim);
while (pos < strs.size())
{
std::string temp = strs.substr(0, pos);
res.push_back(temp);
strs = strs.substr(pos + 1, strs.size());
pos = strs.find(delim);
}
return res;
}
6.字符串分割成整型数据
static void SplitToIntVec(const std::string& s, char delim, vector<int>& result)
{
result.clear();
if (s == "")return;
std::string strs = s + delim;
int pos = strs.find(delim);
while (pos < strs.size())
{
std::string temp = strs.substr(0, pos);
if(temp.size() > 0)
result.push_back(stoi(temp));
strs = strs.substr(pos + 1, strs.size());
pos = strs.find(delim);
}
}
7.取字符串的hash值
static size_t HashString(const string& str)
{
return std::hash<std::string>{}(str);
}
三、字符串的类型转换
1.UTF8格式转GBK格式
static string UTF8ToGBK(const std::string& utf8Str)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
std::wstring tmp_wstr = conv.from_bytes(utf8Str);
//GBK locale name in windows
const char* GBK_LOCALE_NAME = ".936";
std::wstring_convert<std::codecvt_byname<wchar_t, char, mbstate_t>> convert(new std::codecvt_byname<wchar_t, char, mbstate_t>(GBK_LOCALE_NAME));
return convert.to_bytes(tmp_wstr);
}
2.GBK格式转UTF8格式
static string GBKToUTF8(const std::string& GBKStr)
{
const char* GBK_LOCALE_NAME = ".936";
std::wstring_convert<std::codecvt_byname<wchar_t, char, mbstate_t>> convert(new std::codecvt_byname<wchar_t, char, mbstate_t>(GBK_LOCALE_NAME));
std::wstring tmp_wstr = convert.from_bytes(GBKStr);
std::wstring_convert<std::codecvt_utf8<wchar_t>> cv2;
return cv2.to_bytes(tmp_wstr);
}
3.string转wstring
注意:在平常看到的wchar_t其实就是wstring.c_str()即可得到
static std::wstring StringToWideString(std::string& str)
{
std::wstring result;
int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);
auto buffer = std::shared_ptr<TCHAR>(new TCHAR[len + 1]);
MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer.get(), len);
(*(buffer.get() + len)) = '\0';
result.append(buffer.get());
return result;
}
//提供另外一种跨平台的操作(可以linux和macos)
static std::wstring StringToWideString(const std::string &s)
{
std::string strLocale = setlocale(LC_ALL, "");
const char *chSrc = s.c_str();
size_t nDestSize = mbstowcs(NULL, chSrc, 0) + 1;
auto wchDest = std::shared_ptr<wchar_t>(new char[nDestSize]);
wmemset(wchDest.get(), 0, nDestSize);
mbstowcs(wchDest.get(), chSrc, nDestSize);
std::wstring wstrResult = wchDest.get();
setlocale(LC_ALL, strLocale.c_str());
return wstrResult;
}
4.wstring转string
注意:在平常看到的wchar_t其实就是wstring.c_str()即可得到
static std::string WideStringToString(std::wstring& wstr)
{
LPCWSTR pwszSrc = wstr.c_str();
int nLen = WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, NULL, 0, NULL, NULL);
if (nLen <= 0)
return std::string("");
auto pszDst = std::shared_ptr<char>(new char[nLen + 1]);
WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, pszDst.get(), nLen, NULL, NULL);
pszDst.get()[nLen] = 0;
std::string strTemp(pszDst.get());
return strTemp;
}
//提供一种跨平台操作
std::string WString2String(const std::wstring &ws)
{
std::string strLocale = setlocale(LC_ALL, "");
const wchar_t *wchSrc = ws.c_str();
size_t nDestSize = wcstombs(NULL, wchSrc, 0) + 1;
auto chDest = std::shared_ptr<char>(new char[nDestSize]);
memset(chDest.get(), 0, nDestSize);
wcstombs(chDest.get(), wchSrc, nDestSize);
std::string strResult = chDest.get();
setlocale(LC_ALL, strLocale.c_str());
return strResult;
}
四、程序运行记录工具自定义类
1.记录工具自定义类的头文件
#ifndef LOGUTILITY
#define LOGUTILITY
#pragma warning(disable:4996)
#pragma warning(disable:4267)
#pragma warning(disable:4800)
#include <iostream>
#include <memory>
#include <time.h>
#include <string>
#include<fstream>
#include<iostream>
#include<stdarg.h>
class LogUtility
{
public:
LogUtility();
~LogUtility();
void SetStartTime(clock_t time);
/*log文件内容*/
void SetShowLog(bool showLog);
void SetLogFileName(std::string logFileName);
void CloseLogFile();
void OutPutLogMsg(const char* Msg, ...);
void OutPutStampedLogMsg(const char* Msg, ...);
/*追加版本的log文件的生成*/
void SetSummaryFileName(std::string summaryFileName);
void OutPutSummaryMsg(const char* Msg, ...);
void SetShowSummary(bool showSummary);
void CloseSummaryFile();
private:
double GetPassedTime();
clock_t m_start;
std::string _sLogFileName;
std::ofstream _sLogOut;
bool _sShowLog;
std::string _sSummaryFileName;
std::ofstream _sSummaryOut;
bool _sShowSummary;
};
2.记录工具自定义类的cpp文件
#include "LogUtility.h"
/**
* @brief 记录函数的初始化
* @param 无
*/
LogUtility::LogUtility()
{
_sLogFileName = "";
_sShowLog = false;
}
/**
* @brief 记录函数的析构函数
* @param 无
*/
LogUtility::~LogUtility()
{
}
/**
* @brief 设置记录文档的初始时间
* @param 初始时间
*/
void LogUtility::SetStartTime(clock_t time)
{
m_start = time;
}
/**
* @brief 设置是否需要产生当前记录文档的参数
* @param 是否产生log文件
*/
void LogUtility::SetShowLog(bool showLog)
{
_sShowLog = showLog;
}
/**
* @brief 设置产生的log文件的名字
* @param 文件名称
*/
void LogUtility::SetLogFileName(std::string logFileName)
{
if (!_sLogFileName.empty())
{
_sLogOut.close();
}
_sLogFileName = logFileName;
if (_sShowLog)
{
_sLogOut.open(_sLogFileName.c_str());
}
}
/**
* @brief 关闭并生成对应的文件
* @param 无
*/
void LogUtility::CloseLogFile()
{
if (false == _sShowLog || _sLogFileName.empty())
{
return;
}
_sLogOut.flush();
_sLogOut.close();
}
/**
* @brief 输出相关内容
* @param 和printf格式一样的
*/
void LogUtility::OutPutLogMsg(const char* Msg, ...)
{
if (false == _sShowLog || _sLogFileName.empty())
{
return;
}
va_list Args;
static char s[1024];
va_start(Args, Msg);
vsprintf(s, Msg, Args);
va_end(Args);
_sLogOut << s << "\t" << std::endl;
}
/**
* @brief 输出相关内容(标准格式化的)
* @param 和printf格式一样的
*/
void LogUtility::OutPutStampedLogMsg(const char* Msg, ...)
{
if (false == _sShowLog || _sLogFileName.empty())
{
return;
}
va_list Args;
static char s[1024];
va_start(Args, Msg);
vsprintf(s, Msg, Args);
va_end(Args);
_sLogOut << s << ":\t" << this->GetPassedTime() << std::endl;
}
/**
* @brief 设置最加log文件的名字
* @param 最佳文件的名字
*/
void mLogUtility::SetSummaryFileName(std::string summaryFileName)
{
_sSummaryFileName = summaryFileName;
}
void LogUtility::OutPutSummaryMsg(const char* Msg, ...)
{
if (_sSummaryFileName.empty())
{
return;
}
if (false == _sSummaryOut.is_open())
{
_sSummaryOut.open(_sSummaryFileName.c_str(), std::ofstream::app);
}
va_list Args;
static char s[1024];
va_start(Args, Msg);
vsprintf(s, Msg, Args);
va_end(Args);
_sSummaryOut << s << "," << this->GetPassedTime() << std::endl;
}
/**
* @brief 设置是否最佳文件
* @param true false
*/
void LogUtility::SetShowSummary(bool showSummary)
{
_sShowSummary = showSummary;
}
/**
* @brief 关闭并生成当前文件
* @param
*/
void LogUtility::CloseSummaryFile()
{
if (false == _sShowSummary || _sSummaryFileName.empty())
{
return;
}
_sSummaryOut.flush();
_sSummaryOut.close();
}
/**
* @brief 获取每行的当前时间
* @param 无
*/
double LogUtility::GetPassedTime()
{
return 1.0 * (clock() - m_start) / CLOCKS_PER_SEC;
}
3.记录工具的使用
#include <iostream>
using namespace std;
int main()
{
auto utility = share_ptr<LogUtility>(new LogUtility());
utility->SetShowSummary(true);
utility->SetLogFileName("001.log");
utility->SetStartTime(clock());
for(int i = 0; i < 100; i++)
{
utility->OutPutStampedLogMsg("this is %d!", i);
}
utility->CloseLogFile();
return 0;
}
总结
以上就是我平时使用到的一些自定义函数。当然,还有挺多的实用的自定义函数,没有写进来,因为之前使用后就抛弃了,没有很好的保存下来,后面都会开始以写博客的方式去记录一些自己的技术,形成一套自己的代码。如果对你有帮助,希望点赞支持。如果有不同的意见,欢迎评论交流,感谢你的指正。