C++-如何对字符进行频率计数



我需要编写代码来将唯一字符及其频率存储在动态数组中。当新数据进入时,我需要增加它的大小。在这种情况下,新数据将是遇到的新字符。我想到的算法是,每次从给定的字符串中读取时,都要检查已知字符的列表。如果它是一个新字符,我需要将数组大小增加1。如果它不是一个新角色,我会增加它的频率。它是一个结构字母的数组(在下面的代码中(。问题是,我花了很多时间在这方面,但在实现它时遇到了问题。所以问题是我如何才能准确地实现它?谢谢你花时间帮忙。

#include <iostream>
#include <string>
#include <bitset>
#define ARR_LEN(arr) sizeof(arr)/sizeof(arr[0])
using namespace std;
struct unique_char {
char character;
int frequency;
};
int main() {
int char_count;
string str;
getline(cin, str);
struct unique_char* chars = new struct unique_char[100];
system("PAUSE");
exit(0);
}

正如注释中所提到的,使用std::map使这变得相当简单。

其中一个";有趣";关于map的事情是索引运算符创建新的值";"按需";int的初始值为CCD_ 2。所以实际的代码本质上是一行:chars[c] += 1;

#include <map>
#include <iostream>
#include <string>
using namespace std;
int main() {
map<char, int> chars;
string str;
getline(cin, str);
for(char c: str) {
chars[c] += 1;
}
for(auto [character, frequency]: chars) {
cout << character << " : " << frequency << "n";
}
}

N.B.这与@ThomasMatthews的回答有一个主要区别:

映射将只包含已看到的字符,而数组将包含从未命中的所有字符的0。你使用哪种方法应该基于这两种方法中哪一种对你更有用。

使用数组可以使事情直截了当:

unsigned int frequencies[256] = {0};
while (std::getline(std::cin, str))
{
const size_t length = str.length();
for (unsigned int i = 0; i < length; ++i)
{
const char c = str[i];
++frequencies[c];
}
}

尽管如此,您可能希望提高效率:

const size_t BUFFER_SIZE = 1024u * 1024u;
//...
char buffer[BUFFER_SIZE] = {0};
while (std::cin.read(&buffer[0], BUFFER_SIZE)
{
const size_t chars_read = cin.gcount();
for (unsigned int i = 0; i < chars_read; ++i)
{
const char c = buffer[i];
++frequencies[c];
}
}

上面的代码使用块读取来提高输入性能。不需要扫描换行符,只需直接读入内存即可。根据记忆中的字符确定频率。

编辑1:unsigned char
根据注释,unsigned char可能是比char更安全的数据类型,因为char可以签名。当访问阵列插槽时,这可能是一个问题,因为signed char可能是负的,而负索引通常是坏事。运行时,如果出现问题,请将char类型替换为unsigned char

最新更新