QVector<QString> Probleme beim Vergelich anderem QStri

Du bist neu in der Welt von C++? Dann schau hier herein!
Antworten
Marcus Breuer
Beiträge: 113
Registriert: 31. März 2011 17:19
Wohnort: Aachen
Kontaktdaten:

QVector<QString> Probleme beim Vergelich anderem QStri

Beitrag von Marcus Breuer »

Guten Abend oder auch schon guten Morgen,

ich habe das folgende Problem:

Code: Alles auswählen

/* 
    Wenn ein Wert in das QlineEdit input eingegeben wurde
    soll dieser Wert in einem Vektor gespeichert werden,
    um zu verhindern, dass zweimal der gleiche Qstring 
    eingelesen wird. 
*/

void Hauptfenster::add_to_field() {
    QString eingabe = input->text();		
    QVector<QString> v;
    for(int i=0; i<=v.size(); i++) {
        if(eingabe != v.value(i)) {
            v.append(eingabe);
            listfield->addItem(eingabe);
            input->clear();
        }
        else {

        }
    }


}
Im Kommentar steht drin, was in etwa passieren soll. Leider stürzt mein Programm dabei immer wieder ab, bzw es bleibt hängen.
Ich habe die Referenz schon durchgeschaut, vielleicht verstehe ich da aber auch etwas falsch.
Laufe ich beim Vektor schon außerhalb der Grenzen?
das v.value soll ja laut Referenz und in diesem Bsp. hier einen QString zurückliefern. Der Wert, mit dem er verglichen werden soll ist ja auch ein QString. Läuft da etwas schief?
Ich sitze da schon eine Weile dran.

Auf Antworten wir: Lern C++ und co habe ich jedoch keine Lust, da ich das zu oft schon in anderen Beiträgen gelesen habe. Ich bin Anfänger und will es lernen und bitte daher um Hilfe, die mich weiterbringt. Es muss auch keine komplette Lösung sondern nur ein Ansatz sein. Ich will mir den Rest dann selbst erarbeiten.

MfG
Marcus Breuer
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Leider ist der Fehler ein Grundlagenproblem :/

Code: Alles auswählen

void Hauptfenster::add_to_field() {
    QString eingabe = input->text();      

// v ist ein lokales Objekt, es ist leer, size() == 0
    QVector<QString> v;

// Deine Schleife startet bei 0, die Schleifenbedingung liefert aber bei size()==0 schon true.
// Bei korrekter Bedingung "i<v.size()" wird die Schleife aber nie betreten.
    for(int i=0; i<=v.size(); i++) {

// Im ersten Durchlauf ist i=0, size() == 0, value(i) greift außerhalb der Grenzen von v zu -> Crash
// Außerdem: So lange eingabe != value(i), läuft deine Schleife, in jedem Durchlauf wird deine Schleife größer, sie endet NIE!
        if(eingabe != v.value(i)) {
            v.append(eingabe);
            listfield->addItem(eingabe);
            input->clear();
        }
        else {

        }
    }


}
Wenn du etwas speichern willst, sollte der Speicherort (QVector v) auch lange genug existieren. Mache den Vector zu einem Member deiner Klasse.
Und um zu prüfen, ob im Vector ein Element enthalten ist, gibt es QVector::contains().

Ich hoffe das ist jetzt halbwegs klar.
Marcus Breuer
Beiträge: 113
Registriert: 31. März 2011 17:19
Wohnort: Aachen
Kontaktdaten:

Beitrag von Marcus Breuer »

Guten Morgen franzf,

es tut mir echt Leid, dass ich den Codemüll überhaupt gepostet hatte. Saß bis 04:00Uhr an dieser Sache und bin eben schon wieder wach geworden und habe mir nochmal den Code angesehen. Dabei habe ich mich dann gefragt, warum ich so blöd war, den QVector in der Funktion zu deklarieren.

Ich hatte das, (ehrlich:)) gelöst, bevor Du geantwortet hattest und wollte das gerade auch posten, damit sich keiner mehr die Mühe macht, mir darauf zu antworten.

Ich brauche allerdings nichtmal einen QVector. Die Daten, die eingelesen werden, brauchen nicht sortiert werden. Deswegen habe ich mich für QSet<QString> entschieden. Das habe ich jetzt im Header der Klasse zu der auch die gezeigte Funktion gehört als private angelegt und fülle es dann aus der Funktion heraus. So klappt es wunderbar.

Dennoch vielen vielen Dank für deine Antwort. Es war schon spät, sonst wäre ich vllt. schon gestern Abend drauf gekommen.

Eine Frage habe ich dennoch: Ich brauche keine sortierten Daten und auch keine großartigen Optionen auf die erstellte "Liste". Ist das QSet dann wirklich das schnellste? Das habe ich eben jedenfalls so gelesen.

Noch der Code, wie ich es gelöst habe und wie es genau meinen Wünschen entsprechend funktioniert:

Code: Alles auswählen

/* QSet<QString> list ist wie oben beschrieben deklariert */ 

