繁体   English   中英

圆形 function 似乎无法正常工作

[英]Round function doesn't seem to work properly

C++

工作是找到一系列字符串的平均长度。

我使用了这段代码,它确实适用于第一个、第二个和第四个测试用例(总共 5 个)(ps 输入未知)

#include <cmath>
#include <iostream>

using namespace std;

int main() {
  string input;
  int k = 0;
  int sum = 0;

  while (cin >> input) {
    int n = input.size();
    k++;
    sum += n;
  }

  float out = (float)sum / k;
  cout << (int)round(out);

  return 0;
}

当我使用cout<<round(out); 它给出了相同的结果。

当我使用cout<<ceil(out); 最后4个案例是正确的,第一个案例失败了。

当我使用cout<<floor(out); 只有第一种情况是正确的,其他的都失败了。

我错过了什么?

问题

你是大学水平的英语 class,你的教授要你写一篇论文,但你需要找出你使用的所有单词的平均长度。 由您决定每个单词的长度并将其平均。 任务:接受一个字符串,计算出所有单词的平均长度,并返回一个代表平均长度的数字。 删除所有标点符号。 四舍五入到最接近的整数。

输入格式:包含多个单词的字符串。

Output 格式:一个数字,代表每个单词的平均长度,四舍五入到最接近的整数。

示例输入:这个短语有多个单词

样品 Output: 6

测试用例 1你不能这样做吗?

答案3

测试用例2字典中最长的单词是...

答案5

没有看到示例输入,我只是在猜测格式。 当试图在我的编辑器中运行你的代码时,我得到一个无限循环。 这是因为如果您仅按 Enter(空字符串), std::cin不会转换为false 所以我的代码假设所有单词都输入在一行中。 这意味着我现在必须将行拆分为单个单词。

为了使它与std::cin一起工作,我必须按Ctrl+d (WSL Debian) 才能跳出循环,我一点也不喜欢这样。

你最大的问题是你没有去掉标点符号。 如果你不这样做,标点符号会增加你的字符串长度,并且会让你的平均水平下降。 您还将“四舍五入”理解为简单的四舍五入,它可以向上向下舍入。 您想要的 function 是std::ceil() ,因为它总是 go 直到下一个整数。

#include <algorithm>  // std::remove_if, std::copy
#include <cctype>     // std::isalpha
#include <cmath>
#include <iostream>
#include <iterator>  // std::istream_iterator
#include <numeric>   // std::accumulate
#include <sstream>   // for easier (in code) string split on whitespace
#include <vector>    // Dynamic array for holding individual words

// Splits whole line string into vector of individual words
std::vector<std::string> split(std::string line) {
  std::vector<std::string> tmp;
  std::stringstream stream(line);

  std::copy(std::istream_iterator<std::string>(stream),
            std::istream_iterator<std::string>(), std::back_inserter(tmp));

  return tmp;
}

// Strips non-alphabetic characters from each word in a vector of words
std::vector<std::string> strip(std::vector<std::string> words) {
  for (auto& word : words) {
    word.erase(std::remove_if(word.begin(), word.end(),
                              [](const auto& x) { return !std::isalpha(x); }),
               word.end());
  }

  return words;
}

int main() {
  std::string input;

  std::getline(std::cin, input);  // Reads a whole line of input until Enter
  auto words = split(input);
  words = strip(words);

  if (words.size() == 0) {
    std::cout << 0;
    return 0;
  }

  // Once words is cleaned up, it's possible to get the mean directly
  std::cout << static_cast<int>(std::ceil(std::accumulate(
      words.begin(), words.end(), 0.0,
      [numWords = words.size()](const auto& mean, const auto& x) {
        return mean + (static_cast<double>(x.length()) / numWords);
      })));

  // Or the mean can still be calculated in a more manual fashion
  // int sum = 0;
  // for (auto i : words) {
  //   sum += i.length();
  // }

  // int mean =
  //     static_cast<int>(std::ceil(static_cast<double>(sum) / words.size()));
  // std::cout << mean;

  return 0;
}

输入(每行单独运行):

I want to write something
I() want, to. write*&^%$#@! something?

两个输入的 Output 为 5,根据您的要求应该是正确的。

您需要的主要内容是strip() function。

我将工作分解为几个函数,这使得主 function 中的工作更容易理解。 我使用“单线”直接计算平均值然后打印它,但我在评论中留下了更手动的方法。 我将std::ceil()返回的double显式转换为int会增加一些额外的冗长。 更喜欢static_cast而不是 C 风格的演员,它产生更安全的代码。

因为我在(大部分)可能的情况下使用标准库函数和构造,所以我也大量使用 lambdas,通常具有[]() {}形式的东西。 理解 lambdas 可以解锁很多标准库的使用,我强烈建议不要把这个主题搁置很长时间。

如果不是因为需要去掉标点符号和四舍五入,平均计算会更干净。

输入的结构可能会大大简化代码,但也有可能您的学习资源根本没有为您准备好字符串解析通常涉及的工作量。

我怀疑你被一个极端情况绊倒了,比如所有标点符号的字符串未处理导致浮点异常或类似的东西,比如",,, === !!!" .

您可以通过多种不同的方式处理案件(以及所有案件)。 一种直接的方法是使用擦除所有标点符号,然后通过创建一个字符串流并简单地将字符和单词相加来计算单词和字符。 不需要向量来保存单词,您只关心删除了标点和空格的总数,例如

#include <iostream>
#include <sstream>
#include <string>
#include <cctype>
#include <algorithm>

int main (void) {

    std::string line {};
    size_t nchars = 0, nwords = 0;
    
    if (!getline (std::cin, line))                          /* read line of input */
        return 1;
    
    line.erase (std::remove_if (line.begin(),               /* erase-remove punct */
                                line.end(),
                                [](unsigned char c) {
                                    return ispunct(c);
                                }), line.end());
    
    if (line.find_first_not_of(" \t") == std::string::npos) {   /* all punct/space */
        std::cout << "avg: 0\n";
        return 0;
    }
    
    std::stringstream ss (line);                            /* stringstream from line */
    while (ss >> line) {                                    /* count words */
        nchars += line.length();                            /* add total chars */
        nwords += 1;                                        /* add total words */
    }
    
    std::cout << "avg: " << (nchars + nwords - 1)/nwords << '\n';   /* result */
}

示例使用/输出

$ ./bin/mean_of_word_len
this phrase has multiple words
avg: 6

或者

$ ./bin/mean_of_word_len
Can you not do that?
avg: 3

或者

$ ./bin/mean_of_word_len
The longest word in the dictionary is...
avg: 5

或者

$ ./bin/mean_of_word_len
The longest word in the dictionary is......................................
avg: 5

或者

$ ./bin/mean_of_word_len
,,, === !!!
avg: 0

或者

$ ./bin/mean_of_word_len
,,, a === !!!
avg: 1

仔细检查一下,试一试,如果您还有其他问题,请告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM