【问题标题】:A program that finds the word count and letters in a sentence一个在句子中查找字数和字母的程序
【发布时间】:2020-03-06 05:41:18
【问题描述】:

编写一个程序,读取一行文本并输出该行中的单词数和每个字母出现的次数。将单词定义为在每一端由空格、句点、逗号或行首或行尾分隔的任何字母字符串。您可以假设输入完全由字母、空格、逗号和句点组成。输出一行中出现的字母数时,一定要将一个字母的大写和小写版本算作同一个字母。按字母顺序输出字母并仅列出输入行中出现的字母。例如,输入线 我说嗨。 应该产生类似于以下的输出: 3 个字 1个 1小时 2我 1 秒 1 年

#include<iostream>
#include<cstring>
#include<cctype>
using namespace std;

int main()
{
  string input;
  cout<<"Enter a sentence: ";
  getline(cin,input);
  int count[26] = {0},i,wordCount=0;
  for(i = 0; i< input.size();i++){
  if(((input[i]>='a' && input[i] <= 'z')||(input[i]>='A' && input[i] <= 'Z'))&&(input[i+1]=='.'||input[i+1]
  ==','||input[i+1]=='\0'))
  wordCount++;
  if(input[i]>='a' && input[i] <= 'z')
  count[input[i]-'a']++;
  if(input[i]>='A' && input[i] <= 'Z')
  count[input[i]-'A']++;


  }
  char x = input[input.size()-1];
  if(x != '.' && x != 'z' && x!= '\0')
  wordCount++;
  cout<<endl<<wordCount<<" words "<<endl;
  for(i=0; i<26; i++)
  {
    if(count[i]>0)
    cout<<count[i]<<" "<<(char)('a'+i)<<endl;
  }

}

例如,它会运行所有内容,但会打印错误的字号。 示例:输入句子:我很困惑,请帮助

2 个字 2个 1摄氏度 1天 4e 1 英尺 1小时 1 我 2升 1米 1个 1个 2个 2 秒 1个

【问题讨论】:

  • 为什么不使用isupper()islower() 而使用#include &lt;cctype&gt;
  • if(((input[i]&gt;='a' &amp;&amp; input[i] &lt;= 'z')||(input[i]&gt;='A' &amp;&amp; input[i] &lt;= 'Z'))&amp;&amp;(input[i+1]=='.'||input[i+1] ==','||input[i+1]=='\0')) 你忘了检查空格作为单词分隔符。

标签: c++


【解决方案1】:

您必须学习如何将问题分解为子问题。以下不是完整的答案,但应该可以指导您。

  1. 由于输入仅由有效字符组成,您可以假设除了字母和换行符之外的所有内容都是分隔符

  2. 您还可以编写一个函数来读取单个单词,直到它到达行尾。然后你可以这样使用它:

    int main()
    {
      while (get_word())
        ;
    
      cout 
        << "words: " << word_count << endl
        << "letters: " << letter_count;
    }
    
  3. 该函数将使用以下库函数:

    • istream::get - 从流中获取下一个字符;
    • ::isalpha - 如果参数是字母,则返回 true;
    • istream::putback - 在流中放回一个字符。

int word_count, letter_count;

bool get_word()
{
  char c;

  // skip all characters except for letters and new-line
  while (cin.get(c) && !isalpha(c) && '\n' != c)
    ;

  // did we reach the end of line?
  if (!cin || '\n' == c)
    return false; // we read all the words

  //
  string word{ c }; // add the first read character to word
  while (cin.get(c) && isalpha(c)) // while the read character is a letter add it to the word
    word += c;

  // the last read character is not a letter, so put it back in stream
  cin.putback(c);

  // now we have a word: count it
  ++word_count;

  // count letters in word
  letter_count += word.length();

  // we still have words to read
  return true;
}

Run it.

