题目:实现一个函数,把字符串中的每个空格替换为”%20”。
题目背景:网络编程中URL参数中的特殊字符,如空格,#等需要转换为服务器可以识别的字符,转换规则是在%后面加上其ASCII码的两位十六进制表示。空格的ASCII码是32,十六进制为0x20,空格被替换为%20。
首先:新字符串还是原字符串?
若是新字符串,则分配可容纳空间,然后扫描原字符串,遇见空格特殊处理,其余字符原样复制。这没啥难度。
若是原字符串上,考虑2个问题:
- 空格从占1位扩展到3位,增加2位,不能覆盖其后的原值;
- 因为扩充,原字符串后面要有足够大的空间供替换
解决思路:每个空格会增加2位后移,则根据每个非空格字符前的空格数目,可以计算出该字符的最终位置。为了不覆盖后面内容,我们从后往前扫描,先移动后面的覆盖新内存,再往前,移动覆盖后面的内存。 O(n)
笨办法:从前往后扫描,遇到空格,则把该空格后面的字符串整体后移。这样导致越往后的字符串被移动的次数越多,不必要的开销。 O(n2) 。
// offer-04-string-replace.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
char * replace(char str[], int length)
{
// 字符串NULL指针,空串判断
if (str == nullptr || length <= 0)
return str;
// 统计字符个数和空格个数
int originLength = 0;
int numberOfSpace = 0;
int i = 0;
while (str[i] != '\0')
{
++originLength;
if (str[i] == ' ')
++numberOfSpace;
++i;
}
// 由空格数计算新串位置。若超出范围则返回
int newlength = originLength + 2 * numberOfSpace;
if (newlength > length)
return str;
cout << newlength << endl << originLength << endl;
int indexOfOrigin = originLength;
int indexOfnew = newlength;
// 当扫描到首部,或者空格处理完毕
while (indexOfOrigin >= 0 && indexOfnew > indexOfOrigin)
{
// 当遇空格时,indexOfnew多走两位
// 走完空格两者相遇
if (str[indexOfOrigin] == ' ')
{
str[indexOfnew--] = '0';
str[indexOfnew--] = '2';
str[indexOfnew--] = '%';
}
else
{
// 普通字符直接赋值,均往前走一位
str[indexOfnew--] = str[indexOfOrigin];
}
// 每次迭代indexOfOrigin都往前走一位
--indexOfOrigin;
}
return str;
}
int main()
{
char str[100] = {"We are happy."};
char str[100] = {" "};
cout << str << endl;
cout << replace(str, 100) << endl;
return 0;
}