再来积累一道题。
题目描述
统计一个英文句子中单词的个数,假定句子中只包含字母和空格,各单词之间用空格分隔,单词之间的空格可以有多个。
样例输入:i am student
样例输出:3
思路
要看一个英文句子中有几个单词,有两种方法。
- 看这个语句中有几个单词与单词之间的空档,假设有x个空档,那么单词个数就有(x+1)个。
//注:空档不是空格,因为单词之间有多个空格。多个空格组成空档。 - 把这个句子以空档为间隔,分成多个字符串,看能分成几个子字符串。
解决方案1
第一种方法,使用类来解决。代码如下:
//【这个程序的思路其实就是寻找存在于两个单词中间的空挡有多少个】
string s1;
getline(cin, s1, '\n');
int countSpace = 0;//记录空格个数
bool lead = (s1[0] != ' ');
//这里去掉括号也是可以的,赋值时先计算右侧表达式的值,再赋给左侧变量
//这里是看输入的字符串前面有没有空格,如果没有的话,lead为1
for (unsigned int i = 0; i < s1.length(); i++)
//这里是对每一个下标都进行判断,外层是遍历每一个下标
//但是内层还有一个for循环,内层的是用来跳过多个相同的空格的
{
if (s1[i] == ' ')//如果某一个元素是空格,那么就要看它下面的元素是不是空格
{
for (; i < s1.length() && s1[i] == ' '; i++);
//下标首先要小于字符串的总长度,并且当前这个索引对应的元素也得为空格
//满足这两个条件,索引才自增。
//下标循环到下一个非空格的字符
countSpace += lead && (i != s1.length());
//前面这个lead就是判断一下每一个句子的开头是不是含有空格
//只起这一个作用,之后lead就一直是1了
//【这个程序的思路其实就是寻找存在于两个单词中间的空挡有多少个】
//所以如果lead==0,说明最开始的地方就有空格,那么这个时候是不能算在内的
//当然,如果说经历了上面那个跳过空格的for循环后,索引i==s1.length(),
//说明这个句子的最后全是一堆空格,这堆空格后面也没有单词了
//所以必须要i!=s1.length(),或者这里写i<s1.length()也可以。
//同时满足既不是开头的空格,也不是最末尾的空格的空挡,countSpace才计数
lead = 1;
}
}
cout << countSpace + 1 << endl;
这里补充一下中的getline():
cin有其缺陷,cin会忽略(传递并忽略)任何前导白色空格字符
例如空格、制表符、换行符
cin一接触到第一个非空格字符即开始阅读,当读取到下一个空白字符就停止读取
<string>中的getline()就能弥补这个不足。【注意是<string>里的!】
getline()的参数:getline(is,&str,delim)
is: inputStream,输入流,例如cin
&str, string类型的引用,用来储存输入流中的流信息
delim: char类型的变量,设置的截断字符,缺省为遇到'\n'终止。
解决方案2
使用里的strtok函数:
(这个strtok在VS2019里显示不安全,比较麻烦,但是下程序在devc++中可行)
char sentence[100];
char* sSentence[100];
gets(sentence);
//gets()从输入流中读取字符串,
//直至接受到换行符或EOF(End Of File,文字流的结尾,可以是标准输入或文件。)时停止,
//并将读取的结果存放在参数所指向的字符数组中。换行符不作为读取串的内容,
//读取的换行符被转换为‘\0’,由此来结束字符串。
int count = 0;
//用来计数
sSentence[count++] = strtok(sentence, " ");
//strtok首次使用需要指定sentence作为第一个参数,之后第一个参数为NULL。
//具体见下面
while (sSentence[count - 1] != NULL)//只要当前指针被定义了,就进行循环
{
sSentence[count++] = strtok(NULL, " ");//当前指针被赋值成为指向一个英语单词的指针
//之后count++,移到下一个。
}
cout << count-1 << endl;
这里需要注意一下strtok()函数的用法:
strtok(str,delim)
当strtok()在str的字符串中发现参数delim,即“分割字符”时,则会将该字符改为\0 字符;
在第一次调用时,strtok()必需给予参数str,往后的调用则将参数str设置成NULL。每次调用成功则返回指向被分割出片段的指针。
需要注意的是,使用该函数进行字符串分割时,会破坏被分解字符串的完整,调用前和调用后的串已经不一样了。
具体看这:https://www.cnblogs.com/zhoudingcocng/p/6554418.html
gets()函数用法见注释。
这些代码作为积累,以后再碰到类似的就能想起来了。