Arbeiten mit der Konsole (Datei öffnen etc.)



  • Hallo Leute,

    ich benötige eure Hilfe um mein Programm wie gewünscht zu erweitern. Generell soll das wie folgt ablaufen:

    Der User soll dann konkret angeben was für eine Datei geöffnet werden soll, sprich welches Format diese besitzt (z.B. test.txt, test.asc, test.ans). Sprich es soll kontrolliert werden ob es sich um eine ASCII oder ANSI Datei handelt.

    Existiert die Datei und das öffnen gelingt so soll in Form einer kleinen Tabelle angezeigt werden:

    [Zeichen][Anzahl][Prozent]

    Die Prozent beziehen sich in dem Fall auf das einzelne Zeichen und seine Häufigkeit in Bezug auf die Gesamtzahl aller Zeichen.

    Was dann bei der Ausgabe natürlich berücksichtigt werden soll wäre, dass die Umlaute etc. korrekt in der konsole angezeigt werden. Sprich ein "Ä" auch als solches dargestellt wird.

    Hier erst mal mein Quellcode, bis auf die manuelle/expliziete Angabe bzgl. des Formats und der Punkt bzgl. der Umlaute funktioniert der Rest soweit schon.

    #include "stdafx.h"
    #include <iostream> //cout, cin + endl
    #include <fstream> // für ifstream
    #include <map> // map
    #include <locale> //locale
    #include <cstdlib> // EXIT_FAILURE
    #include <windows.h> // für ChartoOem und OemtoChar
    
    	using namespace std;
    
    	void freezeProg() 
    	{ 
    		cout << "\n";
    		cout << "Programm wurde angehalten! Zum Verlassen druecken Sie bitte Enter\n" << endl; 
    		cin.clear();
    	// Hier wird geprüft mit welche Taste gedrückt wurde, in dem Fall
    	// wird nur bei Enter reagiert :)
    		cin.ignore(cin.rdbuf()->in_avail()); 
    		cin.get();
    	}
    
    	typedef map<char, unsigned int> Tchar_counter;
    
    	int main(int argc, char *argv[])
    	{
    		// im char_counter befinden sich alle Zeichen aus der .txt
    		Tchar_counter char_counter;
    		// Anlegen einer char Variable, diese beinhaltet beim Programmaufruf das letzte Zeichen aus
    		// der .txt Datei
    		char character;
    
    		cout << "++++++++++++ Willkommen ++++++++++++";
    		cout << "\n";
    		cout << "Bitte waehlen Sie aus welches Format die Datei besitzt (ANSI,ASCII oder .txt)";
    		cout << "\n";
    		cout << "Bitte geben Sie den Namen der Datei ein, die Sie jetzt gerne oeffnen wollen\n";
    		cout << "\n";
    
    		// Einlesen der User Eingabe als string
    		string filename;
    		// ganze Zeile einlesen
    		std::getline(cin, filename);
    		cout << "\n";
    
    		// Einen Filebuffe anlegen
    		ifstream input(filename.c_str());
    		// Wenn die Datei nicht existiert, wird das Programm verlassen
    		if(!input.is_open())
    			return EXIT_FAILURE;
    
    		locale mylocale;
    		// die while Schleife geht die einzelnen Zeichen durch
    		// anschließend werden die Zeichen hochgezählt und die Prozentrechnung
    		// durchgeführt.
    		// Schließlich noch ein paar "Formatierungen" bei der Ausgabe
    		while(input.get(character))
    		{	
    			// Aus der C++ Reference: "Checks if parameter c is either an uppercase or a lowercase alphabetic letter."
    			// in character steht das letzte Zeichen
    			if(isalpha(character, mylocale))
    				character = tolower(character, mylocale);
    			// char_counter zählt entsprechend die Zeichen hoch
    			++char_counter[character];
    		}
    
    		Tchar_counter::mapped_type sum = Tchar_counter::mapped_type();
    		for(Tchar_counter::const_iterator i(char_counter.begin()), e(char_counter.end()); i != e;i++)
    		{
    			// Summiert die Zeichen aus der Datei -> Gesamtanzahl
    			sum +=i-> second;
    		}
    			cout << "[Zeichen]" << "[Anzahl]" << "[Prozent]" << endl;
    			cout << "\n" << endl;
    		// Genauigkeit der Ausgabe
    		cout.precision(2);	
    		for(Tchar_counter::const_iterator i(char_counter.begin()), e(char_counter.end()); i != e; ++i)
    		{
    			float percent = i->second/float(sum);
    			cout << "[" << i->first << "]" << "[" << i->second << "]" << "[" << percent*100 << "%" << "]" << endl;
    		}
    		// Hält das Programm an und wartet auf die Bestätigung
    		// mit Return, als Zeichen dafür,
    		// das der User das Programm wirklich verlassen will
    		   freezeProg(); 
    		   return 0;
    	}
    

    Natürlich habe ich schon in Foren etc. nachgeschaut und Stichpunkte wären ja beispielsweise CharToOem /OemToChar, jedoch hatte ich es bisher damit noch nicht zu laufen bekommen. So wurden z.B. alle Zeichen korrekt an meine Variablen übergeben, die Umwandlung jedoch funktionierte noch nicht.

    Falls mir da jemand helfen könnte wäre ich sehr dankbar! 🙂



  • hi,
    den sinn deiner anwendung kann ich zwar nicht nachvollziehen, aber für die anzeige der umlaute können dir diese funktionen helfen:
    SetConsoleCP, SetConsoleOutputCP, setlocale.



  • Habe es schon selber hinbekommen, dabei hatte ich mich dann für die setlocale entschieden, denke dass sollte ok / ausreichend sein um das problem mit den Umlauten recht simpel zu lösen 🙂



  • Mh leider gibt es doch noch Probleme.

    Also wenn ich beispielsweise 3, 4 Dateien anlege (.ans, .asc, .txt) und diese entsprechend fülle und beim abspeichern die verschiedenen Codierungen durchgehe (ANSI, Unicode, UTF etc.) dann funktioniert es soweit schon (außer bei UTF-8) mit der korrekten Anzeige.

    Was ich jedoch nicht verstehe ist das mir in der Konsole alle Zeichen (Zahlen, Buchstaben, Umlaute etc. pp) richtig angezeigt werden ABER zusätzlich noch weitere Zeichen oO.

    Wie z.B. irgendwelche "LATIN SMALL LETTER THRON" Zeichen und sowas.

    Hat da jemand eine Ahnung warum dem so ist?



  • die doofe windows konsole kann kein unicode.



  • Mh naja was ich daran nicht ganz verstehe ist eben, er zeigt mir die Zeichen soweit an aber packt noch weitere rein, so als stünde noch mehr Text in der Datei der so nicht direkt sichtbar ist.

    Hatte überlegt ob es vielleicht Blanks oder was in der Richtung sein könnten die dann eben als solche Zeichen interpretiert werden und deswegen mit angezeigt werden. Aber da dürften jetzt keine mehr drinstehen oder eigentlich auch keine anderen Zeichen die "umgewandelt" angezeigt werden 😕



  • hmm...hast du ein minibeispiel mit einem zeichen?



  • Also im Prinzip kannst du ja erst mal meinen Quellcode kopieren, musst halt nur das hier:

    puts(setlocale(LC_ALL,""));
    

    noch mit einfügen.

    Was mir gerade aber mal aufgefallen ist finde ich irgendwie sehr amüsant 😃

    Folgendes Szenario:

    Ich habe eine Datei erstellt (manuell) in Form einer Textdatei. Diese habe ich die Unicode Codierung zugeordnet (speichern unter halt ^^) und einfach mal das hier:

    !"§ÄÜÖ?ßöäüABCD12===<>|;_'*`?`??=()=()/)(%&/%$&&&!§$$*'+#ß092137
    

    reingehauen, soweit so gut, zumindest bei mir zeigt er mir alle Zeichen korrekt an in der Konsole. Jedoch stimmen die Prozentangaben nicht. Schlichtweg aus dem Grund das er mir die Anzahl der Zeichen, hier 64 mit in die Ausgabe (Tabellenform) mit reinpackt.

    [ ][64][49%] -> So in der ersten Klammer stehen vermutlich alle Zeichen drin, daneben die Anzahl und Prozent.

    Zu dieser, wie ich finde interessanten Angabe ergänzt er mir eben noch weitere Zeichen die nicht in der Datei zu finden sind ^^.



  • ja, die zeichen werden angezeigt, wenn sie in der aktukellen windows-codepage auch drin sind. ansonsten gibts die tollen kästchen.
    was deine extra-chars betrifft, hast du den BOM geskippt?



  • Achso, hieße also es werden einfach alle mitangezeigt und man kann das nicht so einfach verhindern? Nur warum kommen diese komischen Werte zustande 😕

    Und ich weiss gerade nicht genau was du mit "BOM geskippt" meinst ^^



  • naja, unter windows haut dir z.b. notepad nen bom an den anfang der datei rein. google mal nach byte order mark.



  • das mit dem bom gilt nur für unicode-formate, klar, ne. ansosnsten gilt: was man bei einer bestimmten codepage reinschreibt, kriegt man auch wieder raus - wenn nicht, ist irgendwo ein fehler.



  • Sehr interessant, die BOM Thematik kannte ich bisher noch gar nicht, vielen Dank für die Information. Das es nur für Unicode Formate gilt ist klar.

    Die Frage ist nur wie ich das problem lösen kann ^^ Da werde ich gerade noch nicht schlau raus.

    Was die Codepage angeht...gibt es da denn keine Möglichkeit das einzugrenzen damit er mir eben nicht diese weiteren Zeichen mit reinnimmt die ja unter anderem mein Ergebnis verfälschen 😕 Habe da bisher zumindest nichts zu gefunden.



  • bmth schrieb:

    Die Frage ist nur wie ich das problem lösen kann ^^ Da werde ich gerade noch nicht schlau raus.

    datei öffnen, und 'nachgucken', ob ein bom vorhanden ist. wenn ja - je nachdem, ob es sich z.b. um das utf 16 little endian -, utf 8- oder sonstwas für ein encoding handelt, ergibt sich die 'bearbeitungs-strategie', bzw. die algorithmen für die nutzdaten. die nutzdaten fangen direkt nach dem bom an, nachdem man ihn eingelesen und dann geskippt (übersprungen) hat.
    gibt ja nicht so viele bom, so um die 6 oder so.

    bmth schrieb:

    Was die Codepage angeht...gibt es da denn keine Möglichkeit das einzugrenzen damit er mir eben nicht diese weiteren Zeichen mit reinnimmt die ja unter anderem mein Ergebnis verfälschen 😕 Habe da bisher zumindest nichts zu gefunden.

    weis der geier, was das für zeichen sind. die windows-konsole ist da leider eingeschränkt, kann nicht alle zeichen anzeigen. kannst ja ne konsole mit nem rich edit control o.ä. emulieren, wenn du unbedingt das konsolen-feeling brauchst. das ding ist toll, zeigt alle zeichen an, ist aber leider auf windows begrenzt. oder etwas mit freetype2 bauen oder so...
    mfg,
    b0m



  • Ok, das mit dem skippen ist ja die eine Sache, jedoch habe ich noch ein anderes Problem.Meiner Meinung nach hat das jedoch nichts mit der "BOM" Thematik zu tun.

    Wenn ich jetzt die paar Testdateien durchgehe ist die Auflistung bei allen Formaten soweit korrekt. Jedoch habe ich z.B. bei "Little Endian" eine falsche Berechnung. Ich weiss nicht warum, aber aus irgendeinem Grund rechnet er mittendrin alle Zeichen zusammen und zeigt mir diese dann so an:

    [][63][49%]

    Die Addition der anderen Zeichen (mal abgesehen davon dass die 2 Zeichen durch das BOM noch mitaufgelistet werden) klappt soweit. Aber natürlich ist das Ergebnis dann eben insgesamt falsch was die Prozentwerte angeht 😕


Anmelden zum Antworten