user-0 提问: 字符串计算单词个数

回复:
user: user-1
content: 源代码如下：  #include <stdio.h> #include <ctype.h> #include <string.h>  int is_upper(char *p) { 	while(*p) 	{ 		if(islower(*p)) return 0; 		p++; 	} 	return 1; }  int main(void) { 	char str[] = "FORBES The CEO of Boloco's Social Media Strategy"; 	char *p; 	int count = 0; 	 	p = strtok(str, " "); 	 	while(p != NULL) 	{ 		if(is_upper(p)) 		{ 			count++; 			printf("%d:\t%s\n", count, p); 		} 		p = strtok(NULL, " "); 	} 	 	return 0;	 }   运行结果如下： 引用1:      FORBES 2:      CEO

user: user-2
content: 引用 2 楼 火柴先生 的回复:引用 1 楼 自信男孩 的回复:先确定单词，然后遍历单词，判断是否有小写字符。我认为最后判断应该是：是否全为大写字符 我的描述不是这样吗？先确定单词，就是在每个单词后面的第一个空格用'\0'填充，然后再遍历这个单词是不是全大写，这样应该没问题吧。 对于加不加'\0'都没关系，因为知道单词的开头，知道单词的结尾，做差就知道单词的长度了～

user: user-0
content: 引用 5 楼 sdhexu 的回复:好人做到底，给你完善一下代码吧：   // 状态机 三种状态 public enum MachineState { 	START, 	UPPER_WORDS, 	NOTUPPER_WORDS }  // 判断一个字符是否为空白 private bool IsSpace( char c ) { 	return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ); }  // 判断一个字符是否为单词的分隔符，可以视情况将其他标点符号加入 private bool IsSeparator( char c ) { 	return IsSpace(c) || ( c == ',' || c == '.' ); }  // 判断所有字母为大写的单词个数 public int GetUpperWordsCount( string p ) { 	MachineState state = MachineState.START; 	int count = 0; 	foreach( char c in p ) 	{ 		switch( state ) 		{ 			case MachineState.START: 				if( c >= 'A' && c <='Z' )  // 如果第一个字符为大写，状态改变 					state = MachineState.UPPER_WORDS; 				else if( IsSpace( c ))     // 如果是空白，保持开始状态 					break; 				else                       // 其他情况，小写状态 					state = MachineState.NOTUPPER_WORDS;  				break; 				 			case MachineState.UPPER_WORDS: 				if( IsSeparator( c ))   // 如果遇到单词分隔，计数并改状态 				{ 					++count; 					state = MachineState.START; 				} 				else if( c>='A' && c <= 'Z' ) // 如果还是大写，保持状态 					break; 				else   // 其他情况（单词有不是大写的字符），进入非大写状态 					state = MachineState.NOTUPPER_WORDS; 				break; 				 			case MachineState.NOTUPPER_WORDS: 			    if( IsSeparator( c ))   // 直到遇到分隔符，否则都是非大写状态 				{ 					state = MachineState.START; 				} 				break;          } 	} } 今天看了下代码，发现您忽视了是要输出全为大写字母的单词的情况，如果考虑输出，还能否在一次遍历的情况下完成，这看起来很难。

user: user-0
content: 引用 6 楼 sdhexu的回复:词法分析器，有穷自动状态机，是编译原理中的知识，它的好处是，连续多个空白符，很容易处理，不会影响计算结果。只遍历一遍字符，效率很高。。理解困难的话，画一个状态图，就容易理解了。   效率的确高，这是我C语言考试最后一道编程题里面的一部分内容，明天再好好看看您的代码，十分感谢！之前也上过编译原理的课，可以看出自己的确学艺不精，要好好努力！

user: user-3
content: 词法分析器，有穷自动状态机，是编译原理中的知识，它的好处是，连续多个空白符，很容易处理，不会影响计算结果。只遍历一遍字符，效率很高。。理解困难的话，画一个状态图，就容易理解了。

user: user-3
content: 好人做到底，给你完善一下代码吧：   // 状态机 三种状态 public enum MachineState { 	START, 	UPPER_WORDS, 	NOTUPPER_WORDS }  // 判断一个字符是否为空白 private bool IsSpace( char c ) { 	return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ); }  // 判断一个字符是否为单词的分隔符，可以视情况将其他标点符号加入 private bool IsSeparator( char c ) { 	return IsSpace(c) || ( c == ',' || c == '.' ); }  // 判断所有字母为大写的单词个数 public int GetUpperWordsCount( string p ) { 	MachineState state = MachineState.START; 	int count = 0; 	foreach( char c in p ) 	{ 		switch( state ) 		{ 			case MachineState.START: 				if( c >= 'A' && c <='Z' )  // 如果第一个字符为大写，状态改变 					state = MachineState.UPPER_WORDS; 				else if( IsSpace( c ))     // 如果是空白，保持开始状态 					break; 				else                       // 其他情况，小写状态 					state = MachineState.NOTUPPER_WORDS;  				break; 				 			case MachineState.UPPER_WORDS: 				if( IsSeparator( c ))   // 如果遇到单词分隔，计数并改状态 				{ 					++count; 					state = MachineState.START; 				} 				else if( c>='A' && c <= 'Z' ) // 如果还是大写，保持状态 					break; 				else   // 其他情况（单词有不是大写的字符），进入非大写状态 					state = MachineState.NOTUPPER_WORDS; 				break; 				 			case MachineState.NOTUPPER_WORDS: 			    if( IsSeparator( c ))   // 直到遇到分隔符，否则都是非大写状态 				{ 					state = MachineState.START; 				} 				break;          } 	} }

user: user-3
content: 很简单的词法分析器，有穷自动状态机。。效率是最高的，没有之一。   public enum MachineState {           START,           UPPER_WORDS, }  public int GetUpperWordsCount( string p ) {          MachineState state = MachineState.START;          int count = 0;          foreach( char c in p )          {                 switch( state )                 {                       case MatchineState.START:                             if( c >= 'A' && c <='Z' )                                   state = MachineState.UPPER_WORDS;                             break;                        case MatchineState.UPPER_WORDS:                              if( c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == ',' || c == '.' )                              {                                    ++count;                                    state = MatchineState.START;                              }                              else if( c>='A' && c <= 'Z' )                                     break;                              else                                    state = MatchineState.START;                             break;                 }          } }

user: user-4
content: 我也认为应该先确定单词，在检查单词是否全部为大写。

user: user-0
content: 引用 1 楼 自信男孩 的回复:先确定单词，然后遍历单词，判断是否有小写字符。我认为最后判断应该是：是否全为大写字符

user: user-2
content: 先确定单词，然后遍历单词，判断是否有小写字符。