问题:统计字符串\(str\)中单词\(word\)出现的次数。已知字符串中的单词用一个空格或者多个空格隔开。
输入格式:有2行,第1行是字符串\(str\),第2行是不带空格的单词\(word\)。
分析:使用string来存储字符串\(str\)和单词\(word\)。可以通过string的find方法查找子串的方式统计单词出现次数,例如字符串和单词内容如下:
nice to meet you and how are you thank you very much
you
nice to meet you and how are you thank you very much
you
nice to meet you and how are you thank you very much you
初步想法是用find方法统计单词you
在字符串nice to meet you and how are you thank you very much
出现次数:

#include<iostream>
#include<string>
using namespace std;
int main()
{
int cnt = 0;
string str,word;
getline(cin,str);
cin>>word;
//查找单词word第一次出现的位置
size_t pos = str.find(word);
while(pos != string::npos){ //查找到
cnt++;
//从pos+word.length()起继续查找单词word第一次出现的位置
pos = str.find(word,pos+word.length());
}
cout<<cnt<<endl;
return 0;
}
#include<iostream>
#include<string>
using namespace std;
int main()
{
int cnt = 0;
string str,word;
getline(cin,str);
cin>>word;
//查找单词word第一次出现的位置
size_t pos = str.find(word);
while(pos != string::npos){ //查找到
cnt++;
//从pos+word.length()起继续查找单词word第一次出现的位置
pos = str.find(word,pos+word.length());
}
cout<<cnt<<endl;
return 0;
}
#include<iostream> #include<string> using namespace std; int main() { int cnt = 0; string str,word; getline(cin,str); cin>>word; //查找单词word第一次出现的位置 size_t pos = str.find(word); while(pos != string::npos){ //查找到 cnt++; //从pos+word.length()起继续查找单词word第一次出现的位置 pos = str.find(word,pos+word.length()); } cout<<cnt<<endl; return 0; }
但是考虑下面的情况:
nice to meet you and how are you thank you and your friends very much
you
nice to meet you and how are you thank you and your friends very much
you
nice to meet you and how are you thank you and your friends very much you
因为your
中也完整出现了单词you
,也会被统计到。find方法是查找子串,如果字符串\(str\)中某个单词中完整出现了单词\(word\)(此外还有其他字符),用上面的方法也会认为单词\(word\)出现了一次导致统计结果出错!那么该如何解决问题呢?
其实我们可以用find方法统计字符串" "+str+" "
中单词" "+word+" "
出现的次数,这样处理就能有效避免上面的问题(注意体会并掌握这种处理方法):
#include<iostream>
#include<string>
using namespace std;
int main()
{
int cnt = 0;
string str,word;
getline(cin,str);
str = " "+str+" ";
cin>>word;
word = " "+word+" ";
//查找单词word第一次出现的位置
size_t pos = str.find(word);
while(pos != string::npos){
cnt++;
//从pos+word.length()起继续查找单词word第一次出现的位置
pos = str.find(word,pos+word.length());
}
cout<<cnt<<endl;
return 0;
}
#include<iostream>
#include<string>
using namespace std;
int main()
{
int cnt = 0;
string str,word;
getline(cin,str);
str = " "+str+" ";
cin>>word;
word = " "+word+" ";
//查找单词word第一次出现的位置
size_t pos = str.find(word);
while(pos != string::npos){
cnt++;
//从pos+word.length()起继续查找单词word第一次出现的位置
pos = str.find(word,pos+word.length());
}
cout<<cnt<<endl;
return 0;
}
#include<iostream> #include<string> using namespace std; int main() { int cnt = 0; string str,word; getline(cin,str); str = " "+str+" "; cin>>word; word = " "+word+" "; //查找单词word第一次出现的位置 size_t pos = str.find(word); while(pos != string::npos){ cnt++; //从pos+word.length()起继续查找单词word第一次出现的位置 pos = str.find(word,pos+word.length()); } cout<<cnt<<endl; return 0; }
如果我们用字符数组存储字符串,那么该如何统计单词出现次数呢?其实我们使用前一小节例题中的方法将字符串中的每个单词找出来:
#include<iostream>
#include<cstring>
using namespace std;
char str[1010];
int main()
{
char last = ' '; //记录上一个字符,体会这里默认值设置成空格字符的用途
fgets(str,sizeof(str),stdin);
int n = strlen(str); //n是字符串长度
int start = 0; //start记录单词首字符下标
//处理fgets输入字符串末尾可能额外附带的'\n'
if(n && str[n-1]=='\n') str[--n] = '\0';
for(int i=0;i<=n;i++){ //注意这里的条件是i<=n,而不是一般遍历字符串的i<n
//如果上一个字符是空格、当前字符不是空格,则找到一个新单词
if(last == ' ' && str[i] != ' '){
start = i; //记录找到的单词的首字符下标
}else if(last != ' ' && (str[i] == ' ' || str[i] == '\0')){ //单词结束
//从start到i-1是一个单词
for(int j=start;j<i;j++) cout<<str[j];
cout<<endl;
}
//last更新为当前字符,在下一次循环中就成了“上一个字符”
last = str[i];
}
return 0;
}
#include<iostream>
#include<cstring>
using namespace std;
char str[1010];
int main()
{
char last = ' '; //记录上一个字符,体会这里默认值设置成空格字符的用途
fgets(str,sizeof(str),stdin);
int n = strlen(str); //n是字符串长度
int start = 0; //start记录单词首字符下标
//处理fgets输入字符串末尾可能额外附带的'\n'
if(n && str[n-1]=='\n') str[--n] = '\0';
for(int i=0;i<=n;i++){ //注意这里的条件是i<=n,而不是一般遍历字符串的i<n
//如果上一个字符是空格、当前字符不是空格,则找到一个新单词
if(last == ' ' && str[i] != ' '){
start = i; //记录找到的单词的首字符下标
}else if(last != ' ' && (str[i] == ' ' || str[i] == '\0')){ //单词结束
//从start到i-1是一个单词
for(int j=start;j<i;j++) cout<<str[j];
cout<<endl;
}
//last更新为当前字符,在下一次循环中就成了“上一个字符”
last = str[i];
}
return 0;
}
#include<iostream> #include<cstring> using namespace std; char str[1010]; int main() { char last = ' '; //记录上一个字符,体会这里默认值设置成空格字符的用途 fgets(str,sizeof(str),stdin); int n = strlen(str); //n是字符串长度 int start = 0; //start记录单词首字符下标 //处理fgets输入字符串末尾可能额外附带的'\n' if(n && str[n-1]=='\n') str[--n] = '\0'; for(int i=0;i<=n;i++){ //注意这里的条件是i<=n,而不是一般遍历字符串的i<n //如果上一个字符是空格、当前字符不是空格,则找到一个新单词 if(last == ' ' && str[i] != ' '){ start = i; //记录找到的单词的首字符下标 }else if(last != ' ' && (str[i] == ' ' || str[i] == '\0')){ //单词结束 //从start到i-1是一个单词 for(int j=start;j<i;j++) cout<<str[j]; cout<<endl; } //last更新为当前字符,在下一次循环中就成了“上一个字符” last = str[i]; } return 0; }
那么只需要判断每次找出来的单词是不是\(word\)就能统计单词\(word\)的数量了:
#include<iostream>
#include<cstring>
using namespace std;
char str[1010],word[1010];
int main()
{
int cnt = 0;
char last = ' '; //记录上一个字符,体会这里默认值设置成空格字符的用途
fgets(str,sizeof(str),stdin);
cin>>word;
int n = strlen(str); //n是字符串长度
int start = 0; //start记录单词首字符下标
//处理fgets输入字符串末尾可能额外附带的'\n'
if(n && str[n-1]=='\n') str[--n] = '\0';
for(int i=0;i<=n;i++){ //注意这里的条件是i<=n,而不是一般遍历字符串的i<n
//如果上一个字符是空格、当前字符不是空格,则找到一个新单词
if(last == ' ' && str[i] != ' '){
start = i;
}else if(last != ' ' && (str[i] == ' ' || str[i] == '\0')){ //单词结束
int j,k;
//从start到i-1是一个单词
//比较字符串str的start到i-1的字符与word的字符是否依次相等
for(j=start,k=0;j<i && word[k];j++,k++){
if(str[j] != word[k]) break;
}
//全部匹配相等,并且单词都匹配结束,那么匹配到单词word
if(j==i && word[k]=='\0') cnt++;
}
//last更新为当前字符,在下一次循环中就成了“上一个字符”
last = str[i];
}
cout<<cnt<<endl;
return 0;
}
#include<iostream>
#include<cstring>
using namespace std;
char str[1010],word[1010];
int main()
{
int cnt = 0;
char last = ' '; //记录上一个字符,体会这里默认值设置成空格字符的用途
fgets(str,sizeof(str),stdin);
cin>>word;
int n = strlen(str); //n是字符串长度
int start = 0; //start记录单词首字符下标
//处理fgets输入字符串末尾可能额外附带的'\n'
if(n && str[n-1]=='\n') str[--n] = '\0';
for(int i=0;i<=n;i++){ //注意这里的条件是i<=n,而不是一般遍历字符串的i<n
//如果上一个字符是空格、当前字符不是空格,则找到一个新单词
if(last == ' ' && str[i] != ' '){
start = i;
}else if(last != ' ' && (str[i] == ' ' || str[i] == '\0')){ //单词结束
int j,k;
//从start到i-1是一个单词
//比较字符串str的start到i-1的字符与word的字符是否依次相等
for(j=start,k=0;j<i && word[k];j++,k++){
if(str[j] != word[k]) break;
}
//全部匹配相等,并且单词都匹配结束,那么匹配到单词word
if(j==i && word[k]=='\0') cnt++;
}
//last更新为当前字符,在下一次循环中就成了“上一个字符”
last = str[i];
}
cout<<cnt<<endl;
return 0;
}
#include<iostream> #include<cstring> using namespace std; char str[1010],word[1010]; int main() { int cnt = 0; char last = ' '; //记录上一个字符,体会这里默认值设置成空格字符的用途 fgets(str,sizeof(str),stdin); cin>>word; int n = strlen(str); //n是字符串长度 int start = 0; //start记录单词首字符下标 //处理fgets输入字符串末尾可能额外附带的'\n' if(n && str[n-1]=='\n') str[--n] = '\0'; for(int i=0;i<=n;i++){ //注意这里的条件是i<=n,而不是一般遍历字符串的i<n //如果上一个字符是空格、当前字符不是空格,则找到一个新单词 if(last == ' ' && str[i] != ' '){ start = i; }else if(last != ' ' && (str[i] == ' ' || str[i] == '\0')){ //单词结束 int j,k; //从start到i-1是一个单词 //比较字符串str的start到i-1的字符与word的字符是否依次相等 for(j=start,k=0;j<i && word[k];j++,k++){ if(str[j] != word[k]) break; } //全部匹配相等,并且单词都匹配结束,那么匹配到单词word if(j==i && word[k]=='\0') cnt++; } //last更新为当前字符,在下一次循环中就成了“上一个字符” last = str[i]; } cout<<cnt<<endl; return 0; }