将一个字符串中的字符替换成另一个字符串

题目:原地实现字符串中的每个空格替换成"%20",例如输入"We are happy", 输出"We%20are%20happy"

被替换的字符串当然不仅仅是空格,上面只是个例子

这是道很好的题目,也是我进百度面试时的一道题,题目不难,但是问题得考虑全面

#include <iostream>
#include <vector>
#include <cassert>

using namespace std;

int findNumberFirst(const char *str, const char *dest, vector<int>& pvec)
{
	if (str == NULL || dest == NULL)
		return 0;

	int pos = 0;
	int lenStr = strlen(str);
	int lenDest = strlen(dest);

	if (lenStr < lenDest)
		return 0;

	int count = 0;
	while (pos <= lenStr - lenDest)
	{
		if (strncmp(str + pos, dest, strlen(dest)) == 0)
		{
			pvec.push_back(pos);
			pos += lenDest;
			count++;
		}
		else
		{
			pos++;
		}
	}

	return count;
}

int findNumberLast(const char *str, const char *dest, vector<int> &pvec)
{
	if (str == NULL || dest == NULL)
		return 0;

	int strLen = strlen(str);
	int destLen = strlen(dest);

	if (strLen < destLen)
		return 0;

	int pos = 0;
	while (pos <= strLen - destLen)
	{
		if (strncmp(str + pos, dest, strlen(dest)) == 0)
		{
			pos += destLen;
			pvec.push_back(pos - 1);
		}
		else
		{
			pos++;
		}
		
	}

	return pvec.size();
}

void replaceArray(char *str, const char *src, const char *dest)
{
	if (str == NULL || src == NULL || dest == NULL)
		return;

	vector<int> pvec;
	int strLen = strlen(str);
	int srcLen = strlen(src);
	int destLen = strlen(dest);

	if (strLen < srcLen)
		return;

	int posBefore = 0;
	int posAfter = 0;

	if (srcLen < destLen)
	{
		int count = findNumberLast(str, src, pvec);
		if (count <= 0)
			return;
		
		posAfter = strLen + count * (destLen - srcLen) - 1;
		posBefore = strLen - 1;

		while (count > 0 && posBefore >= 0)
		{
			if (pvec[count - 1] == posBefore)
			{
				posAfter -= destLen;
				strncpy(str + posAfter + 1, dest, strlen(dest));
				count--;
				posBefore--;
			}
			else
			{
				str[posAfter--] = str[posBefore--];
			}
		}
	}
	else if (strLen > destLen)
	{
		int count = findNumberFirst(str, src, pvec);
		if (count <= 0)
			return;

		posAfter = 0;
		posBefore = 0;

		int i = 0;
		while (count >= 0 && posBefore < strLen)
		{
			if (count > 0 && pvec[i] == posBefore)
			{
				strncpy(str + posAfter, dest, strlen(dest));
				posAfter += destLen;
				count--;
				posBefore += srcLen;
				i++;
			}
			else
			{
				str[posAfter++] = str[posBefore++];
			}
		}
		str[posAfter] = '\0';
	}
}

void main()
{	
	char *str = new char[100];
	if (str == NULL)
		return;
	memset(str, '\0', 100);

	const char *src = " ";
	const char *dest = "%20";
//case1: 只有1个空格
	strcpy(str, " ");

	replaceArray(str, src, dest);
	cout << "str: " << str << endl;

	replaceArray(str, dest, src);
	cout << "str: " << str << endl;

//case2: 两个空格
	strcpy(str, "  ");

	replaceArray(str, src, dest);
	cout << "str: " << str << endl;

	replaceArray(str, dest, src);
	cout << "str: " << str << endl;

//case3: 正常情况
	strcpy(str, "we are happy");

	replaceArray(str, src, dest);
	cout << "str: " << str << endl;

	replaceArray(str, dest, src);
	cout << "str: " << str << endl;

//case3: 空格在前
	strcpy(str, " we are happy");

	replaceArray(str, src, dest);
	cout << "str: " << str << endl;

	replaceArray(str, dest, src);
	cout << "str: " << str << endl;

//case4: 空格在后
	strcpy(str, "we are happy ");

	replaceArray(str, src, dest);
	cout << "str: " << str << endl;

	replaceArray(str, dest, src);
	cout << "str: " << str << endl;

//case4: 没空格
	strcpy(str, "wearehappy");

	replaceArray(str, src, dest);
	cout << "str: " << str << endl;

	replaceArray(str, dest, src);
	cout << "str: " << str << endl;

//case5: 两边一样
	strcpy(str, "we are happy");

	replaceArray(str, src, dest);
	cout << "str: " << str << endl;

	src = "%20";
	assert(dest == "%20");
	replaceArray(str, dest, src);
	cout << "str: " << str << endl;
}


很有意思的一个情况是srcLen和destLen或大或小的情形,其边界条件的判定不一样

比如we are happy为例子,从后往前拷贝时,count=2

在count=0时,恰好将最前面的空格替换完成,we则不用重复拷贝

但是对于从前往后拷贝

当count=0时,最后面的happy将不会被拷贝

展开阅读全文

没有更多推荐了,返回首页