剑指Offer----面试题四:替换空格

转载请注明出处<http://blog.csdn.net/qianqin_2014/article/details/51452126>


预备知识:


C/C++把常量字符串放到单独的一个内存区域。当几个 指针赋值给相同的常量字符串时,它们实际上会指向相同的内存地址。但是用常量内存 初始化数组,情况却不相同。

代码如下:
#include<iostream>
using namespace std;

int main()
{
	char *ch1 = "ABCD";
	char *ch2 = "ABCD";

	if (ch1 == ch2)
		cout << "same" << endl;
	else
		cout << "no same" << endl;

	char ch3[] = "ABCD";
	char ch4[] = "ABCD";
	if (ch3 == ch4)
		cout << "same" << endl;
	else
		cout << "no same" << endl;


	system("pause");
	return 0;
}

运行结果:
same
no same
请按任意键继续. . .

分析:
  1. ch1和ch2是两个指针,我们无需为它们分配内存以存储字符串内容,而只需要把它们指向“ABCD”在内存中的地址就可以了。由于“ABCD”是常量字符串,它在内存中只有一个拷贝,因此ch1和ch2指向的是同一个地址。
  2. ch3和ch4是两个字符串数组,我们会为它们分别分配两个长度为5个字节的空间,并把“ABCD”的内容分别复制到数组中去,这是两个初始地址不同的数组,因此ch1和ch2的值也不相同。

题目:

请实现一个函数,把字符串中的每个空格替换成“%20”。例如输入“We are happy.”,则输出“We%20are%20happy.”。

思路一:

利用string
源代码:
#include<iostream>
#include<string>
#include<algorithm>

using std::cout;
using std::endl;
using std::find;
using std::string;

int main()
{
	string str = "We are happy.";
	size_t pos = str.find(" ");
	while (pos < str.size())//不包括'\n'
	{
		str.replace(pos, 1, "%20");//在pos位置上删除一个字符,并插入"%20"
		size_t temp = str.find(" ", pos);//在pos位置之后查找" "
		pos = temp;
	}
	cout << str << endl;

	system("pause");
	return 0;
}

输出结果:
We%20are%20happy.
请按任意键继续. . .

思路二:

遍历字符串,没找到一个空格,将空格替换为“%20”,并将后边的字符向后移动两个位置。


思路三:

先统计字符串中空格的数目并计算替换之后字符串的总长度,每替换一个空格,字符长度增加2,因此替换之后的长度等于原始长度+空格数*2.

(a)把第一个指针指向字符串的末尾,把第二个指针指向替换之后的字符串的末尾
(b)依次赋值字符串中的内容,直至第一个指针碰到第一个空格
(c)把第一个空格替换成“%20”,把第一个指针向前移动1格,把第二个指针向前移动3格
(d)依次向前赋值字符串中的字符,直至碰到空格
(e)替换字符串中的倒数第二个空格,把第一个指针向前移动1格,把第二个指针向前移动3格

源代码:
#include<iostream>
#include<cstdlib>//malloc

using std::cout;
using std::endl;

void Replace(char *ch)
{
	if (ch == NULL)
		return;

	int len = strlen(ch)+1;//字符串的长度,包括'\n'
	int count = 0;//记录空格的数目
	for (int i = 0; i < len; i++)//统计空格的数目
	{
		if (ch[i] == ' ')
			count++;
	}

	char *temp = (char *)malloc((len + count * 2)*sizeof(char));//分配新的空间

	for (int i = 0; i < len; i++)//将ch中的内容复制到新分配的空间
		temp[i] = ch[i];

	char *p1 = temp + len - 1;//指向ch的最后一个字符'\n'
	char *p2 = temp + len + count * 2 - 1;//指向新分配空间的最后一个字符空间

	while (p1 != p2)
	{
		if (*p1 != ' ')
		{
			*(p2--) = *(p1--);
		}
		else
		{
			*(p2--) = '0';
			*(p2--) = '2';
			*(p2--) = '%';
			--p1;
		}
	}
	cout << temp << endl;
}

