2017-08-26 110 views
3

我想知道是否有人可以帮助我。我试图使用列表或结构作为容器来计算文本文件中字母的频率,并且在计算解决方案时遇到了一些问题。C++ - 没有匹配的构造函数

下面我有一些代码,并首次尝试使用struct但无法弄清楚如何轻松地浏览这个对象的指针。有没有人有如何添加和通过struct条目步行的例子? struct不是像可扩展容器吗?

如果我可以使用std::list我宁愿这样做,但在阅读std::list文档后,在本网站或网站上找不到任何有用的示例。我需要一个char变量和一个整数char包含找到的字母,整数是我找到每个字母多少次的计数器。

有人可以帮忙吗?

谢谢。

到目前为止的代码:

#include <iostream> 
#include <fstream> 
#include <list> 
using namespace std; 

struct LetterBox { 
    char letter; 
    size_t frequency; 
    LetterBox* Next; 
    LetterBox(char ch, size_t count, LetterBox* ptr) 
    { 
     letter = ch; 
     frequency = count; 
     Next = ptr; 
    } 
}; 

int main() { 

    new LetterBox(' ',0,nullptr); 
// new LetterBox(' ',0,nullptr); 
    int count = 0; 
    char ch; 
    string line; 
    string FileName; 

    cout << "Enter the name of the textfile: "; 
    cin >> FileName; 

    ifstream file (FileName); 
    if (file.is_open()) 
     while (file.good()) 
     { 
      while(getline(file, line)) { 
       for (int i = 0; i < sizeof(line); i++) { 
        ch = toupper(line[i]); 
        count++; 
        cout << ch; 

       } 
      } 
      file.close(); 
     } 
    else 
    { 
     cout << "Unable to open file:" << FileName << endl; 
     return 1; 

    } 
    return 0; 
} 
+1

你应该使用地图:http://www.cplusplus.com/reference/map/map/。一般来说,你不应该在C++中使用'struct'。 – DyZ

+1

为什么不使用std :: map 直接关联字符和它的计数器? –

+0

您的'LetterBox'结构可以包含Array或List作为包含类。或者你可以使用链表。 – MKR

回答

0

正如其他人在你的问题在意见建议中,std::map是你需要什么。使用std::map,您可以将出现次数映射到相应的字符。

下面是一个简单的例子:

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

int main() { 
    std::string hello { "Hello, World!" }; 
    std::map<char, std::size_t> letterCounts; 

    for(char ch : hello) 
     letterCounts[ch]++; 

    for(auto& elem : letterCounts) 
     std::cout << elem.first << ": " << elem.second << std::endl; 
} 

std::list是好当你打算使用的容器具有快速插入和移除的能力。访问std::list内的元素很慢。

+0

'std :: vector'会在练习中击败'std :: list'。现代CPU *真的很讨厌*追逐指针,并且在预取友好的东西上执行得更好。尝试一下;无论std :: list在理论上(大O)比插入的std :: vector更好,我敢打赌真正的钱,你会看到'std :: vector'几乎每一次都会出现。根据我的经验,'std :: list'接近您可以为现代CPU选择的* worst *数据结构。 –

1

你可以实验一下,使用std ::地图就像你在其他一些语言使用字典,这是更快,更容易,更诱人,如果你想在以后支持UTF编码已经解决的问题。

但是,如果您已经知道它只会用于ASCII文本,那么还有另一种方法。

您的ASCII宇宙是0-255(0-128实际但让忽略,以防有人使用扩展ASCII)。这意味着我们实际上可以在合理的空间覆盖了

std::array<std::size_t, 256> letters= {0}; 

所有结果然后,您可以用

for (int i = 0; i < sizeof(line); i++) { 
    ch = toupper(line[i]); 
    letter[ch]++; 
} 

后来更换您的内环写出来的结果

for (char ch = 'A'; ch <= 'Z'; ch++) { 
    std::cout << "Letter: '" << ch << "' occured " << letter[ch] << " times\n"; 
} 

这应该与std::map大致相同的空间使用率,但更好的位置和更好的查找时间。你只能使用27个字母,但增加了更多的条件。

0

这里是我所使用mapstructured binding用于计数信的频率

新功能的C++ 17实施例中使用

1.如果语句初始化

  1. 结构绑定
#include<iostream> 
#include<string> 
#include<map> 
#include<algorithm> 

int main() 
{ 
    std::map<char,int> counterOfChar; 
    std::string My("Once upon a time there was a lion who was very funny in reading text and counting them"); 
    std::for_each(My.begin(), My.end(), [&counterOfChar](const char& n) 
    { //'if' initialization statements are a C++1z extension 

     if (auto [iter,success] = counterOfChar.insert(std::make_pair(toupper(n),1)) ;success == false) 
     { 
      counterOfChar[iter->first] = ++iter->second; 
     } 
    }); 
    for (const auto &[character,count]:counterOfChar) 
    { 
     std::cout<<character<<" "<<count<<std::endl; 
    } 
return 0; 
} 

输出

17 
A 6 
C 2 
D 2 
E 8 
F 1 
G 2 
H 3 
I 5 
L 1 
M 2 
N 10 
O 5 
P 1 
R 3 
S 2 
T 6 
U 3 
V 1 
W 3 
X 1 
Y 2 
Program ended with exit code: 0 
+0

我觉得我非常接近,但由于某种原因,我的程序由于某种原因计算了更多'C',但所有其他字符似乎都算好。 –

+0

@Cory Hall如果你想要,你可以发布你的新代码 –

相关问题