【问题标题】:Print histogram with "*" representing relative frequencies in C++用“*”打印直方图,表示 C++ 中的相对频率
【发布时间】:2021-07-25 16:24:30
【问题描述】:

我正在尝试将具有绝对值的直方图转换为显示用户编写的字符串中字母的相对频率的直方图。字母频率应以 * 表示。因此,如果字母“A”占字符串的 1%,则应该有两个 *。 1% = 两个 *。

尝试计算频率时,输出为零。我真的不明白为什么。

我试图搜索互联网,但我真的找不到对我有帮助的东西。我想我的头脑和编码都陷入了困境。

这是我的三个函数的代码:

void berakna_histogram_abs(const string inm, int arr[ANTAL_BOKSTAVER]){

    int i, j = 0;

    while (inm[i] != '\0'){
        if (inm[i] >= 'a' && inm[i] <= 'z'){
            j = inm[i] - 'a';
            ++arr[j];
        }
        if (inm[i] >= 'A' && inm[i] <= 'Z'){
            j = inm[i] - 'A';
            ++arr[j];
        }
        i++;
    }
}
void abs_till_rel(int arr[ANTAL_BOKSTAVER], int (&ree)[ANTAL_BOKSTAVER]){

        for(int i = 0; i < ANTAL_BOKSTAVER; i++) {
            ree[i] = arr[i] / 26;
            printf("%c %lf \n", i + 'a', ree[i]);
        }

        for (int x = 0; x < ANTAL_BOKSTAVER; x++){

        }

    }

void plotta_histogram_rel(int (&ree)[ANTAL_BOKSTAVER]){

    cout << "Frekvensen av bokstäver i texten är: " << endl;
    for (int i = 0; i < ANTAL_BOKSTAVER; i++){
        cout << char(i + 'a') << " : " << ree[i] << endl;

         }
    }

我不能在第三个函数中做任何计算,那只是为了写直方图。整个程序很大,如果你愿意,我会提供所有代码。

非常感谢任何帮助。

谢谢!

