Häufigkeit Zeichen aus Datei/String



  • ...



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



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


Anmelden zum Antworten