C++高效实现去除字符串头尾指定字符

江岸
江岸
发布时间:2026-10-15| 4人浏览过
原创

在C++开发中,去除字符串首尾指定字符是常见需求。相比依赖标准库,手动实现可更深入理解内存与指针操作。本文对比了基于循环移位与使用`memmove`优化的两种TrimHead/TrimTail方案,并通过基准测试揭示实际运行时的性能表现。

一、从头部开始去除指定字符

要实现去除头部字符的功能,核心逻辑是先定位第一个非目标字符的位置,再将后续内容移动至起始处。

第1步:基础循环移位实现

目的:通过遍历找到断点,并将剩余字符逐一拷贝至原位。
入口:源字符串指针 pszSrc 和目标字符 chTrim。
动作:
1. 检查指针有效性,若为空则直接返回。
2. 遍历字符串,跳过所有等于 chTrim 的字符。
3. 将剩下的字符逐个向前覆盖,最后补上字符串结束符 '\0'。

// 实现方式一
void TrimHead(char* pszSrc, char chTrim)
{
	if(NULL == pszSrc)
		return;
	
	// 从头部开始跳过chTrim指定的字符
	int i = 0;
	char* psz = pszSrc;
	while (*psz && *psz == chTrim) {
		i++;
		psz++;
	}
	
	// 从psz开始将后面字符逐一拷贝到前面
	i = 0;
	while(*psz)
	{
		*(pszSrc+i) = *psz;
		i++;
		psz++;
	}
	*(pszSrc+i) = 0;
}

完成状态:字符串头部的目标字符被移除,内容左移。

第2步:使用 memmove 优化

目的:减少多次内存写入操作,提升大数据量下的执行效率。
入口:同上。
动作:
1. 记录字符串总长度 iStrLen。
2. 同样先定位第一个非目标字符指针 psz。
3. 若位置发生变化,计算新长度,利用 memmove 一次性将有效部分及末尾空字符整体前移。

// 实现方式二
void TrimHeadEx(char* pszSrc, char chTrim)
{
	if(NULL == pszSrc)
		return;

	// 从头部开始跳过chTrim指定的字符
	int iStrLen = strlen(pszSrc);
	char* psz = pszSrc;
	while (*psz && *psz == chTrim) 
		psz++;

	// psz指向第一个非指定字符的位置
	if(psz != pszSrc)
	{
		// 计算新字符串长度
		iStrLen = iStrLen - (psz - pszSrc);
		memmove(pszSrc, psz, (iStrLen+1));	// +1表示将末尾的0也一并拷贝
	}
}

完成状态:达到相同效果,但涉及更少的指令周期。

二、去除尾部指定的字符

去除尾部字符通常有两种思路:正向遍历记忆最后一个非目标位,或逆向遍历寻找起始截断点。

第1步:正向遍历法

目的:从头扫到尾,标记最后出现的目标字符位置。
动作:
1. 维护一个 pszLast 指针,初始为NULL。
2. 遍历时,若遇到目标字符且未记录过,则标记;若遇到非目标字符,则重置标记。
3. 遍历结束后,若找到了目标字符,将其替换为 '\0'。

// 实现方式一
void TrimTail(char* pszSrc, char chTrim)
{
	if(NULL == pszSrc)
		return;

	char* psz = pszSrc;
	char* pszLast = NULL;
	
	// 从头开始遍历直到整个字符串结束
	while(*psz)
	{
		// 遇到指定字符,则用pszLast记住该位置
		if(*psz == chTrim)
		{
			if(NULL == pszLast)
				pszLast = psz;
		}
		else
			pszLast = NULL;
		psz++;
	}
	
	// 如果找到末尾的第一个指定字符,则作为字符串的结尾
	if(pszLast != NULL)
		*pszLast = 0;
}

缺点:无论尾部是否有目标字符,都必须完整扫描整个字符串。

第2步:逆向遍历法

目的:从尾部倒着查找,快速定位并截断。
入口:同上。
动作:
1. 获取字符串长度 iStrLen,索引从 iStrLen - 1 开始。
2. 只要当前字符是指定字符,索引递减。
3. 停止后将新的位置加1作为新长度,并在该处填入 '\0'。

// 实现方式二
void TrimTailEx(char* pszSrc, char chTrim)
{
	if(NULL == pszSrc)
		return;

	// 从尾部开始跳过chTrim指定字符
	int iStrLen = strlen(pszSrc);
	char* pszStr = pszSrc;
	int iLastIdx = iStrLen - 1;
	while(iLastIdx >= 0 && *(pszStr+iLastIdx) == chTrim)
		iLastIdx--;
	
	// 计算新字符串长度并在结尾赋值为0
	iStrLen = iLastIdx+1;
	*(pszSrc+iStrLen) = 0;
}

优势:若尾部没有目标字符,几乎不产生多余开销;若有大量目标字符,能迅速缩小范围。

三、性能测试与分析

为了客观评估各版本的速度差异,可以通过固定次数的循环调用来测量耗时。以下是包含上述函数的完整测试框架:

第1步:构建基准测试环境

目的:模拟高频调用场景,暴露微小的性能差距。
参数:循环次数设为 10000000,确保时钟精度带来的误差最小化。
动作:
1. 准备两组相同的缓冲区 szTrim1 和 szTrim2,初始化带有首尾空格的测试串。
2. 分别调用普通版和优化版的 TrimHead/Tail 函数。
3. 使用 clock() 记录时间差并打印结果。

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 此处省略 TrimHead, TrimHeadEx, TrimTail, TrimTailEx 的定义

void TestSpeedTrim(bool bTrimHead)
{
	char szTrim1[256] = {0};
	char szTrim2[256] = {0};
	
	char* pszOrigin = "     This is a trim test head/tail    ";
	strcpy(szTrim1, pszOrigin);
	strcpy(szTrim2, pszOrigin);
	
	int i = 0;
	int iCount = 10000000;
	clock_t cStart = 0;
	
	// 第一种Trim方法
	cStart = clock();
	for(i = 0; i < iCount; i++)
	{
		bTrimHead ? TrimHead(szTrim1, ' ') : TrimTail(szTrim1, ' ');
	}
	clock_t cSpan1 = clock() - cStart;
	
	// 第二种Trim方法
	cStart = clock();
	for(i = 0; i < iCount; i++)
	{
		bTrimHead ? TrimHeadEx(szTrim2, ' ') :	TrimTailEx(szTrim2, ' ');
	}
	clock_t cSpan2 = clock() - cStart;
	
	printf("cSpan1 = %d, cSpan2 = %d\r\n", cSpan1, cSpan2);
	printf("szTrim1=[%s]\r\n", szTrim1);
	printf("szTrim2=[%s]\r\n", szTrim2);
}

int main(int argc, char* argv[])
{
	// 测试头
	printf("删除头部的空字符:\r\n");
	TestSpeedTrim(true);

	// 测试尾
	printf("\r\n删除尾部的空字符:\r\n");
	TestSpeedTrim(false);

	getchar();
	return 0;
}

总结

在实际C/C++底层开发中,虽然 `std::string` 已经高度封装,但在处理 char* 数组时,合理使用 memmove 和逆向索引往往能获得更好的控制力与潜在性能增益。以上关于C++实现去除字符串头尾指定字符功能的详细内容,更多关于C++字符串处理技巧的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。