计算字符串中的单词

Posted

技术标签:

【中文标题】计算字符串中的单词【英文标题】:Counting words in a string 【发布时间】:2014-07-19 13:44:53 【问题描述】:

我正在自学 C++。我编写了这个程序来数。我知道这不是最好的方法,但这是我能想到的。

我使用空格来计算单词的数量。这就是问题所在。

countWords("");   // ok, 'x.empty()' identifies it as an empty string.
countWords("  "); // 'x.empty()' fails, function returns 1.

p.s 我希望这个程序不计算诸如“!”、“?”之类的符号。作为词。这是我的代码:

#include <iostream>
#include <string>

int countWords(std::string x);

int main() 
    std::cout << countWords("Hello world!");


int countWords(std::string x) 
    if(x.empty()) return 0; // if the string is empty
    int Num = 1;              

    for(unsigned int i = 0; i < x.size(); i++) 
        // if there is a space in the start
        if(x[0] == ' ') continue;

        // second condition makes sure that i don't count 2 spaces as 2 words
        else if(x[i] == ' ' && x[i - 1] != ' ') Num++;
    
    return Num;

【问题讨论】:

首先,empty 检查是多余的。其次,看看你脑海中的" 123 456 789" 会发生什么。为简洁起见,只需调用std::unique,然后再调用std::count空格即可。对于一次通过,std::finding 下一个空格和std::find_if_noting 下一个非空格重复也可以。 您在开始循环之前将Num 设置为1,因此在第二个示例中,代码必须返回1 x.empty() 在第二种情况下也必须返回false,因为您的字符串不为空(包含一个空格) @UnholySheepm,我知道。但是如果我将 Num 设置为零,那么我就无法得到想要的结果。 @Blastfurnace 否,请参阅第一个条件。当第一个为真时,第二个永远不会运行。顺便说一句,+1 为您提供帮助。 @user3834119 我假设你的意思是你得到的比预期少 1,在这种情况下你可以添加另一个测试语句:x[i]=='\0' 因为零终止是字符串的结尾 【参考方案1】:

您的功能可以简化为:

int countWords(std::string x) 

    int Num = 0;      
    char prev = ' ';

    for(unsigned int i = 0; i < x.size(); i++) 

        if(x[i] != ' ' && prev == ' ') Num++;

        prev = x[i];
    
    return Num;

这是demo

编辑:跟进评论:

这是用' '替换其他字符的简单方法,认为可能有一个构建方法:

void replace(std::string &s, char replacer, std::set<char> &replacies)

    for (int i=0; i < s.size(); i++)
        if (replacies.count(s[i])) s[i] = replacer;


demo

【讨论】:

+1 以获得良好的编码。我希望该程序适用于“?”,“!”之类的符号,这些符号不应算作单词。你能推荐一个方法吗? @user3834119,所以您基本上希望"?","!".. 被视为现在处理空格,也许您可​​以将这些字符替换为空格。 @Ajavall 是的。你是怎么做到的(用空格替换它们)?【参考方案2】:

您的答案的问题是您正在计算后面有“ ”符号的单词数。我相信您从 Num = 1 开始,因为您不会计算最后一个单词。但是,仅当您正在分析的字符串不以 ' ' 结尾时才会发生这种情况。否则,您将多计算 1 个字。解决此问题的最简单方法是添加

if(x.back() == ' ')
    Num--;

在返回答案之前。

【讨论】:

x[x.size() - 1] 只是x.back()【参考方案3】:

您的解决方案不充分。应用时会失败:

前导空格 尾随空格 只有空格 其他形式的空格

您需要重新考虑您的算法应该如何工作,因为您只需要一个更复杂的方法来涵盖所有用例。

或者您可以避免重新发明***并使用 标准库 已经提供的内容,例如:

int countWords(const std::string& s) 
    std::istringstream isss;
    return std::distance(std::istream_iterator<std::string>iss,
                         std::istream_iterator<std::string>);

这里std::istringstreamstd::istream_iterator用于对字符串进行分词,std::distance用于获取提取的分词个数。

【讨论】:

【参考方案4】:

我找到了最好的使用字符串流:

int Count(const std::string &string)

  stringstream ss(string);
  char cmd[256] = 0;
  int Words = 0;
  while(true)
  
    ss >> cmd;
    if(!ss)
        break;
    Words++;
  
  return Words;

输入:“亲爱的朋友你好”输出:4

即使应用也不会失败:

前导空格 尾随空格 只有空格 其他形式的空格

【讨论】:

“输出:4”,输入在哪里? @Quest 试试这个。 std::stringstream ss("你在说什么?");输出:6 @user3834119:输出不应该是 6 吗? :O @Silnik 我们在这里计算的是单词,而不是字符。那句话有5个字。即使你尝试这个,“你好,我亲爱的朋友。” (4 个字)输出:5 @user3834119:那你还没有定义一个词是什么。这里的每个人都会期望一个单词是一串没有空格的字符。然后根据你的定义是:“!!!”,“我”,“土豆!”一个字?您没有在问题中提供足够的信息。【参考方案5】:

