C++ Newbie

McAvatar

Admiral Special
Mitglied seit
11.08.2004
Beiträge
1.268
Renomée
8
Standort
Bielefeld, NRW
Hallo Leute!

Ich versuche gerade, mich an C++ heranzutasten. Mit Java, PHP und Python habe ich Erfahrung, bei C++ lerne ich gerade die Grundlagen - das hat den Haken, dass ich von Templates, der STL oder gar Boost überhaupt keine Ahnung habe.

Aber erst mal zur Entwicklungsumgebung: Im Moment nutze ich CodeBlocks mit MinGW. Um die Syntax zu prüfen, nehme ich Cppcheck. Eclipse CDT war meine erste Wahl, allerdings komme ich nicht mal mit der Konfiguration klar... :]

Da ich mich gerade mit dem Thema Entropie und Information beschäftigt habe, ist ein kleines Programm zur Ermittlung der Shannon-Entropie als Erstlingswerk entstanden. Hilfreich wäre, wenn jemand mit mehr Ahnung drübergucken könnte. Meine Lösung funktioniert zwar, ist aber vermutlich nicht ein Paradebeispiel für Eleganz. *buck*

Code:
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <math.h>

using namespace std;

const unsigned char ae = static_cast<unsigned char>(132);
const unsigned char oe = static_cast<unsigned char>(148);

int main(int argc, char *argv[]) {
    
    if (argc < 2) {
        cerr << "Zu wenig Argumente, mindestens ein Dateiname ist anzugeben.";
        return 1;
    }
    
    for (int currentarg = 1; currentarg < argc; currentarg++) {
        ifstream inFile(argv[currentarg]);
        if (!inFile) {
           cout << "Eingabedatei " << argv[currentarg] << " kann nicht ge" << oe << "ffnet werden.";
        }
        int in;
        int data[256] = {0};
        int symbolcounter = 0;
        
        while (inFile.good()) {
              in = inFile.get();
              data[in]++;
              symbolcounter++;
        }
        
        inFile.close();
        
        cout << "Untersuchung der Datei " << argv[currentarg] << "\n";
        cout << "H" << ae << "ufigkeiten der Symbole:\n";
        double entropy = 0.0;
        
        for (int i=0; i<256; i++) {
            double p_i = (double)data[i] / (double)symbolcounter;
            if (data[i] != 0) {
               entropy -= p_i * (log(p_i) / log(2));
               cout << char(i) << " " << data[i] << "\n";
            }
        }
        cout << "Shannon-Entropie: " << entropy << " Bit pro Zeichen. \n \n";
    }
    
    return 0;
}
 
Schon die nächste Frage...

Ich parse zeilenweise eine Datei und lege die relevanten Daten in einem struct pro Zeile ab. Mittels eines vectors von Zeigern auf structs speichere ich die gefunden Gesamtdaten ab.

Code:
struct datum {
      unsigned int startPos;
      unsigned int endPos;
      unsigned int direction;
    };

vector<datum*> data;

datum* temp = new struct datum;
                    temp->startPos = atoi(vec.at(rptpos).c_str());
                    temp->endPos = endpos;
                    temp->direction = direction;

data.push_back(temp);

Scheint mir so richtig zu sein.

Code:
for (unsigned int i = 0; i < data.size(); i++) {
            cout << data.at(i)->startPos << " " << data.at(i)->endPos << " " << data.at(i)->direction << endl;
}

Wie würde der Zugriff aber mit einem Iterator funktionieren?

Code:
for (vector<datum*>::iterator it = data.begin(); it!=data.end(); ++it) {
}

Bekomme ich hier Zeiger auf structs zurück? Wie kann man die Elemente der structs ansprechen?
 
Mit *it oder it-> erhältst du das im vector gespeicherte Element, also hier einen Pointer. Den musst du nochmal derefernzieren um die Elemente selbst ansprechen zu können. Also:

Code:
for (vector<datum*>::iterator it = data.begin(); it!=data.end(); ++it) {
cout << (*it)->startPos << " " << (*it)->endPos << " " << (*it)->direction << endl;
}

Du kannst aber auch einen vector direkt aus structs erzeugen, dann ist die Syntax schöner. Man muss sich nur im klaren sein das der vector dann mit den Objekten/Structs selbst jongliert.

