一个小题目(单词统计)

今天休息的时候看到一个关于单词统计的小题目:

[b]统计一段由字符和和空格组成的字符串中有多少个单词[/b]

题目一看觉得很简单,无非是遍历字符串,然后根据字母是不是空格之类的来统计单词的个数。博主用了一个状态机来做这件事,我觉得颇有新意,所以就记下心来了。后面的留言有人觉得博主这是把简单问题复杂化,其实我觉得不然。最近在看《设计模式精解》,开篇作者提出的观点我就觉得非常好:需求总是在发生变化的,我们必须让我们写出的代码能够适应变化,而不是为预防变化而费尽必力。一语中的,想起大三的时候刚参与实习的时候,那个时候认为需求一旦定下来了就没有理由变,从而把责任怪罪到定义需求的人上面去,其实是多么狭隘。同样,我觉得两种做法的区别就是,后者更能适应需求的变化。想想,如果字符串除了空格和字符,还加上了各种符号啊之类的,前者的代码写起来就不那么好看了,从而也不好维护了。

下面是我写的两种实现方法:

#include
using namespace std;

/** description:
** given a string of alpha and spaces,
** return how many words are there in the string
** Words are seperated by space(s)
**/

int wordsCount( const char* str )
{
if( str == NULL )
return 0;
int count = 0;
char cur;
while( cur = *str )
{
if( cur == ' ' )
while( *(++str)!='\0' && *str==' ' );
else
{
count++;
while( *(++str)!='\0' && *str!=' ' );
}
}
return count;
}

/** now let's try another solution with state machine */
int wordsCountSM( const char* str )
{
enum STATE { InitState, SpaceState, AlphaState };
int count = 0;
char cur;
STATE state = InitState;
while( cur = *str++ )
{
switch(state)
{
case InitState:
if( cur == ' ' )
state = SpaceState;
else
state = AlphaState;
break;
case SpaceState:
if( cur != ' ' )
state = AlphaState;
break;
case AlphaState:
if( cur == ' ' )
{
state = SpaceState;
count ++;
}
break;
default:
break;
}
}
if ( state == AlphaState )
count++;
return count;
}


int main()
{
char* test1 = "this is a normal string";
char* test2 = " this is a abnormal string";
char* test3 = "this is an abnormal string ";
char* test4 = " this is an abnormal string ";
char* tests[4] = { test1, test2, test3, test4 };
for( int i=0; i<4; i++ )
{
cout< }
return 0;
}


相比之下,其实写第一种实现方法的时候花了我比较多的时间,因为我很害怕出错,而第二种实现方法很规则,只要照着状态机的转移图写就行了,不容易出错,下面是我画的状态图:

[img]http://dl.iteye.com/upload/attachment/0072/3215/fd35b9cf-ffe4-30ea-828b-5581ff672fe8.jpg[/img]
单词数增加的途径只有两个:从AlphaState->SpaceState,或者是从AlphaState到字符串结束。当需求发生变化时,我们或者添加新的状态,或者对状态的转移条件做一定的修改,很方便,而且不容易出错。

你可能感兴趣的:(实践,编程,设计模式)