用“*”打印直方图表示 C++ 中的相对频率

Print histogram with "*" representing relative frequencies in C++

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

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

我已经尝试在互联网上搜索,但我无法真正找到对我有帮助的东西。我想我被困住了,无论是在我的头脑中还是在编码中。

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

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

    int i, j = 0;

    while (inm[i] != '[=10=]'){
        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 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.
        }
}
}

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

所以,您有一些错误需要更正。您没有在第一个函数中将数组作为引用传递。你按价值传递它。因此,在第一个函数 berakna_histogram_abs 中对该数组所做的所有修改将对外界不可见。

你需要像在其他函数中那样做 -->

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] != '[=13=]') {
        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;
}