Häufigkeit Zeichen aus Datei/String



  • Mein GCC hat leider noch kein 11



  • Swordfish schrieb:

    Jolle schrieb:

    Was hat es mit "auto it" auf sich, kann mein compieler leider nichts mit anfangen.

    C++11 – Part 1: Automatic Types

    Dann eben

    char ch = max_element(test.begin(), test.end())->first;
    

    Bin eben erst dazu gekommen es auszuprobieren. Bei deinem Code gibt er leider einfach das letzte Zeichen aus nicht das was am meisten in der map vorkam.



  • #include <fstream>
    #include <iostream>
    #include <vector>
    #include <string>
    #include <set>
    
    struct CharCount
    {
    	explicit CharCount(unsigned char c, std::size_t count)
    		: c(c), count(count)
    	{ }
    
    	unsigned char c;
    	std::size_t count;
    };
    
    bool operator < (CharCount const& lhs, CharCount const& rhs)
    {
    	return lhs.count < rhs.count;
    }
    
    std::string getStreamContent(std::ifstream & str)
    {
    	std::string fileContent;
    	std::string tmp;
    
    	while ( std::getline(str, tmp) )
    	{
    		fileContent += tmp + "\n";
    		tmp.clear();
    	}
    
    	return fileContent;
    }
    
    std::set<CharCount> countChars(std::string const& strContent)
    {
    	std::vector<std::size_t> countings(std::numeric_limits<unsigned char>::max(), 0);
    	for(auto c : strContent)
    	{
    		countings[static_cast<std::size_t>(c)]++;
    	}
    
    	std::set<CharCount> frequenzy;
    	for(std::size_t i = 0; i < countings.size(); ++i)
    	{
    		frequenzy.insert(CharCount(static_cast<char>(i), countings[i]));
    	}
    
    	return frequenzy;
    }
    
    int main()
    {
    	std::string filename;
    	std::cout << "Dateiname: ";
    	std::getline(std::cin, filename);
    
    	std::ifstream file(filename.c_str());
    	if ( !file )
    	{
    		std::cerr << "Datei gibt es nicht" << std::endl;
    		return -1;
    	}
    
    	std::string fileContent = getStreamContent(file);
    	auto frequenzy = countChars(fileContent);
    
    	for(auto cc : frequenzy)
    	{
    		std::cout << "\"" << cc.c << "\"" << "(" << static_cast<std::size_t>(cc.c) << ") -> " << cc.count << std::endl;
    	}
    
    	std::cin.get();
    	return 0x0;
    }
    

    wäre eine halbwegs flexible Möglichkeit



  • ...



  • Habe es jetzt hiermit gelöst

    typedef map<char, int> test;

    struct less_value {

    bool operator()(test::value_type const& l, test::value_type const& r) {
    return l.second < r.second; // second ist der Wert eines Map-Elementpaars
    }
    };


  • Mod

    Warum eine Klasse mit operator(), aber ganz ohne Member? Das ist eine Funktion!



  • Ich habe hier mal noch ein abstrakte Lösung:

    #include <algorithm>
    #include <fstream>
    #include <iostream>
    #include <iterator>
    #include <map>
    #include <string>
    #include <utility>
    using namespace std;
    
    struct most_occurrence
    {
    	template <typename T>
    	bool operator()(const T& lhs, const T& rhs)
    	{
    		return lhs.second < rhs.second;
    	}
    };
    
    template<typename Iter>
    typename map<typename iterator_traits<Iter>::value_type,unsigned>
    all_occurrences(Iter begin, Iter end)
    {
    	map<typename iterator_traits<Iter>::value_type,unsigned> count;
    
    	for(Iter it=begin; it!=end; ++it)
    	{
    		++count[*it];
    	}
    	return count;
    }
    
    int main()
    {
    	ifstream file("test.txt");
    
    	const string content( (istreambuf_iterator<char>(file)), (istreambuf_iterator<char>()) );
    
    	const map<char,unsigned> occurrences = all_occurrences( content.begin(), content.end() );
    
    	const pair<char,unsigned> most = *max_element( occurrences.begin(), occurrences.end(), most_occurrence() );
    
    	for(map<char,unsigned>::const_iterator it=occurrences.begin(); it!=occurrences.end(); ++it)
    	{
    		cout << it->first << ": " << it->second << 'x' << '\n';
    	}
    	cout << most.first << " kommt auf haeufigsten vor: " << most.second << 'x' ;
    }
    


  • SeppJ schrieb:

    Warum eine Klasse mit operator(), aber ganz ohne Member?

    Sowas lässt sich viel leichter inlinen.



  • SeppJ schrieb:

    Warum eine Klasse mit operator(), aber ganz ohne Member? Das ist eine Funktion!

    Will max_element nicht einen Functor?


  • Mod

    duh schrieb:

    Sowas lässt sich viel leichter inlinen.

    Nein.

    out schrieb:

    Will max_element nicht einen Functor?

    Nein, max_element will irgendetwas aufrufbares. Irgendetwas, so dass der Code comp(a,b) etwas sinnvolles ergibt.



  • SeppJ schrieb:

    duh schrieb:

    Sowas lässt sich viel leichter inlinen.

    Nein.

    out schrieb:

    Will max_element nicht einen Functor?

    Nein, max_element will irgendetwas aufrufbares. Irgendetwas, so dass der Code comp(a,b) etwas sinnvolles ergibt.

    Wie würde es denn ohne Functor gehen?

    template <typename T>
    	bool most_occurrence(const T& lhs, const T& rhs)
    	{
    		return lhs.second < rhs.second;
    	}
    
    	// Error: Funktions-template "bool most_occurrence(const T &,const T &)" kann nicht als Funktionsargument verwendet werden.
    	const pair<char,unsigned> most = *max_element( occurrences.begin(), occurrences.end(), most_occurrence );
    


  • ...


  • Mod

    @out: Mit deinem template würde das auch gehen, du musst es aber natürlich noch instanzieren.



  • Danke swordfish so klappts auch wunderbar! Jetzt noch der Rest und die häufigkeitsanalyse für den caeser code ist fertig.



  • Ich erinnere noch kurz an cooky451s Vorschlag:

    cooky451 schrieb:

    Bei 8 bit kannste auch nen unsigned arr[256] = {} nehmen.

    #include <algorithm>
    #include <iostream>
    
    int main(){
      int histogram[256]={0};
      histogram['y']=2;
      histogram['q']=1;
      histogram['e']=47;
      histogram['u']=19;
      const char ch = std::max_element(histogram, histogram+256) - histogram;
      if(31<ch && ch<256)
        std::cout << '\'' << ch << "\'\n";
    }
    

    Für die Puristen... 🙂



  • von mir noch der Hinweis: char zuerst auf unsigned char casten und dann weiterarbeiten

    wenn mann z.B. char auf unsigned int castet, schiebt der Compiler noch einen unerwünschten cast dazwischen: char -> int -> unsigned int

    (für Zeichen > 127)



  • Noch eine Frage... 😞

    Kennt jemand das Zeichen " „ ", wenn ich es caste wird mir es als -124 dargestellt. In der ASCII Tabelle finde ich es irgendwie nicht, aber c++ stellt es dar wenn man eine -124 als char ausgibt.

    Danke 🙂



  • Das ist auch nicht ASCII, sondern Windows-1252 (Zeichen 132, weil -124 = 132 (mod 256)). Es handelt sich dabei um eine spezielle Kodierung, die von der Windows-Konsole verwendet wird, wenn man sie nicht anders zwingt. Und eigentlich auch so ziemlich nur da.



  • also wenn ich " „ " bzw. -124 auf unsigned char caste bekomme ich 132 bzw. 0x84 und das ist der untere Anführungsstrich bei „”

    http://de.wikipedia.org/wiki/Latin-1#Windows-1252


  • Mod

    Das ist eben ein nicht-ASCII Zeichen. -124 ist als unsigned 8-Bit Wert 132. Das Zeichen 132 im Windows-1252 ist "„". Hieraus folgere ich, dass du vermutlich eine Windowskonsole zur Ausgabe benutzt, die diesen Wert eben als dieses Zeichen ausgibt.

    Für dein ganzes Programm sind chars nur Zahlen. Die ganze Darstellung als irgendwelche Zeichen findet ganz woanders statt. Dein Programm bekommt bloß einen Strom von Zahlen rein (die Standardeingabe) und gibt 2 Ströme von Zahlen (Standardausgabe, Standardfehlerausgabe, evtl. noch Standardlogausgabe) raus. Wie diese Zahlen dargestellt werden, ist Sache der Programmumgebung.

    (Es ist natürlich nicht ganz willkürlich: Wenn du dein Programm für eine bestimmte Umgebung übersetzt, dann muss der Übersetzer (der Compiler) sicherstellen, dass die Zeichen die du in deinem Quelltext benutzt auch zu dieser Umgebung passen. Wenn du bloß einen Zahlenwert (hier -124) im Quelltext benutzt, kann dieser natürlich nicht übersetzt werden, sondern wird einfach übernommen. Würdest du stattdessen den Universal-character-name für das Zeichen "„" benutzen, würde das Programm auch in nicht-Windowskonsolen auf gleiche Weise funktionieren (sofern die Umgebung das Zeichen darstellen kann).)


Anmelden zum Antworten