Häufigkeit Zeichen aus Datei/String



  • auto it = std::max_element(test.begin(), test.end());
    

  • Mod

    Du liest übrigens das letzte Zeichen der Datei falsch ein. Ein Stream setzt das eof-Flag, nachdem eine Leseaktion an mangelnden Daten scheitert, nicht davor.

    P.S.: Willst du die Verteilung nicht ohnehin sortiert haben? Deine nächste Frage wäre doch bestimmt, was das zweithäufigste Zeichen ist.



  • A ok danke Sepp & Cooky.

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

    Sepp, naja ich wollte eingentlich das häuftigste Zeichen im Verschlüsselten Text (wahrscheinlich "e" oder wohl eher "leerzeichen"). Danach hätte ich die Differenz zwischen e bzw. "leerzeichen" und dem häuftigsten Zeichen im Text errechnet und hätte so den Schlüssel um den Text du entschlüsseln ( mit caeser verschlüsselt)



  • ...



  • Danke. Man lernt die aus und das ist wohl an mir vorbei gegangen 🙂



  • 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... 🙂


Anmelden zum Antworten