【讨论】:

    【解决方案2】:

    到目前为止,我看到的答案是恕我直言,不知何故太复杂了。尤其是看起来像带有一些 C++ 扩展的 C。

    我想展示一个“更现代”的 C++ 解决方案,它利用了 C++ 算法和现代语言特性。

    这样,计算std::string 中的单词就是一个语句,一个典型的单行语句。计数字符也是如此。

    计数字符有一个众所周知且广泛传播的解决方案。只需使用std::map,将元素添加为键,使用索引运算符,然后增加键的值。你可以用谷歌搜索它并找到大量的例子。

    对于这个任务的特殊要求,我们额外检查,在std::map 中只放置字母字符。而且,我们确保所有内容都是小写的。

    整个计数归结为:

    std::for_each(test.begin(), test.end(), 
        [&counter](const char c) { if (std::isalpha(c)) counter[std::tolower(c)]++;  });
    

    我们遍历std::string中的每个字符,检查它是否是alpha,如果是,则将其转换为小写,放入映射中并计数。

    好的,简单。

    现在,我们要数单词。为此,我们还将使用一个迭代器,它迭代字符串中的所有单词。如您所知,迭代器(或者更好地说,它的底层容器)具有“开始”和“结束”。如果你从开始位置减去结束位置,那么你总是有元素的数量。

    例子:如果你有一个std::vector,那么你就知道std::vectorbegin()end()之间的距离就是向量中的元素个数。好的,清楚。

    现在,我们如何遍历 std::string 中的所有单词?为此,C++ 有一个std::sregex_token_iterator。这将遍历遵循给定模式的所有元素。该模式将在std::regex 中定义。结果又是一个超简单的语句,又是一个单行语句(一个语句):

    std::distance(
        std::sregex_token_iterator(test.begin(), test.end(), re, 1),
        std::sregex_token_iterator()) 
    

    请注意此解决方案对于假设的困难任务的简单性。我们将在显示屏上显示结果。而且人物也很重要。对于后者,我们使用基于范围的 for 循环,并通过结构化绑定从 std::map 中提取元素。

    结果是一个非常简短的解决方案,以优雅的 C++ 方式满足要求。

    #include <iostream>
    #include <iterator>
    #include <algorithm>
    #include <cctype>
    #include <regex>
    #include <map>
    
    const std::regex re(R"([\w]+)");
    const std::string test{ "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, "
                            "sed diam nonumy eirmod tempor invidunt ut labore et dolore "
                            "magna aliquyam erat, sed diam voluptua. At vero eos et "
                            "accusam et justo duo dolores et ea rebum. Stet clita kasd "
                            "gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." };
    
    int main() {
        // Count the number of characters
        std::map<char, size_t> counter{};
        std::for_each(test.begin(), test.end(), [&counter](const char c) { if (std::isalpha(c)) counter[std::tolower(c)]++;  });
    
        // Print the number of words
        std::cout << "Number of Words: " 
            <<  std::distance(std::sregex_token_iterator(test.begin(), test.end(), re, 1), std::sregex_token_iterator()) 
            << "\n\nCount of characters:\n\n";
    
        // Show character count on display
        for (const auto& [character, count] : counter) std::cout << character << " -> " << count << "\n";
    
        return 0;
    }
    

    可惜没人看。 . .

    【讨论】:

      【解决方案3】:

      不要使用'\0' 来检查空格,而是使用' '
      '\0' 表示字符串中的 NUL 终止。
      C++ 中,字符串不是以'\0' 结尾的。
      '\0' 在 ASCII 中的值是 0
      ' ' 表示空格,它在 ASCII 中的值是 32。

      这是更新后的代码:-

      #include<iostream>
      #include<cstring>
      #include<cctype>
      using namespace std;
      
      int main()
      {
        string input;
        cout<<"Enter a sentence: ";
        getline(cin,input);
        int count[26] = {0},i,wordCount=0;
        for(i = 0; i< input.size();i++){
        if(((input[i]>='a' && input[i] <= 'z')||(input[i]>='A' && input[i] <= 'Z'))&&(input[i+1]=='.'||input[i+1]
        ==','||input[i+1]==' '))
        wordCount++;
        if(input[i]>='a' && input[i] <= 'z')
        count[input[i]-'a']++;
        if(input[i]>='A' && input[i] <= 'Z')
        count[input[i]-'A']++;
      
      
        }
        char x = input[input.size()-1];
        if(x != '.' && x != 'z' && x!= ' ')
        wordCount++;
        cout<<endl<<wordCount<<" words "<<endl;
        for(i=0; i<26; i++)
        {
          if(count[i]>0)
          cout<<count[i]<<" "<<(char)('a'+i)<<endl;
        }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2016-07-06
        • 1970-01-01
        • 1970-01-01
        • 2017-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多