void Hauptfenster::add_to_field() {
    QString eingabe = input->text();
    if(list.contains(eingabe)) {
        input->clear();
    }
    else {
    list.insert(eingabe);
    listfield->addItem(eingabe);     
    input->clear();
    }
}
Marcus Breuer
Beiträge: 113
Registriert: 31. März 2011 17:19
Wohnort: Aachen
Kontaktdaten:

Beitrag von Marcus Breuer »

So, direkt noch der Nachtrag, der sich aber auch als Frage entpuppen wird:)

Wie genau testet Ihr, ob bspw. die eine oder die andere Funktion schneller ist?
Oder in dem Fall das QSet vielleicht den Anforderung entsprechend dem QVector vorzuziehen ist oder nicht?

Wie gesagt, ich versuche mich noch mit dem Frischlingsstatus zu schützen. Also nicht böse werden, wenn das für Euch etwas total Triviales ist.

Schönen ersten Mai. Grüße,
Marcus Breuer
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Ein QVector ist nicht sortiert. Im Prinzip ist das nur ein sich selbst in der Größe anpassendes C-Array (die Daten liegen in einem zusammenhängenden Block im Freispeicher). Prinzipiell ist das der Container, der in den meisten Fällen reicht. Schnell genug, kein Memory-Overhead, schnelles Anhängen, ...). Nur das Einfügen/Löschen in der Mitte ist langsam, aber das brauchst du nicht.
Ein QSet hat schon einen gewissen Overhead: Hash bilden, hashtable speichern, usw. Ein QSet ist sicher eine tolle Sache, wenn du richtig viele Einträge hast.

Und an der Anzahl der zu erwartenden Einträge würde ich mich orientieren. Wie viel erwartest du denn?
Marcus Breuer
Beiträge: 113
Registriert: 31. März 2011 17:19
Wohnort: Aachen
Kontaktdaten:

Beitrag von Marcus Breuer »

Danke für die schnelle Antwort. Es macht echr Spaß in dem Forum.

Ich rechne in etwa mit Einträgen in der Größenordnung zwischen 10 und 40. Also denke, dass das dann kein Problem für den Rechner darstellen sollte. In
einem Praktikum mussten Komilitonen von mir mit 40000 Werten rechnen. Da macht es dann glaube ich Sinn sich über sowas Gedanken zu machen.

Gibt es denn über den Creator eine gewisse Möglichtkeit, sage ich mal, die Performance zu messen? Bspw in Fom von Zeitmessung? Also nicht, dass ich mit der Stoppuhr dann vorm PC sitze.
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag von padreigh »

Es gibt QTime und dort .elapsed() http://doc.trolltech.com/latest/qtime.html - das ist bei solch kleinen Datensätzen nicht genau genug ... ich genke mal die 40 (oder auch 400/4000/40000) Werte schluckt der ohne Probleme - vor allem da du ja das ganze auf menschliche Eingaben ansetzt die wohl kaum mit 10000/Sekunde reinpreschen werden. Der kann also ganz gemütlich Zeug reinhashen ;)

http://doc.trolltech.com/latest/qtime.html
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

10-40 -> QVector. Das contains() ist schnell genug, und das Anhängen kostet in den meisten Fällen nur das Kopieren des Objekts.
Bei 40000 kann man über QSet nachdenken.

Wg. Performance: Wenn du nicht merkst, dass es langsam läuft, bleib bei deiner Lösung.
Marcus Breuer
Beiträge: 113
Registriert: 31. März 2011 17:19
Wohnort: Aachen
Kontaktdaten:

Beitrag von Marcus Breuer »

ok, super, danke euch beiden. ich werde von zeit zu zeit, sollte ich es mal mit größeren datenmengen aufnehmen wollen machen wie padreigh sagte und ansonsten wohl erstmal so weiter machen wie bisher.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Wg. Performance: Wenn du nicht merkst, dass es langsam läuft, bleib bei deiner Lösung.
Das kann man auch noch ausbauen ! :

zuerst die schnelle (und trotzdem hoffentlich sichere) Version implementeiren, und dann spaeter beim tuning abschaetzen, ob man da overhaed für performance betreiben soll.

Wobei auch wiederum gilt, wenn die schnellere (performante) keinen signifikanten mehraufwand hat, keine seitenefffekte etc ... und genau so sicher ist, sollt man natuerlich gleich die performantere Version nehmen.

In deinem Fall trifft eher das letztere zu.
Container, vor allem Ihr verhalten solltest aus dem FF können, also mit fortgeschrittenen Level :-) Das geht mal so ins Blut ueber, das dir immer zuerst überlegst, was machst mit dem, und danach leitest ab, welchen container du brauchst.

In deinem Fall:
du brauchst nicht sortiert, du musst nicht "schnell" nach gewissen Elementen in Deinem container suchen -> kein Set
Du brauchst die Daten nicht am Stueck (keine C-Kompatiblitaet) und auch ein superschneller zugriff auf den Index (Xte element) brauchst nicht -> kein Vector.
Du laeufst die Liste fast immer nur komplett durch (iteration), der container dafuer mit der "besten performance" und den wenigsten Anforderungen ist die verkettete Liste -> QLinkedList (std::list)

Ciao ...
Antworten