【问题标题】:How to count the occurrence of the spaces and any ascii characters in a string?如何计算字符串中空格和任何 ascii 字符的出现次数?
【发布时间】:2016-03-07 13:46:00
【问题描述】:

我编写了这段代码来计算字符串中每个字符的出现次数,但它不计算空格或任何扩展 ASCII 字符...知道吗?

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

int main()
{
std::string input = "slowly";

std::map<char, int> occurrences;

for (std::string::iterator character = input.begin(); character != input.end(); character++)
{
    occurrences[*character] += 1;
}

for (std::map<char, int>::iterator entry = occurrences.begin(); entry != occurrences.end(); entry++)
{
    std::cout << entry->first << '=' << entry->second << std::endl;
}
}

如果有任何更快的算法来处理大量字符以获得相同的结果,我将不胜感激??

【问题讨论】:

  • 嗯,你可以使用一个计数数组,带有127 条目,然后直接索引到它。 std::unordered_map 通常是比std::map 更好的“默认”关联容器。 (我也不是std::endl的粉丝。)
  • 它会计算空格和特殊字符。
  • 首先,如果您有非常大的字符串,您可以并行执行。其次,我建议使用std::array&lt;std::size_t, 256u&gt;作为occurences的类型,并在使用前将所有这些值初始化为0

标签: c++


【解决方案1】:

我认为你的代码很好,因为它对我有用,我在 Windows 7 机器 64 上使用 Visual Studio C++ 2010 执行它。

#include "stdafx.h"
#include <iostream>
#include <map>
#include <string>

int main()
{
std::string input = "And if there's any faster algorithm to deal with a large amount of characters to get the same results i would be thankful ?? How to count the occurrence of the spaces and any ascii characters in a string?";

std::map<char, int> occurrences;

for (std::string::iterator character = input.begin(); character != input.end(); character++)
{
    occurrences[*character] += 1;
}

for (std::map<char, int>::iterator entry = occurrences.begin(); entry != occurrences.end(); entry++)
{
    std::cout << entry->first << '=' << entry->second << std::endl;
}
}

这是执行上述代码时的结果:

更新:

这是一个新代码,其中 iam 使用包含变量 input 的上述值的文件

#include "stdafx.h"
#include <iostream>
#include <map>
#include <string>
#include <fstream>
#include <streambuf>

std::ifstream inputFile("text.txt");
std::string input((std::istreambuf_iterator<char>(inputFile)),
                 std::istreambuf_iterator<char>());


int main()
{

std::map<char, int> occurrences;

for (std::string::iterator character = input.begin(); character != input.end(); character++)
{
    occurrences[*character] += 1;
}

for (std::map<char, int>::iterator entry = occurrences.begin(); entry != occurrences.end(); entry++)
{
    std::cout << entry->first << '=' << entry->second << std::endl;
}
}

我们有相同的结果:

【讨论】:

  • 它不计算文件中的空格..尝试从文件中读取相同的字符串它不会计算任何空格
【解决方案2】:

对于真的长字符串(超过数百万个元素),您可以将字符串拆分为更小的部分,并将每个部分传递给处理其小部分并添加到其小映射的线程,然后在所有线程完成后在最后合并地图。否则,对于多达数千甚至数万个字符的字符串,它可能不会有太大的区别,而对于少于几千个字符的字符串,设置线程和合并映射可能会比您当前花费更多的时间线性方法。

此外,除非您希望对结果进行排序,否则请改用 std::unordered_map

【讨论】:

    【解决方案3】:

    好吧,这段代码计算了字符串中出现的字符。您的示例,如果您写了std::string input = "slowly \tmedium \rfast \n";,将计算 3 个空格 (32)、1 个制表符 (8)、1 个 cr (13) 和 1 个换行 (10)。

    当然,如果您使用以下内容读取文件:

    std::string input;
    ...
    in >> input;
    

    您明确要求空格分隔的单词,因此您既找不到空格也找不到任何其他空白 (\t\r\n)。

    如果要计算文件中的所有字符,则必须对以二进制模式打开的文件使用二进制读取 (in.read(char *buf, streamsize size))。

    最后一个警告:如果您的文件使用像 UTF8 这样的多字节编码字符集,您必须准备好将单个 é 字符视为 2 字节 0xc3 oxc9...

    为了速度,您可以首先使用数组而不是映射来计算字符数,然后可以选择多线程处理您的程序以处理像 Joachim 解释的非常大的文件。

    【讨论】:

      猜你喜欢
      • 2012-10-03
      • 2010-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-24
      • 2014-07-03
      相关资源
      最近更新 更多