簡體   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