我在接受采访时被问到这一点,显然这是一个简单的问题,但对我而言并不是,现在仍然不明显.
给定一个字符串,计算其中的所有单词.如果重复它们无关紧要.只是文本文件中的总计数字数.单词是由空格分隔的任何东西,标点符号无关紧要,只要它是单词的一部分.
例如:
A very, very, very, very, very big dog ate my homework!!!! ==> 11 words
我的"算法"只是查找空格并递增计数器直到我达到空值.既然我没有得到这份工作,之后被要求离开,我想我的解决方案并不好?谁有更聪明的解决方案?我错过了什么吗?
Mar*_*ork 35
假设单词是空格分隔的:
unsigned int countWordsInString(std::string const& str)
{
std::stringstream stream(str);
return std::distance(std::istream_iterator<std::string>(stream), std::istream_iterator<std::string>());
}
Run Code Online (Sandbox Code Playgroud)
注意:单词之间可能有多个空格.此外,它不会捕获其他空格字符,如制表符新行或回车符.因此计算空间是不够的.
流输入运算符>>用于从流中读取字符串时.读取一个空格分隔的单词.所以他们可能正在寻找你用它来识别单词.
std::stringstream stream(str);
std::string oneWord;
stream >> oneWord; // Reads one space separated word.
Run Code Online (Sandbox Code Playgroud)
何时可以使用它来计算字符串中的单词.
std::stringstream stream(str);
std::string oneWord;
unsigned int count = 0;
while(stream >> oneWord) { ++count;}
// count now has the number of words in the string.
Run Code Online (Sandbox Code Playgroud)
变得复杂:
流可以像任何其他容器一样处理,并且有迭代器来循环它们std :: istream_iterator.在istream_iterator上使用++运算符时,它只需使用运算符>>从流中读取下一个值.在这种情况下,我们正在读取std :: string,因此它读取一个空格分隔的单词.
std::stringstream stream(str);
std::string oneWord;
unsigned int count = 0;
std::istream_iterator loop = std::istream_iterator<std::string>(stream);
std::istream_iterator end = std::istream_iterator<std::string>();
for(;loop != end; ++count, ++loop) { *loop; }
Run Code Online (Sandbox Code Playgroud)
使用std :: distance只需将所有上述内容包装在一个整洁的包中,因为它通过在第一个上面执行++来找到两个迭代器之间的距离,直到我们到达第二个.
为了避免复制字符串,我们可以偷偷摸摸:
unsigned int countWordsInString(std::string const& str)
{
std::stringstream stream;
// sneaky way to use the string as the buffer to avoid copy.
stream.rdbuf()->pubsetbuf (str.c_str(), str.length() );
return std::distance(std::istream_iterator<std::string>(stream), std::istream_iterator<std::string>());
}
Run Code Online (Sandbox Code Playgroud)
注意:我们仍将原文中的每个单词复制为临时单词.但是成本很低.
一个不太聪明,更明显的所有程序员在团队中的方法.
#include <cctype>
int CountWords(const char* str)
{
if (str == NULL)
return error_condition; // let the requirements define this...
bool inSpaces = true;
int numWords = 0;
while (*str != '\0')
{
if (std::isspace(*str))
{
inSpaces = true;
}
else if (inSpaces)
{
numWords++;
inSpaces = false;
}
++str;
}
return numWords;
}
Run Code Online (Sandbox Code Playgroud)
另一个可以工作的基于提升的解决方案(未经测试):
vector<string> result;
split(result, "aaaa bbbb cccc", is_any_of(" \t\n\v\f\r"), token_compress_on);
Run Code Online (Sandbox Code Playgroud)
更多信息可以在Boost String Algorithms Library中找到
您可以使用std :: count或std :: count_if来执行此操作。下面是一个带有std :: count的简单示例:
//Count the number of words on string
#include <iostream>
#include <string>
#include <algorithm> //count and count_if is declared here
int main () {
std::string sTEST("Text to verify how many words it has.");
std::cout << std::count(sTEST.cbegin(), sTEST.cend(), ' ')+1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
更新:由于AydinÖzcan(11月16日)的观察,我对该解决方案进行了更改。现在,单词之间可能有多个空格。:)
//Count the number of words on string
#include <string>
#include <iostream>
int main () {
std::string T("Text to verify : How many words does it have?");
size_t NWords = T.empty() || T.back() == ' ' ? 0 : 1;
for (size_t s = T.size(); s > 0; --s)
if (T[s] == ' ' && T[s-1] != ' ') ++NWords;
std::cout << NWords;
return 0;
}
Run Code Online (Sandbox Code Playgroud)