Code:
for (vector<datum>::iterator it = data.begin(); it!=data.end(); ++it) {
cout << it->startPos << " " << it->endPos << " " << it->direction << endl;
}
 
Danke,funktioniert. :)

Wie kann man am Besten die Performanz eines C++-Programms messen? Soweit ich das verstehe, misst clock() die CPU-Ticks, blendet also Laufzeiten anderer Programm aus, oder?
 
Zumindest bekommt man ungefähr die zwischen zwei Messungen verstrichene CPU-Zeit (Umrechnung mit dem Define CLOCKS_PER_SEC).
 
Gut, ich versuch's mal damit. Und die nächste Frage: Wie kann ich eine Binärdatei einlesen und dabei das EOF ignorieren? Mein erster Ansatz war

Code:
while (inFile.good())
            {
                symbol = inFile.get();

Allerdings stoppt hier das Einlesen mit dem ersten 0x1A-Zeichen. Das kann aber in meinen Dateien durchaus vor dem Ende auftauchen.
 
Du musst dem Inputfilestream sagen, dass du eine Binärdatei lesen willst. Beim öffnen also ios::binary mit angeben.
 
Tja, mal wieder eine Frage zum Thema:

Ich erzeuge eine Reihe von Objekten, die ich zu einer Liste hinzufüge.

Code:
std::list<CodedMarker*> rptList;
CodedMarker* marker = new CodedMarker(parseBuffer);
rptList.push_back(marker);

Wie kann ich jetzt die Liste als Parameter an eine Funktion übergeben? Der "normale" Weg, einfach den Typ std::list<CodedMarker> des Parameters anzugeben scheint ja nicht zu funktionieren.
.
EDIT :
.

Gut, pointer in einem STL-Container zu speichern, scheint keine gute Idee zu sein.

Also doch eher:

Code:
rptList.push_back(CodedMarker(parseBuffer));

Aber das nur nebenbei.
 
Hallo Leute,

ich habe eine Header-Datei Fibonacci.h, in der die Funktion probeFirstCoding deklariert wird:

Code:
#include "CodedRepeatMarker.h"

class Fibonacci {

enum codingType {BINARY, FIBONACCI};

/***************************************************************************/
public:

codingType probeFirstCoding(const std::vector<CodedRepeatMarker>& repeatList);

Die entsprechende Funktion ist in der Fibonacci.cpp definiert:

codingType Fibonacci::probeFirstCoding(const std::vector<CodedRepeatMarker>& repeatList) {
...

Ich kann diese Konstruktion allerdings nicht kompilieren:

Code:
Fehler: »CodedRepeatMarker« wurde in diesem Gültigkeitsbereich nicht definiert
Fehler: Templateargument 1 ist ungültig
Fehler: Templateargument 2 ist ungültig

Ich nehme mal an, das liegt an der Verwendung des vectors. Ich hab leider keine Idee, was ich ändern muss. Rufe ich die Funktion über die Datei auf, in der main() steht, ist das Kompilieren kein Problem. ???
 
Hmm... in der Definition scheint erstmal der Scope für das Enum zu fehlen:
Code:
[B]Fibonacci::[/B]codingType Fibonacci::probeFirstCoding(const std::vector<CodedRepeatMarker>& repeatList) {
...

EDIT:
Noch ein Nachtrag zu
Wie kann ich jetzt die Liste als Parameter an eine Funktion übergeben? Der "normale" Weg, einfach den Typ std::list<CodedMarker> des Parameters anzugeben scheint ja nicht zu funktionieren.
Gut, pointer in einem STL-Container zu speichern, scheint keine gute Idee zu sein.
Pointer in Containern können schon ne gute Idee sein, solang man darauf achtet den allokierten Speicher auch irgendwann wieder freizugeben. Und natürlich ist der Typ zur Übergabe nicht mehr std::list<CodedMarker> sondern eben auch std::list<CodedMarker*>. Ganz einfach.
 
Zuletzt bearbeitet:
Mit Boost würde ich mich nicht sehr stark auseinander setzten CXX11 hat viele Sachen jetzt drinne die Boost auch anbietet.
Zum mal würde ich statische Funktionen nur dar deklarieren wo man sieh unbedingt benötigt, ansonsten wird es Kompliziert mit Multithreading.
VS 11
GCC < 4.4
Unterstützen schon eine große untermenge des neuen Standards
 
Zuletzt bearbeitet:
Zurück
Oben Unten