1. 程式人生 > >從一個字串中去除多餘的空格。

從一個字串中去除多餘的空格。

      字串中如果有一個地方由一個或多個連續的空格組成,就把它們改成單個空格字元。注意當遍歷整個字串時要確保它以NUL字元結尾。

      此處的空格的含義包括但不限於空格字元,為什麼呢?空格、水平製表、垂直製表、換頁、換行、回車在控制檯輸出的時候都會讓我們感覺字元之間由空格隔開了,所以,在遍歷字串的時候,應該對上述特殊字元進行處理。只有這樣,才更符合我們的習慣。

#include<stdio.h>
#include<assert.h>
#define NUL '\0'

int 
is_white(int ch)
{
	return ' ' == ch || '\t' == ch || '\v' == ch 
		|| '\f' == ch || '\n' == ch || '\r' == ch;
}

void
deblank(char *str) {
	assert(NULL != str);
	
	/*
	**將兩個指標都指向字串的首部。
	*/
	char *src = str;
	char *dest = str;
	
	/*
	**遍歷整個字元陣列
	*/
	for (; *src != NUL;) {
		
		/*
		**首次出現空格,進行復制,
		**緊接著再次出現,直接跳過。
		*/
		if (is_white(*src)) {
			*dest++ = ' ';
			src++;
			while (is_white(*src)) {
				src++;
			}
		}
		
		/*
		**如果不是空格的話,後面的值複製到前面去。
		*/
		else {
			*dest++ = *src++;
		}
	}
	
	/*
	**新增結束符 '\0'。
	*/
	*dest = NUL;
}

int main() {
	char str[] = "I\t\t\tlike      it   !";
	printf("刪除多餘的空格前:\n%s\n", str);
	deblank(str);
	printf("刪除多餘的空格後:\n%s\n", str);
	return 0;
}
      處於對程式健壯性的考慮,我在刪除多餘空格函式deblank函式體最前面加上了斷言,只有輸入的指標引數非空進行後續操作才是合法的,不然會產生不可預料的後果。本程式在VS2017下編譯執行通過。

對程式進行分析,我們可以發現,判斷是否首次是否為“空格”,出現了兩重迴圈,我在第一次創作這篇部落格的半個月後,突然想到了改進版本:

  • 新的版本只出現了一重迴圈
#include<stdio.h>
#include<assert.h>
#define NUL '\0'

int 
is_white(int ch)
{
	return ' ' == ch || '\t' == ch || '\v' == ch 
		|| '\f' == ch || '\n' == ch || '\r' == ch;
}

void
deblank(char* str) 
{
	assert(NULL != str);
	/*
	**將兩個指標都指向字串的首部。
	*/
	int tag = false;//判斷是否為首次出現空格。
	char *src = str;
	char *dest = src;
	/*
	**遍歷整個字元陣列
	*/
	for (; *src != NUL;) {

		/*
		**首次出現空格,進行復制,
		**緊接著再次出現,直接跳過。
		*/
		if (is_white(*src))
		{
			*dest = ' ';
			if (tag) {
				dest++;
				tag = false;
			}
			src++;
		}
		else
		{
			tag = true;
			*dest++ = *src++;
		}
	}

	/*
	**新增結束符 '\0'。
	*/
	*dest = NUL;
}

int 
main() {
	char str[] = "I\t\t\tlike      it   !";
	printf("刪除多餘的空格前:\n%s\n", str);
	deblank(str);
	printf("刪除多餘的空格後:\n%s\n", str);
	return 0;
}