这在我的机器上既简单又快速。它遍历字符串,使用bool 来跟踪 无论它是否在一个单词内,以及空​​格字符作为单词分隔符。我使用isspace() 库函数进行了测试,但这个switch 语句稍快。

int countwords(const std::string &str)

    int count = 0;
    bool in_word = false;
    for (char ch : str) 
        switch (ch) 
        case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
            in_word = false;
            break;
        default:
            if (!in_word) 
                in_word = true;
                ++count;
            
            break;
        
    
    return count;

这很容易针对不同的单词分隔符进行扩展或修改。这是一个将任何非字母字符视为分隔符的版本。将 !isalpha() 调用更改为 isspace() 将得到与上述代码相同的结果。

int countwords(const std::string &str)

    int count = 0;
    bool in_word = false;
    for (char ch : str) 
        if (!isalpha(ch))  // non-alpha chars are word delimiters
            in_word = false;
         else if (!in_word) 
            in_word = true;
            ++count;
        
    
    return count;

【讨论】:

【参考方案6】:
int countwords(std::string x)

    int i, count = 0;
    for (i = 0; i < x.size(); i++)
        if (x[i] == ' ')
            count++; //just count empty spaces

    count++; //count++ is same as count+1,so there will be count+1 words in string
    if (x.size() == 0)
        count = 0;
    return count;

【讨论】:

这不是真的 - 根据您的解决方案 countWords("Hello_____world!") = 5,其中 _ 是 ' ' 但在 cmets 中连续写入 4 个空格会被删除。 是的,我提到只有 1 个空格作为分隔符,但是你可以毫无问题地将这 4 个空格转换为一个【参考方案7】:

所以在阅读了一些有用的 cmets 之后,我自己尝试了。这是我的解决方案。我已经检查了我的程序是否有最坏的情况。如果你们中的任何人,可以找到任何该程序不起作用的情况,请告诉我,以便我可以工作和改进它。

为了清楚起见,我们不想要像“,”,“!”这样的符号。 , "?", "." , "\n" 算作单词。但显然,正如我们在语言中所考虑的那样,“我”应该算作单词。我通过用空格替换它们来确保这一切。如果我错过了什么,请告诉我。

#include <iostream>
#include <string> 

void replace(std::string& str, char x, char y);
int countWords(std::string x);

int main()
std::cout<<countWords(" \n \t Hello, world ! ");


void replace(std::string& str, char x, char y)
for(unsigned int i=0;i<str.size();i++)
    if(str[i]==x) str[i]=y;



int countWords(std::string x)

replace(x,',',' ');
replace(x,'.',' ');
replace(x,'!',' ');
replace(x,'?',' ');
replace(x,'(',' ');
replace(x,')',' ');
replace(x,'\n',' ');
replace(x,'\t',' ');
replace(x,'"',' ');

if(x.empty()) return 0;
int Num=1;

for(unsigned int i=1;i<x.size();i++)
    if(x[i]==' ' && x[i-1]!=' ') Num++;

if(x.back() == ' ') Num--;
return Num;

【讨论】:

怎么样?在函数替换中,const 限定符没有理由。并且函数 countWords 太慢了 @Quest 感谢您的建议。当您使用“?”时它会起作用。如果您能提出一种快速运行的方法,我们将不胜感激。 您应该尝试 Blastfurnace 的答案并添加更多开关盒【参考方案8】:

在代码中加入下面几行

int Num;
if(x[0] == ' ') Num = 0;
else Num = 1;

这将消除字符串开头的空白计数

#include <iostream>
#include <string>

int countWords(std::string x);

int main() 
    std::cout << countWords("Hello world!");


int countWords(std::string x) 
    if(x.empty()) return 0; // if the string is empty

    int Num;
    if(x[0] == ' ') Num = 0;
    else Num = 1;


    for(unsigned int i = 0; i < x.size(); i++) 
        // if there is a space in the start
        if(x[0] == ' ') continue;

        // second condition makes sure that i don't count 2 spaces as 2 words
        else if(x[i] == ' ' && x[i - 1] != ' ') Num++;
    
    return Num;

【讨论】:

这是错误的。在你的情况下 countWords("Hello ") = 2

以上是关于计算字符串中的单词的主要内容,如果未能解决你的问题,请参考以下文章

试图计算字符串中的单词

如何计算文本字符串中的单词?

如何提取 MySQL 字符串中的第 n 个单词并计算单词出现次数?

如何使用正则表达式计算字符串中的单词

如何使用 C++ 计算字符串中的某个单词

java计算字符串中的单词