c++常用的一些自定义函数

本文介绍了作者在C++编程中常用的自定义函数,包括文件处理(读取、路径格式化)、字符串操作(替换、大小写转换、去除空格等)、字符串类型转换(如UTF8/GBK、wstring-string转换),以及程序运行记录工具类LogUtility的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

平时在我们编写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;
}

总结

以上就是我平时使用到的一些自定义函数。当然,还有挺多的实用的自定义函数,没有写进来,因为之前使用后就抛弃了,没有很好的保存下来,后面都会开始以写博客的方式去记录一些自己的技术,形成一套自己的代码。如果对你有帮助,希望点赞支持。如果有不同的意见,欢迎评论交流,感谢你的指正。

<think>好的,用户的问题是想在C++中实现某些功能,但不使用自定义函数。我需要先理解用户的具体需求。用户可能希望避免定义自己的函数,可能因为代码简洁性、项目规范限制,或者对函数作用域和可维护性有要求。 首先,我需要考虑C++中哪些结构可以在不定义函数的情况下实现功能。根据引用[1],C++提供了多种控制结构,如if-else、循环、switch语句,以及函数调用。但用户要求不使用自定义函数,所以需要利用内置函数语言结构。 可能的解决方案包括使用lambda表达式、内联代码、宏、STL算法和标准库函数。例如,STL算法如`std::for_each`或`std::transform`可以替代循环处理数据,而无需定义函数。不过,这些算法通常需要函数对象,可能需要lambda,但lambda是否算自定义函数呢?如果用户认为lambda是匿名函数,可能属于自定义,但有时候用户可能接受这种内联的方式。 另外,考虑使用宏来替代函数。宏在预处理阶段展开,不会生成函数,但需要注意宏的局限性和潜在问题,比如作用域和类型安全。例如,可以用宏实现简单的操作,但复杂逻辑可能难以维护。 还可以利用C++的控制结构直接编写代码,将所有逻辑放在main函数里,或者使用嵌套的代码块。例如,用循环和条件语句处理任务,但这可能导致代码冗长,尤其是重复代码时。 需要检查用户提供的引用内容。引用[1]提到可以在其他函数内部或全局作用域定义函数,但用户不想自定义函数。引用[2]提到避免使用某些库,比如regex,但用户的问题不涉及特定库,所以可能不需要考虑这点。 可能的应用场景包括简单的一次性脚本,或者限制函数使用的环境。例如,教学环境中让学生仅用控制结构完成任务,或者某些嵌入式系统的编码规范限制函数定义。 接下来,需要确保回答符合格式要求:行内数学公式用$...$,独立公式用$$...$$,正确使用LaTeX,中文回答,生成相关问题,引用标注正确。需要给出具体例子,比如使用宏、STL算法或内联代码的示例代码。 最后,生成相关问题需要考虑用户可能的后续疑问,例如替代方案的限制、宏的优缺点、代码组织方法等。</think>在C++中实现功能而不使用自定义函数,可以通过以下方法结合语言特性和标准库实现: ### 1. 利用控制结构直接实现 通过`if-else`、循环等控制结构编写内联代码。例如实现数组求和: ```cpp #include <iostream> int main() { int arr[] = {1,2,3,4,5}; int sum = 0; for(int x : arr) { // 基于范围的for循环 sum += x; } std::cout << "Sum: " << sum; // 输出Sum: 15 } ``` ### 2. 使用STL算法替代函数 标准模板库(STL)提供预定义算法,如`std::accumulate`实现求和: ```cpp #include <iostream> #include <numeric> #include <vector> int main() { std::vector<int> v = {1,2,3,4,5}; std::cout << "Sum: " << std::accumulate(v.begin(), v.end(), 0); // 输出Sum:15 } ``` ### 3. 宏定义替代函数 通过预处理器宏实现简单功能: ```cpp #include <iostream> #define PRINT_SQUARE(x) std::cout << (x)*(x) << "\n" int main() { PRINT_SQUARE(5); // 输出25 } ``` ### 4. 使用Lambda表达式(匿名函数) 虽然技术上属于函数对象,但无需显式命名: ```cpp #include <iostream> #include <algorithm> int main() { int arr[] = {3,1,4}; std::sort(arr, arr+3, [](int a, int b){return a > b;}); // 降序排序 // 结果为{4,3,1} } ``` ### 限制与注意事项 - 代码可维护性降低:内联代码可能增加重复逻辑 - 宏的副作用:例如`PRINT_SQUARE(++x)`会展开为`(++x)*(++x)` - STL算法覆盖率:约100+预定义算法可覆盖80%常用操作[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值