如何对结构体进行排序并按排序顺序打印?



input.txt,我有一个句子,例如:

HELLO计算这里有多少字符和哪些字符

我必须阅读input.txt并计算每个字母在该句子中有多少个字符。然后,我必须将这些字符按降序排序。

我给你举个例子,有:

H:7, E:6, L:2, O:3, C:5, W:2, A:7, Y:1, R:6, S:2, I:1, M:1, N:1

字母表示它是哪个字母,数字表示该字母在句子中出现的次数。当我对它们排序时,它应该是这样的:

H:7, A:7, E:6, R:6, C:5, O:3, L:2, W:2, S:2, Y:1, I:1, M:1, N:1

如果两个字母出现的次数相同,那么哪个字母在前面并不重要。

问题是我不知道如何对它们进行排序,也不知道如何使每个字母以有序的顺序打印出来。我是c++新手,所以我知道的不多。

我唯一想到的是把所有这些字母放入struct,然后排序。我想过把它们放到一个数组中,但我不确定怎么做,或者是否可能。所以我决定用struct试试,但没能成功。

下面是我的代码:

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
struct letters{
int A=0, C=0, E=0, H=0, I=0, L=0, M=0, N=0, O=0, R=0, S=0, W=0, Y=0;
int n=13;
};
int main() {
string str;
int A=0, C=0, E=0, H=0, I=0, L=0, M=0, N=0, O=0, R=0, S=0, W=0, Y=0;
int n=13; // How many letters there are in total
ifstream read("input.txt");
while (getline(read,str)) {
for(char &ch : str) {
// Here I read a letter and if it matches one of those "if statements" it counts it
if(ch == 'A'){
A++;
}
if(ch == 'C'){
C++;
}
if(ch == 'E'){
E++;
}
if(ch == 'H'){
H++;
}
if(ch == 'I'){
I++;
}
if(ch == 'L'){
L++;
}
if(ch == 'M'){
M++;
}
if(ch == 'N'){
N++;
}
if(ch == 'O'){
O++;
}
if(ch == 'R'){
R++;
}
if(ch == 'S'){
S++;
}
if(ch == 'W'){
W++;
}
if(ch == 'Y'){
Y++;
}
}
}
letters a[n];
sort(a, a+n); // Trying to sort it and then print everything out like I did below. But I don't know how
// Here I just check if every letter is counted correctly
cout << "A: " << A << endl;
cout << "C: " << C << endl;
cout << "E: " << E << endl;
cout << "H: " << H << endl;
cout << "I: " << I << endl;
cout << "L: " << L << endl;
cout << "M: " << M << endl;
cout << "N: " << N << endl;
cout << "O: " << O << endl;
cout << "R: " << R << endl;
cout << "S: " << S << endl;
cout << "W: " << W << endl;
cout << "Y: " << Y << endl;
read.close();
return 0;
}

我想过把它们放入一个数组,但我不确定如何做到这一点,或者如果它是可能的。

这是个好主意,因为对数组进行排序是一件很容易的事情。此外,数组可以很容易地扩展以容纳其他字母,这样您就不必更改程序来容纳,例如,在input.txt的新版本中容纳字母Q

你的问题看起来像家庭作业,所以请原谅我没有一直为你做。想象一下这个数组的元素会是什么样子,因为它必须在计数器的同时包含一个字母。

您可能希望分配足够的数组元素来容纳所有可能的字母。排列该向量中的元素,以便可以通过简单的索引(无需搜索!)来查找每个字母的元素。然后读取文件,为遇到的每个字母增加计数器。然后对数组进行排序,并打印计数器值为非零的所有元素。

由于需要按频率降序排序,我建议使用struct的容器:

struct Letter_Frequency
{
char letter;
unsigned int frequency;
};
std::vector<Letter_Frequency> frequencies;

下面的代码片段展示了如何构建容器:

while (getline(text_file, text_str))
{
const size_t string_length(text_str.length());
for (size_t str_index = 0U; str_index < string_length; ++str_index)
{
const char c = text_str[str_index];
// Skip characters that are not a letter.
if (!isalpha(c)) continue; 
// Search the container for the letter...
const size_t container_size(frequencies.size());
bool         letter_exists = false;
for (size_t container_index = 0U;
container_index < container_size;
++container_index)
{
if (frequencies[container_index].letter == c)
{
++frequencies[container_index].frequency;
letter_exists = true;
break;
}
}
if (!letter_exists)
{
Letter_Frequency new_letter;
new_letter.letter = c;
new_letter.frequency = 1U;
frequencies.push_back(new_letter);
}
}
}

由于容器已创建并填充,因此需要按频率降序排序。这可以通过编写排序函数来实现:

bool Order_Descending_By_Frequency(const Letter_Frequency& a,
const Letter_Frequency& b)
{
return a.frequency > b.frequency;
}

排序:

std::sort(frequencies.begin(), frequencies.end(),
Order_Descending_By_Frequency);

还有其他方法可以计算频率并按频率降序排序。上面的代码片段展示了一种可能性。

限制和其他修改留给OP或读者作为练习。

Edit 1: Simplicity
一种更简单的方法是使用数组并"自下而上"打印数组。

const unsigned int MAX_LETTERS = 26;
unsigned int frequencies[MAX_LETTERS] = {0};
//...
for (size_t str_index = 0U; str_index < string_length; ++str_index)
{
const char c = text_str[str_index];
if (isalpha(c))
{
const char upper_c(toupper(c));
++frequencies[(upper_c - 'A')];
}
}
for (int index = MAX_LETTERS - 1; index >= 0; --index)
{
if (frequencies[index] > 0)
{
const char letter = 'A' + index;
std::cout << letter << ": " << frequencies[index] << "n";
}
}

在上面的代码片段中,频率是在通常的方法中计算的,但是打印从数组的末尾开始。不需要排序

最新更新