ComboBox mit Schleife?



  • ich habe jetzt den code folgendermaßen aufgebaut und mit den änderungen von audacia versehen:

    for(int cbi=1;cbi<=6;cbi++)
        {
            for(int ctrli=0;ctrli<this->ControlCount;ctrli++)
            {
                TComboBox* cbTemp = dynamic_cast <TComboBox*> (this->Controls[ctrli]);
                if (cbTemp != 0) {
                    if(cbTemp->Name=="ComboBox"+IntToStr(cbi))
                    {
                        // sFileNames ist ein Array vom Typ String oder AnsiString!
                        slTemp->LoadFromFile(sFileNames[cbTemp->ItemIndex]);
                        for(int i=0;i<slTemp->Count;i++)
                        {
                            RichEdit1->Lines->LoadFromFile (sFileNames[cbTemp->ItemIndex]);
                        }
    
                    }
                }
            }
        }
    

    Er compiliert und schreibt mir den Text aus der Datei auch ins RichEdit aber die Fehlermeldung "Exception der Klasse EAccessViolation" Zugriffsverletung bei Adresse 4000ECC7 in Modul 'rtl60.bpl'...kommt trotzdem nachdem ich den Button gedrückt hab.



  • audacia schrieb:

    heini schrieb:

    programmiertechnisch schlechter Stil

    Da muß ich das dann doch ein wenig konkretisieren 😉

    Danke fuer deine Hinweise, aber deine Kritik muss ich an folgender Stelle in Frage stellen:

    Dein Code verursacht ein Speicherleck, wenn eine Exception geworfen wird. Eine gute Faustregel ist: wenn du delete verwendest, machst du etwas falsch. Nimm einen Smart-Pointer oder std::vector<>.

    Hast du dir den Quelltext nicht richtig angesehen oder irrst du dich in einem Punkt vielleicht? Ich meine: Wenn man ein Objekt erstellt und Speicherbereiche verwendet, sollte man diese auch wieder freigeben. Geschieht das nicht durch diesen Code?

    TStringList* slTemp;
    //...
    delete slTemp;
    

    testman schrieb:

    for(int i=0;i<slTemp->Count;i++)
    {
        RichEdit1->Lines->LoadFromFile (sFileNames[cbTemp->ItemIndex]);
    }
    

    Das musst du mir jetzt mal erklaeren: Du versuchst fuer jede Zeile, die in slTemp enthalten ist, die ganze Datei in dasselbe RichEdit komplett zu laden?

    LoadFromFile ersetzt doch alle vorhandenen Zeilen, oder irre ich mich? Wenn du Dateien zusammenfuegen moechtest, musst du den Weg ueber die temporaere StringList gehen (dafuer ist slTemp auch gedacht) und jede Zeile einzeln einfuegen.



  • heini schrieb:

    Hast du dir den Quelltext nicht richtig angesehen oder irrst du dich in einem Punkt vielleicht? Ich meine: Wenn man ein Objekt erstellt und Speicherbereiche verwendet, sollte man diese auch wieder freigeben. Geschieht das nicht durch diesen Code?

    TStringList* slTemp;
    //...
    delete slTemp;
    

    Was passiert, wenn in dem Code zwischen new und delete eine Exception geworfen wird?

    heini schrieb:

    LoadFromFile ersetzt doch alle vorhandenen Zeilen, oder irre ich mich? Wenn du Dateien zusammenfuegen moechtest, musst du den Weg ueber die temporaere StringList gehen (dafuer ist slTemp auch gedacht) und jede Zeile einzeln einfuegen.

    Ah, das Zusammenfügen war mir entgangen. Es ist dennoch nicht notwendig, jede Zeile einzeln anzuhängen; dafür gibt es TStrings::AddStrings.



  • audacia schrieb:

    delete eine Exception geworfen wird?

    Ah, daher weht der Wind. Jetzt kann ich das nachvollziehen. Gut, da muesste man sich eine Loesung ueberlegen, evtl. mit

    try
    {
        // Versuch
    }
    catch(...)
    {
        delete slTemp;
    }
    

    Oder so...

    Ah, das Zusammenfügen war mir entgangen. Es ist dennoch nicht notwendig, jede Zeile einzeln anzuhängen; dafür gibt es TStrings::AddStrings.

    Stimmt, auf die Methode bin ich gar nicht gekommen. Dann waere das also auch abgedeckt. Jetzt darf der Herr testman das alles noch auswerten und seine Loesung praesentieren. Ich bin gespannt.



  • heini schrieb:

    Ah, daher weht der Wind.

    Vielleicht solltest du meine Postings richtig lesen 😉

    audacia schrieb:

    Dein Code verursacht ein Speicherleck, wenn eine Exception geworfen wird.

    heini schrieb:

    Gut, da muesste man sich eine Loesung ueberlegen, evtl. mit

    try
    {
        // Versuch
    }
    catch(...)
    {
        delete slTemp;
    }
    

    Was passiert, wenn keine Exception geworfen wird? 😉

    Nein, die Lösung ist ganz simpel, wurde von mir schon genannt und heißt Smart-Pointer (konkret: std::auto_ptr<>).



  • audacia schrieb:

    Was passiert, wenn keine Exception geworfen wird? 😉

    try
    {
       //Versuch
    }
    catch(...)
    {
       //Fehlermeldung	
    }
    __finally 
    {
       delete slTemp;
    }
    

    😃



  • halloei schrieb:

    try
    {
       //Versuch
    }
    catch(...)
    {
       //Fehlermeldung	
    }
    __finally 
    {
       delete slTemp;
    }
    

    try/catch und try/finally können nicht kombiniert werden. Falls überhaupt, dann so:

    try
        {
            try
            {
               // Versuch
            }
            catch(...)
            {
               // Fehlermeldung (wozu eigentlich? Dafür sorgt doch die VCL.)
            }
        }
        __finally
        {
        }
    

    Und dann sind wir schon fast bei

    if (value == true)
      return true;
    else
      return false;
    

    😃



  • Hallo

    Das __finally sollte im C++ Builder ersetzt werden durch die konsequente Verwendung von RAII, sprich die Ausnutzung der Konstruktoren/Destruktoren von lokalen Objekten. Alle Ressourcen sollten sich selber automatisch aufräumen, sobald sie ihren Gültigkeitsbereich verlassen.
    Im Notfall ist dafür ein schon angesprochener Smart-Pointer zu benutzen.

    bis bald
    akari



  • Danke nochmal an alle für die Tipps!
    Habe jetzt den Code nochmal angepasst und es funktioniert auch solange ich TXT-Dateien verwende!
    Bei RTF-Dateien gibt er mir den Fehler: "Fehler beim einfügen von RichEdit-Zeile"
    Da ich auf die Formatierungen in den RTFs angewiesen bin brauch ich aber dafür eine Lösung!
    Hoffe das von euch noch wer einen guten Vorschlag hat!!

    ...
    AnsiString sFileNames[]=
    {
        "test.txt",
        "test.rtf",
    };
    ...
    ComboBox1->Items->Add(sFileNames[0]);
    ComboBox1->Items->Add(sFileNames[1]);
    ComboBox2->Items->Add(sFileNames[0]);
    ComboBox2->Items->Add(sFileNames[1]);
    ...
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    
        // Die Funktion LoadFromFile ersetzt den aktuellen Text,
        // darum muss das ueber eine temporaere Variable geschehen.
        TStringList *slTemp=new TStringList;
    
        // Da von der ersten zur letzten ComboBox hingearbeitet werden soll,
        // muss zuerst diese Schleife durchlaufen:
        for(int cbi=1;cbi<=2;cbi++)
        {
            for (int ctrli = 0; ctrli < this->ControlCount; ctrli++)
            {
               TComboBox* cbTemp = dynamic_cast <TComboBox*> (this->Controls[ctrli]);
                if (cbTemp != 0)
                    {
                    if(cbTemp->Name=="ComboBox"+IntToStr(cbi))
                      {
                        // sFileNames ist ein Array vom Typ String oder AnsiString!
                        if(cbTemp->ItemIndex!=-1)
                        {
                            slTemp-> LoadFromFile (sFileNames[cbTemp->ItemIndex]);
                            RichEdit1->Lines->AddStrings(slTemp);
                        }
                      }
                    }
              }
        }
        // Speicher freigeben...
        delete slTemp;
    
    }
    


  • Hi,

    ersetze in Zeile 36 den Code mit

    RichEdit1->Text = slTemp->Text;
    

    mfg
    kpeter



  • kpeter schrieb:

    RichEdit1->Text = slTemp->Text;
    

    Und noch immer moechte er mehrere Dateien zusammenfuegen, also korrekterweise:

    RichEdit1->Text+=slTemp->Text;
    


  • heini schrieb:

    kpeter schrieb:

    RichEdit1->Text = slTemp->Text;
    

    Und noch immer moechte er mehrere Dateien zusammenfuegen, also korrekterweise:

    RichEdit1->Text+=slTemp->Text;
    

    Lass ihm doch auch noch was zum Denken übrig.



  • kpeter schrieb:

    Lass ihm doch auch noch was zum Denken übrig.

    Naja, ich wollte halt nicht, dass da jemand verzweifelt. Ich kenne solche Kleinigkeitsfehler selbst und weiss, wie sehr man sich aergert, an solchen Stellen...



  • Am Rande,

    @Heini, @kpeter,
    Ich hab immerwieder erlebt, dass man, nur dadurch, dass man sein Problem anderen erklären möchte, seinen eigenen Denkfehler erkennt. Aber leider hat der BCB heute soviele Funktionen und Methoden, dass man nicht mehr alle durchschauen kann - da hilft oft auch nicht mehr die Hilfe.
    Ich bin ein Fan von selber denken, aber man sollte unterscheiden, ob man kann oder nicht, oder einfach zu faul ist.

    Rudi



  • hallo @all!
    ich finde es total klasse, wie ihr einem helft!
    ---offtopic---
    ich habe eine ausbildung zum kaufm. assistenten für informatik gemacht und da wird programmierung nur angerissen!
    ---offtopic---
    ich finde persönlich das man selber nachdenken muss, um auch die hintergründe zu verstehen aber gerad wenn man nicht weiterkommt und sich in einem weg verrennt braucht man tipps und vorschläge um auch zum ziel zu kommen!
    ALSO VIELEN DANK AN DIESER STELLE AN ALLE!

    kpeter schrieb:

    heini schrieb:

    kpeter schrieb:

    RichEdit1->Text = slTemp->Text;
    

    Und noch immer moechte er mehrere Dateien zusammenfuegen, also korrekterweise:

    RichEdit1->Text+=slTemp->Text;
    

    Lass ihm doch auch noch was zum Denken übrig.

    Das zum beispiel kannt ich noch gar nicht, dachte bislang man macht es über:

    RichEdit1->Text = RichEdit1->Text + slTemp->Text;
    

    Also wieder was gelernt, obwohl ich mit dem "+=" nicht zurecht komme 😞
    Finde dazu auch noch nichts in der Hilfe...hmmm mal weitersuchen!



  • testman schrieb:

    ... obwohl ich mit dem "+=" nicht zurecht komme 😞
    Finde dazu auch noch nichts in der Hilfe...hmmm mal weitersuchen!

    Siehe unter operator +=.

    Operatoren gibt es einige; es lohnt sich, sich mit ihnen zu befassen, da sie den Code komplexer machen. Und erlernen kann man sie locker 😉

    mfg
    kpeter



  • @kpeter
    hab ich mir gerad durchgelsen 🙂

    habe jetzt 2 Fragen, da ich fast fertig bin...
    habe

    String *sFileNames;
    

    im header
    und

    sFileNames = new String[anzahl];
    

    bei FormCreate;

    wenn ich jetzt

    delete sFileNames;
    

    bei FormClose setze, kommt ein Exception-Fehler! Ebenso bei FormDestroy!
    Was mach ich da falsch?

    Und zu

    RichEdit1->Text+=slTemp->Text;
    

    wäre meine Frage, wieso ich nichts angezeigt bekomme aber auch keine Fehlermeldung erhalte!?

    RichEdit1->Text=slTemp->Text;
    

    funktioniert aber nur eins!



  • Ja, beim AnsiString gibt es da mit dem Operatoren += wohl so einige Schwierigkeiten. Versuch's mit deinem Weg.

    Zu sFileNames : Versuch das mal bitte ohne Zeiger, also mit

    String sFileNames[ANZAHL];
    

    im Header, oder aber - wenn du sehr ehrgeizig bist - im private -Bereich von TForm1 .



  • testman schrieb:

    Und zu

    RichEdit1->Text+=slTemp->Text;
    

    wäre meine Frage, wieso ich nichts angezeigt bekomme aber auch keine Fehlermeldung erhalte!?

    Weil du dich nicht an die Regeln zur Benutzung von Properties hältst.

    In einer früheren Diskussion hatte ich die Regeln mal grob hier zusammengefaßt.


Anmelden zum Antworten