题目:请实现一个函数,把字符串中的每个空格替换成“%20”。例如输入“We are happy.”,则输出”We%20are%20happy.”。
我们可以先遍历一次字符串,这样就能统计出字符串中空格的总数,并可以由此计算出替换之后的字符串的总长度。每替换一个空格,长度增加2,因此替换以后字符串的长度等于原来的长度加上2乘以空格数目。我们还是以前面的字符串We are happy.”为例,We are happy.”这个字符串的长度是14(包括结尾符号’\0’),里面有两个空格,因此替换之后字符串的长度是18。
我们从字符串的后面开始复制和替换。首先准备两个指针,P1和P2。P1指向原始字符串的末尾,而P2指向替换之后的字符串的末尾(如图2.4(a)所示)。接下来我们向前移动指针P1,逐个把它指向的字符复制到P2指向的位置,直到碰到第一个空格为止。此时字符串包含如图2.4(b)所示,灰色背景的区域是做了字符拷贝的区域。碰到第一个空格之后,把P1向前移动1格,在P2之前插入字符串”%20”。由于”%20”的长度为3,同时也要把P2向前移动3格如图2.4(c)所示。
我们接着向前复制,直到碰到第二个空格(如图2.4(d)所示)。和上次一样,我们再把P1向前移动1个,并把P2向前移动3格插入”%20”(如图2.4(e)所示)。此时P1和P2指向同一位置,表明所有空格都已替换完毕。
从上面的分析我们可以看出,所有的字符都只复制一次,因此这个算法的时间效率是O(n)。
注:图中带阴影的区域表示被移动的字符。(a)把第一个指针指向字符串的结尾,把第二个指针指向替换后的字符串的末尾。(b)依次复制字符串的内容,直至第一个指针碰到第一个空格。(c)把第一个空格替换成’%20’,把第一个指针向前移动1格,把第二个指针向前移动3格。(d)依次向前复制字符串中的字符,直至碰到空格。(e)替换字符串中的倒数第二个空格,把第一个指针向前移动1格,把第二个指针向前移动3格。
下面是参考代码:
/*length为字符数组string的总容量*/
void ReplaceBlank(char string[], int length)
{
if(string == NULL || length <= 0)
return ;
/*orinalLength为字符串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 + 2 * numberOfBlank;
if(newLength > length)
return ;
itn indexOfOriginal = origianlLength;
int indexOfNew = newLength;
while(indexOfOriginal >= 0 && indexOfOriginal != indexOfNew)
{
if(string[indexOfOriginal] == ' ')
{
string[indexOfNew--] = '0';
string[indexOfNew--] = '2';
string[indexOfNew--] = '%';
}
else
{
string[indexOfNew--] = string[indexOfOriginal];
}
-- indexOfOriginal;
}
}