2017-08-26 176 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如果你想要,你可以發佈你的新代碼 –

相關問題