问题描述:
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
解题思路及知识点
- 题意要求将一个字符串中的每个空格进行替换,倘若从前向后进行查找和替换,很难处理,会涉及字符串覆盖问题,在这里采用从后向前进行查找和替换,这样处理比较方便,而且能避免字符串覆盖问题。
- 在求字符串长度时可利用strlen函数,格式:strlen (字符指针表达式)功能:计算给定字符串的(unsigned int型)长度,不包括'\0'在内,说明:返回s的长度,不包括结束符NULL。
- strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值(长度不包含'\0')
思路一:在查找空格同时进行字符串处理
这种解法在查找到空格的同时将数组长度增加,然后将空格后字符串元素进行移位处理,但存在重复处理,每发现一个空格,它后面的字符串元素全部得处理,其中包括前面处理过的字符串元素,占用时间和资源较多,不建议采用。(后附示意图及源码)
#include<stdio.h>
#include<string.h>
void th(char a[],int l)
{
int i=l-1,j; //将l-1的值赋给i,用i表示下标
int k;
if (a == NULL) //判断字符串是否为空或者字符串长度是否为0
{
printf("字符串为空,请重新输入\n");
return ;
}
if (l == 0)
{
printf("字符串长度为0,请重新输入\n");
return ;
}
while (i>=0) //对字符串进行遍历
{
if (a[i] == ' ') //判断a[i]元素是否为空格
{
for (j=l-1; j >i; j--)
{
a[j + 2] = a[j]; //当a[i]元素为空格时,将后面的元素全部后移两位
}
a[j] = '%';;
a[++j] = '2'; //将空格及其后两位替换为题目要求得“%20”
a[++j] = '0';
l+=2;
}
i--;
}
printf("for循环输出替换空格后的字符串 ");
for (k = 0; k< l ; k++)
{
printf("%c", a[k]); //此处为检验结果,采用for循环输出替换空格后的字符串
}
printf("\n");
return ;
}
int main()
{
int l;
char a[40] = " We are happy。 ";
printf("\t\t原字符串\t %s\n", a); //此处利用字符串性质直接利用printf语句输出原字符串
l = strlen(a); //利用strlen()函数求得字符串长度
th(a, l); //调用子函数进行替换
printf("printf语句输出替换空格后的字符串 %s\n", a); //此处利用字符串性质直接利用printf语句输出替换空格后的字符串
th(a, 0); //测试字符串长度为0
th(NULL, l); //测试字符串为空
return 0;
}
思路二:先找空格数,再进行替换
这种解法可以直接发现字符串中本来不存在空格的情况 ,避免处理有些字符串浪费时间和资源,且避免重复处理。
- 求空格数:确定替换后的字符串长度;
- 替换空格:将空格替换成字符串”%20”。(后附示意图及源码)
源码1: C语言
#include<stdio.h>
#include<string.h>
void th(char a[], int l)
{
int i = 0, j=0; //将l-1的值赋给i,用i表示下标,j作为空格计数器
int h,k,d;
if (a == NULL) //判断字符串是否为空或者字符串长度是否为0
{
printf("字符串为空,请重新输入\n");
return ;
}
if (l == 0)
{
printf("字符串长度为0,请重新输入\n");
return ;
}
while (a[i]!='\0') //对字符串进行遍历
{
if (a[i] == ' ') //判断a[i]元素是否为空格
{
j++; //当a[i]元素为空格时,将计数器j+1
}
i++;
}
h = l + j * 2;
d = l + j * 2; //将替换完空格的字符串长度赋值给h和d
if (l >= d)
{
printf("原字符串中无空格,请重新输入\n");
return;
}
while (l >= 0 && h >= 0)
{
if (a[l] == ' ') //判断a[i]元素是否为空格
{
a[h--] = '0';;
a[h--] = '2'; //当a[i]元素为空格时,将空格及其后两位替换为题目要求得“%20”
a[h--] = '%';
}
else
{
a[h--] = a[l];
}
l--;
}
printf("for循环输出替换空格后的字符串 ");
for (k = 0; k < d; k++)
{
printf("%c", a[k]); //此处为检验结果,采用for循环输出替换空格后的字符串
}
printf("\n");
}
int main()
{
int l;
char a[40] = " We are happy。 ";
printf("\t\t原字符串\t %s\n", a); //此处利用字符串性质直接利用printf语句输出原字符串
l = strlen(a); //利用strlen()函数求得字符串长度
th(a, l); //调用子函数进行替换
printf("printf语句输出替换空格后的字符串 %s\n", a); //此处利用字符串性质直接利用printf语句输出替换空格后的字符串
th(a, 0); //测试字符串长度为0
th(NULL, l); //测试字符串为空
return 0;
}
源码2:C++语言(牛客网在线编程剑指offer测试通过)
#include<iostream>
#include<string>
using namespace std;
class Solution {
public:
void replaceSpace(char *str, int length) {
int i = 0, j=0,h,d; //将l-1的值赋给i,用i表示下标
if (str == NULL) //判断字符串是否为空或者字符串长度是否为0
{
cout <<"字符串为空,请重新输入" << endl;
return ;
}
if (length == 0)
{
cout << "字符串长度为0,请重新输入" << endl;
return ;
}
while (str[i] != '\0') //对字符串进行遍历
{
if (str[i] == ' ') //判断str[i]元素是否为空格
{
j++; //当str[i]元素为空格时,将计数器j+1
}
i++;
}
h = length + j * 2;
d = length + j * 2; //将替换完空格的字符串长度赋值给h和d
if (length >= d)
{
cout << "原字符串中无空格,请重新输入" << endl;
return;
}
while (length >= 0 && h >= 0)
{
if (str[length] == ' ') //判断str[i]元素是否为空格
{
str[h--] = '0';;
str[h--] = '2'; //当str[i]元素为空格时,将空格及其后两位替换为题目要求得“%20”
str[h--] = '%';
}
else
{
str[h--] = str[length];
}
length--;
}
}
};
int main()
{
int l;
char a[40] = " We are happy。 ";
cout << a << endl; //输出原字符串
l = strlen(a); //利用strlen()函数求得字符串长度
Solution b;
b.replaceSpace(a, l); //调用子函数进行替换
cout << a << endl; //输出替换空格后的字符串
b.replaceSpace(a, 0); //测试字符串长度为0
b.replaceSpace(NULL, l); //测试字符串为空
return 0;
}
注意问题:
- 在查找时要注意字符串为NULL或者字符串长度为0的情况;
- 在测试时要注意考虑各种情况,不能遗漏;测试时,将空格放在最前,最后和中间某位置以及字符串为NULL或者字符串长度为0;
- 处理字符串要添加处理字符串的头文件 #include<string.h>或者#include<string>;
- strlen函数返回的是字符串长度,在处理时注意这个返回值并非是元素下标。