1. 程式人生 > >C++中的替換空格

C++中的替換空格

 例,請實現一個函式,把字串中的每個空格替換成“%20”。例如輸入“We are happy.”,則輸出“We%20are%20happy.”。

 分析:

          我們可以先遍歷一次字串,這樣就能統計出字串中空格的總數,並可以由此計算出替換之後的字串的總長度。每替換一個空格,長度增加2,因此替換以後字串的長度等於原來的長度加上2乘以空格數目。我們還是以前面的字串'We are happy,”為例,”We are happy‘”這個字串的長度是14(包括結尾符號'\0'),裡面有兩個空格,因此替換之後字串的長度是18。

          我們字串的後面開始複製和替換。首先準備兩個指標,P1和P2。P1指向原始字串的末尾,而P2指向替換之後的字串的末尾(如圖(a)所示)。接下來我們向前移動指標P1,逐個把它指向的字元複製到P2指向的位置,直到碰到第一個空格為止。此時字串包含如圖(b)所示,灰色背景的區域是做了字元拷貝(移動)的區域。碰到第一個空格之後,把Pl向前移動1格,在P2之前插入字串"%20"。由於"%20"的長度為3,同時也要把P2向前移動3格如圖(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 str[],int length)
{
	if(str==NULL && length<=0)
		return;

	//originalLength為字串str的實際長度
	int originalLength=0;
	int numberOfBlank=0;
	int i=0;
	while (str[i]!='\0')
	{
		++originalLength;
		if(str[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 (str[indexOfOriginal]==' ')
		{
			str[indexOfNew--]='0';
			str[indexOfNew--]='2';
			str[indexOfNew--]='%';
		} 
		else
		{
			str[indexOfNew--]=str[indexOfOriginal];
		}

		--indexOfOriginal;
	}

}

測試用例:

1)輸入的字串中包含空格(空格位於字串的最前面,空格位於字串的最後面,空格位於字串的中間,字串中有連續多個空格)。
2)輸入的字串中沒有空格
3)特殊輸入測試(字串是個NULL指標、字串是個空字串、字串只有一個空格字元、字串中只有連續多個空格)。

//測試程式碼:

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 _tmain(int argc, _TCHAR* argv[])
{
    Test1();
    Test2();
    Test3();
    Test4();
    Test5();
    Test6();
    Test7();
    Test8();
    Test9();

    return 0;
}

     效果如下:


    參考文獻:何海濤.《劍指Offer名企面試官精講典型程式設計題》.2012年.電子工業出版社