int main()
{
	char *ch = "We are happy.";
	cout << ch << endl;
	Replace(ch);
<span style="white-space:pre">	char *ch2 = " ";
<span style="white-space:pre">	</span>Replace(ch2);
<span style="white-space:pre">	</span>char *ch3 = "  We  ";
<span style="white-space:pre">	</span>Replace(ch3);
<span style="white-space:pre">	</span>char *ch4 = NULL;
<span style="white-space:pre">	</span>Replace(ch4);</span>
	system("pause");
	return 0;
}

运行结果:
We are happy.
We%20are%20happy.
%20
%20%20We%20%20
请按任意键继续. . .

官方源代码:

// ReplaceBlank.cpp : Defines the entry point for the console application.
//

// 《剑指Offer——名企面试官精讲典型编程题》代码
// 著作权所有者:何海涛

#include <iostream>
#include <string>

/*length 为字符数组string的总容量*/
void ReplaceBlank(char string[], int length)
{
	if (string == NULL && length <= 0)
		return;

	/*originalLength 为字符串string的实际长度*/
	int originalLength = 0;
	int numberOfBlank = 0;
	int i = 0;
	while (string[i] != '\0')
	{
		++originalLength;

		if (string[i] == ' ')
			++numberOfBlank;

		++i;
	}

	/*newLength 为把空格替换成'%20'之后的长度*/
	int newLength = originalLength + numberOfBlank * 2;
	if (newLength > length)
		return;

	int indexOfOriginal = originalLength;
	int indexOfNew = newLength;
	while (indexOfOriginal >= 0 && indexOfNew > indexOfOriginal)
	{
		if (string[indexOfOriginal] == ' ')
		{
			string[indexOfNew--] = '0';
			string[indexOfNew--] = '2';
			string[indexOfNew--] = '%';
		}
		else
		{
			string[indexOfNew--] = string[indexOfOriginal];
		}

		--indexOfOriginal;
	}
}

void Test(char* testName, char string[], int length, char expected[])
{
	if (testName != NULL)
		printf("%s begins: ", testName);

	ReplaceBlank(string, length);

	if (expected == NULL && string == NULL)
		printf("passed.\n");
	else if (expected == NULL && string != NULL)
		printf("failed.\n");
	else if (strcmp(string, expected) == 0)
		printf("passed.\n");
	else
		printf("failed.\n");
}

// 空格在句子中间
void Test1()
{
	const int length = 100;

	char string[length] = "hello world";
	Test("Test1", string, length, "hello%20world");
}

// 空格在句子开头
void Test2()
{
	const int length = 100;

	char string[length] = " helloworld";
	Test("Test2", string, length, "%20helloworld");
}

// 空格在句子末尾
void Test3()
{
	const int length = 100;

	char string[length] = "helloworld ";
	Test("Test3", string, length, "helloworld%20");
}

// 连续有两个空格
void Test4()
{
	const int length = 100;

	char string[length] = "hello  world";
	Test("Test4", string, length, "hello%20%20world");
}

// 传入NULL
void Test5()
{
	Test("Test5", NULL, 0, NULL);
}

// 传入内容为空的字符串
void Test6()
{
	const int length = 100;

	char string[length] = "";
	Test("Test6", string, length, "");
}

//传入内容为一个空格的字符串
void Test7()
{
	const int length = 100;

	char string[length] = " ";
	Test("Test7", string, length, "%20");
}

// 传入的字符串没有空格
void Test8()
{
	const int length = 100;

	char string[length] = "helloworld";
	Test("Test8", string, length, "helloworld");
}

// 传入的字符串全是空格
void Test9()
{
	const int length = 100;

	char string[length] = "   ";
	Test("Test9", string, length, "%20%20%20");
}

int main3()
{
	Test1();
	Test2();
	Test3();
	Test4();
	Test5();
	Test6();
	Test7();
	Test8();
	Test9();

	system("pause");
	return 0;
}


测试用例:
输入的字符串包含空格(空格位于字符串最前面,空格位于字符串的最后面,空格位于字符串中间,字符串中有连续多个空格)
输入的字符串中没有空格
特殊输入测试(字符串中十个NULL指针、字符串十个空字符串、字符串中只有一个空格字符,字符串中只有连续多个空格)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值