【问题讨论】:

  • 在void abs_till_rel(int arr[ANTAL_BOKSTAVER], int ree[ANTAL_BOKSTAVER], int frekvens){ 中,您传递的是数组的副本(您是按值传递它们),因此在修改它们时,您不会修改原始数组。尝试通过引用传递结果:void abs_till_rel(int arr[ANTAL_BOKSTAVER], int &amp;ree[ANTAL_BOKSTAVER], int &amp;frekvens){
  • 你应该通过返回结果来实现,而不是通过参数修改它们。
  • 谢谢!好的,所以也许 abs_till_rel 应该是 int 而不是 void?返回“frekvens”(=英语频率)。
  • 您可以返回pair 或自定义struct,还有其他几种可能。
  • “我会提供所有代码” -- 请不要。问题应该有最少 数量的代码来重现问题(因此命名为“minimal reproducible example”)。虽然有时真正最小的代码是不合理的(因为它需要知道问题的答案),但您应该能够接近。一旦你有足够的代码来重现问题,不要无缘无故地添加更多。 (您可以通过将问题中的内容复制到新项目(或在线编译器)然后编译并运行来查看您是否有足够的代码。如果问题出现,则说明您有足够的代码。)

标签: c++ arrays histogram


【解决方案1】:

因此,您有一些错误需要纠正。您不会在第一个函数中将数组作为引用传递。你按值传递它。因此,将在第一个函数 berakna_histogram_abs 中对该 arra 进行的所有修改对外界都是不可见的。

你需要在你的其他函数中做同样的事情 -->

void berakna_histogram_abs(const std::string inm, int (&arr)[ANTAL_BOKSTAVER]) {

顺便说一句,字符串也应该作为引用传递。反正。没那么重要。

下一个问题。您忘记在第一个函数中将变量 i 初始化为 0。所以,它会有一些随机值,程序会失败,因为你用inm[i]访问一些随机索引。

在您的计算函数abs_till_rel 中,您使用了错误的公式。您需要乘以 100 以获得 0 到 100 之间的整数结果作为百分比。然后除以 26,这使得结果与字母表中字母的数量有关。我的猜测是你想要与字符串中的字母数有关系。

为此,您首先需要计算所有字母数以获取总计数。例如:

int sum = 0;
    for (int i = 0; i < ANTAL_BOKSTAVER; i++) sum += arr[i];

然后除以这个总和,如下所示:

ree[i] = (arr[i] * 100) / sum;

要输出直方图,您可以使用std::string constructor number 2 简单地构建一个带有星号的字符串

您更新后的程序如下所示:

#include <iostream>
#include <string>
#include <stdio.h>

constexpr int ANTAL_BOKSTAVER = 26;

void berakna_histogram_abs(const std::string inm, int (&arr)[ANTAL_BOKSTAVER]) {

    int i = 0, j = 0;

    while (inm[i] != '\0') {
        if (inm[i] >= 'a' && inm[i] <= 'z') {
            j = inm[i] - 'a';
            ++arr[j];
        }
        if (inm[i] >= 'A' && inm[i] <= 'Z') {
            j = inm[i] - 'A';
            ++arr[j];
        }
        i++;
    }
}
void abs_till_rel(int arr[ANTAL_BOKSTAVER], int(&ree)[ANTAL_BOKSTAVER]) {
    
    int sum = 0;
    for (int i = 0; i < ANTAL_BOKSTAVER; i++) sum += arr[i];

    if (sum >0) for (int i = 0; i < ANTAL_BOKSTAVER; i++) {
        ree[i] = (arr[i] * 100) / sum;
        std::cout << (char)(i + 'a') << '\t' << ree[i] << '\n';
    }

    for (int x = 0; x < ANTAL_BOKSTAVER; x++) {

    }

}

void plotta_histogram_rel(int(&ree)[ANTAL_BOKSTAVER]) {

    std::cout << "Frekvensen av bokstäver i texten är: " << std::endl;
    for (int i = 0; i < ANTAL_BOKSTAVER; i++) {
        std::cout << char(i + 'a') << " : " << std::string(ree[i]*2,'*') << std::endl;

    }
}
int main() {

    std::string test{"The quick brown fox jumps over the lazy dog"};

    int frequencyArray[ANTAL_BOKSTAVER] = {};
    int frequencyInPercent[ANTAL_BOKSTAVER] = {};

    berakna_histogram_abs(test, frequencyArray);
    abs_till_rel(frequencyArray, frequencyInPercent);
    plotta_histogram_rel(frequencyInPercent);

}

但在 C++ 中,我们会使用标准方法并编写以下代码:

#include <iostream>
#include <map>
#include <string>
#include <cctype>

// Our test string. This is a standard test string that contains all letters
std::string test{ "The quick brown fox jumps over the lazy dog" };

int main() {
    // Count all letters
    std::map<char, size_t> counter{};
    for (const auto& c : test) if (std::isalpha(c)) counter[std::tolower(c)]++;

    // Show histogram
    for (const auto& [letter, count] : counter)
        std::cout << letter << '\t' << std::string((count * 200) / test.size(), '*') << '\n';
    return 0;
}

【讨论】:

  • 谢谢!!我想我们彼此过去了。我已经解决了这个问题,请看下面的答案。感谢您的宝贵时间!
【解决方案2】:
void abs_till_rel(int arr[ANTAL_BOKSTAVER], int langd, double frekArr[ANTAL_BOKSTAVER]){
//Function to calculate the relative frequency of letters in a string.
    for (int i = 0; i < ANTAL_BOKSTAVER; i++){

    frekArr[i] = arr[i]; //Writes over the input from the user to a new array.

    frekArr[i] = frekArr[i] * 200 / langd; //Calculates the relative frequency
    //*200 since 1% should be represented by two (2) *.
    }
}
void plotta_histogram_rel(double frekArr[ANTAL_BOKSTAVER], int langd){

    int j = 0;
    for (int i = 0; i < ANTAL_BOKSTAVER; i++){
    cout << char(i + 'A') << " : ";
//Creates a histograg, horizontal, with A-Z.

        if(frekArr[i] > 0){
        for ( j = 0; j < frekArr[i]; j++){ 
        cout << "*";
        }
        cout << endl;
        }
//If the index in frekArr is NOT empty, loop through the index [i] times and 
//write double the amount of *. 
        else {
            cout << " " << endl;
//Else, leave it empty.
        }
}
}

我已经解决了这个问题。请参阅上面的工作代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-11
    • 2019-12-17
    • 1970-01-01
    • 2022-10-14
    • 1970-01-01
    • 2012-04-03
    • 2021-08-27
    • 1970-01-01
    相关资源
    最近更新 更多