2017-08-26 13 views
3

Ich habe mich gefragt, ob mir jemand helfen kann. Ich versuche entweder eine Liste oder eine Struktur als Container zu verwenden, um die Häufigkeit von Buchstaben in einer Textdatei zu zählen, und habe Probleme, die Lösung herauszufinden.C++ - Kein passender Konstruktor

Ich habe einen Code unten und habe zuerst versucht, eine struct zu verwenden, aber kann nicht herausfinden, wie man leicht dieses Objekt mit einem Zeiger navigiert. Hat jemand Beispiele dafür, wie man Einträge in einer struct hinzufügen und durchlaufen kann? Ist ein struct nicht wie ein erweiterbarer Container?

Wenn ich die std::list verwenden kann, würde ich lieber tun, aber konnte nicht wirklich irgendwelche Beispiele auf dieser Seite oder im Internet finden, die nützlich genug waren nach dem Lesen der std::list Dokumentation. Ich brauche eine char Variable und eine ganze Zahl die char enthält den Buchstaben gefunden und die ganze Zahl ist der Zähler, wie oft ich jeden Buchstaben gefunden habe.

Kann mir hier jemand helfen?

Danke.

-Code bisher:

#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

sollten Sie Karten verwenden: http://www.cplusplus.com/reference/map/map/. Sie sollten im Allgemeinen niemals 'struct's in C++ verwenden. – DyZ

+1

Warum nicht std :: map verwenden, um Zeichen und ihre Zähler direkt zuzuordnen? –

+0

Ihre 'LetterBox'-Struktur kann ein Array oder eine Liste als Klasse enthalten. Oder Sie können die Linked-List verwenden. – MKR

Antwort

0

Wie andere in den Kommentaren unter Ihrer Frage vorgeschlagen, ist die std::map was tun Sie brauchen. Mit std::map können Sie die Anzahl der Vorkommen den entsprechenden Zeichen zuordnen.

Hier ist ein einfaches Beispiel:

#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; 
} 

Die std::list ist gut, wenn Sie beabsichtigen, Fähigkeiten, einen Behälter mit schnellem Einsetzen und Entfernen zu verwenden. Zugreifen auf Elemente in einem std::list ist langsam.

+0

'std :: vector' wird in der Praxis jedoch' std :: list' schlagen. Moderne CPUs * hassen wirklich * jagen Zeiger und führen viel besser auf etwas Prefetcher freundlich. Versuch es; unabhängig davon, dass "std :: list" theoretisch (großes O) besser ist als "std :: vector" für Einfügungen, werde ich echtes Geld wetten, dass du 'std :: vector' fast jedes Mal übertreffen wirst. Nach meiner Erfahrung liegt 'std :: list' nahe bei der * schlechtesten * Datenstruktur, die Sie für moderne CPUs auswählen können. –

1

Sie können ein wenig experimentieren, indem Sie std :: map verwenden, wie Sie dict in einigen anderen Sprachen verwenden, es ist schneller, einfacher, verführerischer und löst bereits Probleme, wenn Sie später die UTF-Kodierung unterstützen wollen.

Aber wenn Sie bereits wissen, dass es nur für ASCII-Text verwendet wird, gibt es einen anderen Weg.

Ihr Universum für ASCII ist 0-255 (eigentlich 0-128, aber ignorieren Sie das, falls jemand das erweiterte ASCII verwendet). Dies bedeutet, dass wir tatsächlich in einem angemessenen Raumabdeckung alle Ergebnisse mit einem

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

Sie können dann mit

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

Ihre innere Schleife ersetzen und schreiben Sie später das Ergebnis

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

Diese sollte in etwa die gleiche Raumnutzung wie ein std::map, aber bessere Lokalität und viel bessere Nachschlagezeit sein. Sie könnten mit nur 27 Buchstaben auskommen, aber das fügt mehr Bedingungen hinzu.Hier

0

ist ein Beispiel für die ich verwendet habe map und structured binding zum Zählen der Frequenz des Briefes

Neue Funktion von C++ 17 verwendet

1.If Aussage mit initializer

  1. Struktur Bindung
#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; 
} 

Ausgabe

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

Ich denke, ich bin ziemlich nah dran, aber aus irgendeinem Grund zählt mein Programm aus irgendeinem Grund mehr "C", aber alle anderen Charaktere scheinen gut zu zählen. –

+0

@Cory Hall Großartig, wenn Sie möchten, können Sie Ihren neuen Code posten –

Verwandte Themen