Problem mit Datein und Strings



  • Oh mann, wo soll man hier anfangen?

    Das grundlegende Problem ist hier

    printf("%i: %s\n", j, zeilen[j]);
    

    printf ist nicht typsicher, deshalb verwendet man sowas in C++ auch nicht. Ein std::string ist nunmal kein C-String, deshalb kannst du ihn auch nicht ausgeben wie einen. Korrekt wäre

    printf("%i: %s\n", j, zeilen[j].c_str());
    

    Aber wie bereits angedeutet, schreibt man in C++

    cout << j << ": " << zeilen[j] << endl;
    

    noch was:

    1. Gewöhn dir die C typische Variablendeklaration ab. In C++ deklariert man Variablen dann, wenn man sie braucht. Nutze entsprechend RAII.

    2. Wenn schon std::string, dann auch komplett.
    Also statt

    char     filename[128];
    [...]
        cin.getline(filename, 127);
    

    besser

    string filename;
    getline(cin, filename);
    
    file.open(filename, ios::in);
    

    ios::in ist unnötig, du hast ja sowieso einen ifstream.
    Besser

    ifstream file(filename.c_str());
    
    file.seekg(0L, ios::beg);
    

    Unnötig. Nach dem Öffnen der Datei steht der Dateizeiger sowieso am Anfang.

    5. Wenn deine Datei mehr als 1024 Zeilen hat, hast du astreines undefiniertes Verhalten. Nutze vector<string> und push_back.



  • @groovemaster ich muss dir da bei einer sache wiedersprechen

    und zwar folgende aussage

    1. Gewöhn dir die C typische Variablendeklaration ab. In C++ deklariert man Variablen dann, wenn man sie braucht. Nutze entsprechend RAII.

    erstens ist in c++ nirgends festgelegt das man alles erst eine zeile bevor man die variable braucht deklariert daraus folgt deine aussage ist schonmal falsch

    zweitens schau dich doch mal im netzt um (ich fasse es mal kurz zusammen)

    wenn es überall im programm gebraucht wird deklariert man das am anfang einer datei oder bei großen projekten mit vielen dateien kann man auch eine große header datei extra fürs deklarieren von variablen struct vectoren usw. anlegen

    wenn etwas nur innerhalb einer funktion gebraucht wird wird es dort am anfang der funktion nicht irgendwo zwischendrin deklariert

    dies ist steht so in sämtlichen richtlinien und tutorial zu sauberen programmierstil

    ausserdem wird es in firmen mit vielen entwicklern auch so verlangt Z.B. Simens
    da es nicht zuzumuten ist das ein entwickler eines teams z.b. deklaration eines chars im quelltext erst suchen muss

    ausserdem fördert dein ratschlag fehlerhaften code

    z.b.

    char1[255]
    char2[300]

    wenn du char2 in char1 kopieren willst fällt dir wenn beide untereinander sind sofort auf das char2 zu groß ist wenn man es aber wie du machst und zwischen beiden etliche zeilen code liegen fällt das nicht so schnell auf



  • Zur Variablendefinition:

    Auch wenn manche nicht glauben werden, aber alleine aus Effizienzgründen ist es meistens schon sinnvoller, Variablen erst dann zu definieren, wenn man sie wirklich braucht.

    Warum sollte ich erst zig Konstruktoren aufrufen und Felder allozieren, wenn ich sie in der Funktion "vielleicht" benötige?

    Stell Dir vor file.good() produziert in dem hier beschriebenen Programm ein false. Dann hättest du jeweils 1024 Konstruktor- und und Destruktoraufrufe um die Ausgabe "Datei nicht gefunden" zu produzieren.

    Sauberes Programmieren hängt meiner Meinung nach mehr von sauberem Klassendesign ab.

    Gruss

    turing



  • In jedem guten C++ Buch (dazu gehört auch das von Bjarne Stroustrup) steht drin, das man AUCH aus Performance-Gründen die Variablen erst bei gebrauch deklarieren soll. Somit hat Groovemaster vollkommen recht.

    Weiterhin wird der Code durch die spätere Deklaration viel verständlicher. Warum soll ich mir Variablen anschauen, die wahrscheinlich nie zum Zug kommen, weil es z.B. vorher eine Abbruchbedingun gibt? Ist nur ein Beispiel.

    Auch sonst stimme ich mit groovemaster voll überein. 👍



  • Artchi schrieb:

    In jedem guten C++ Buch (dazu gehört auch das von Bjarne Stroustrup) steht drin, das man AUCH aus Performance-Gründen die Variablen erst bei gebrauch deklarieren soll.

    Jo klar, denn z. B. die ganzen Klassen muessen ja erst konstruiert werden.

    Warum soll ich etwas unnoetig konstruieren, wenn ich es noch oder gar nicht
    benoetige (z. b. wenn eine exception fliegt)?

    mfg
    v R



  • Kostet es Zeit Speicher auf den Stack zu legen?

    int main()
    {
        int a;
    }
    


  • Hehe, natürlich. Das ist doch ein Push-Befehl auf der CPU, bei einem einfachen Datentyp! Und weg nehmen kostet auch wieder ein Befehl. Das kann sich mächtig summieren.



  • ihr müsst euch mal hören aus performance gründen*vogel zeig*
    aus performance gründen wäre es sinnvoller alles beim start des programms anzulegen und nicht erst kurz bevor die funktion ausgeführt wird (kommt euch das bekannt vor?
    so werden nämlich alle großen programme geschrieben z.b. Winamp,Nero und sogar windows) nämlich so viel wie möglich am programmstart anlegen bedeutet zwar nen längeren startvorgang aber schnellere ausführungszeit

    @artchi schmeiß das buch weg würd ich sagen ist nämlich völliger blödsinn
    speicheranfordern ist unter allen höheren betriebssytemen ein zeitraubendes unterfangen als beispiel windows98 braucht über 20takte nur um anschließend sagen zu können der speicher kann jetzt benutzt werden danach kommen zuordnung des speichers eintrag das speicher belegt wurde und dann kann erst geschrieben werden macht also locker 40 takte bevor die funktion loslegen kann und da behauptet jemand aus performance gründen besser? aber für euch die blind sowas vertrauen hat ja c++ sein eigene intelligenz nämlich das der kompiler merkt das etwas irgendwo deklariert wird und deklariert(belegt den dafür benötigten speicher gleich am anfang beim programmstart) weis aber nicht aus dem kopf ob man dafür die optimierung aktivieren muss oder ob er das immer macht

    und @turing lese mal bitte meinen text und überfliege ihn nicht nur
    ich hatte nämlich auch geschrieben das man in der funktion selbst auch etwas deklarieren kann und das kann natürlich vorteile haben z.b. wenn die funktion sehr selten benutzt wird dann bringt es natürlich vorteile dies nicht am anfang zu deklarieren

    @artchi deinen letzten post versteh ich nicht erst sagts du aus performance gründen soll man es kurz vorher machen

    z.b. PSEUDOCODE

    int a
    int b
    int c

    a+b =c
    cout << c

    das sollte bei dir schneller sein als a b und c am programmstart zu deklarieren und nur
    die funktion aufzurufen
    dabei weist du ja das es zeit kostet



  • Skippy schrieb:

    ihr müsst euch mal hören aus performance gründen*vogel zeig*
    aus performance gründen wäre es sinnvoller alles beim start des programms anzulegen und nicht erst kurz bevor die funktion ausgeführt wird (kommt euch das bekannt vor?
    so werden nämlich alle großen programme geschrieben z.b. Winamp,Nero und sogar windows) nämlich so viel wie möglich am programmstart anlegen bedeutet zwar nen längeren startvorgang aber schnellere ausführungszeit

    Schwachsinn. Ich arbeite auch an einem groesseren Projekt und dort holt man
    sich speicher dann, wenn man ihn benoetigt und nicht vorher. Leute die meinen
    man muss den Ram unnoetig vollklatschen sind ein Grund, warum wir mehr und
    mehr Arbeitsspeicher benoetigen.

    @artchi schmeiß das buch weg würd ich sagen ist nämlich völliger blödsinn
    speicheranfordern ist unter allen höheren betriebssytemen ein zeitraubendes unterfangen als beispiel windows98 braucht über 20takte nur um anschließend sagen zu können der speicher kann jetzt benutzt werden danach kommen zuordnung des speichers eintrag das speicher belegt wurde und dann kann erst geschrieben werden macht also locker 40 takte bevor die funktion loslegen kann und da behauptet jemand aus performance gründen besser? aber für euch die blind sowas vertrauen hat ja c++ sein eigene intelligenz nämlich das der kompiler merkt das etwas irgendwo deklariert wird und deklariert(belegt den dafür benötigten speicher gleich am anfang beim programmstart) weis aber nicht aus dem kopf ob man dafür die optimierung aktivieren muss oder ob er das immer macht

    und @turing lese mal bitte meinen text und überfliege ihn nicht nur
    ich hatte nämlich auch geschrieben das man in der funktion selbst auch etwas deklarieren kann und das kann natürlich vorteile haben z.b. wenn die funktion sehr selten benutzt wird dann bringt es natürlich vorteile dies nicht am anfang zu deklarieren

    Ach jetzt ploetzlich bringen lokale Deklarationen also doch Vorteile, gerade
    eben war es noch besser den Speicher direkt bei Programm start zu besorgen.

    Was denn nun?

    @artchi deinen letzten post versteh ich nicht erst sagts du aus performance gründen soll man es kurz vorher machen

    z.b. PSEUDOCODE

    int a
    int b
    int c

    a+b =c
    cout << c

    das sollte bei dir schneller sein als a b und c am programmstart zu deklarieren und nur
    die funktion aufzurufen
    dabei weist du ja das es zeit kostet

    Wieso betrachtest du simple Datentypen? Betrachte mal komplexe Datentypen.
    Wieso sollen diese erstellt werden, wenn ich sie noch gar nicht benoetige?

    Jetzt willst du tausende Objekte erstellen, musst aber vorher noch jede Menge
    anderes Zeug erledigen. Du erstellst sie natuerlich bei Programmstart. Jetzt
    wird vorher aber eine Exception geschmissen und du kannst die Objekte gar nicht
    nutzen.

    Aber hauptsache wir haben den Speicher schonmal, der jetzt auch noch unnoetiger
    Weise aufgeraeumt werden muss.

    mfg
    v R



  • Skippy! Du hast überhaupt nichts verstanden, was ich gesagt habe. Und deine Verfahren "Alles bei Programmstart anlegen!" kann nicht wirklich funktionieren. Jedenfalls nicht, wenn man vernünftiges Programmdesign hat. Und von dieser ominösen Win98-Speicheranforderung die 20 Takte braucht... was soll der Mist? Variablen auf dem Stack werden nicht vom OS angefordert, der wird von der CPU gemacht, es wird einfach nur ein Stackregister (oder wie es auch immer auf einer bestimmten CPU funktioniert) incrementiert.

    Egal, wovon ist hier überhaupt die Rede? Zwei Beispiele:

    void foo(bool a) {
         int x, y;   // zwei pushs auf den Stack
         if(a)
            return;
         x++;
         y++;
    }
    
    void bar() {
        foo(true);
    }
    

    Das obige Bsp. verbraucht sinnlos zwei push-Befehle! Obwohl x und y nicht gebraucht werden.

    Die nachfolgende Version spart zwei pushs, weil völlig unnötig:

    void foo(bool a) {
         if(a)
            return;
         int x, y;   // zwei pushs auf den Stack
         x++;
         y++;
    }
    
    void bar() {
        foo(true);
    }
    

    So, man stelle sich jetzt mal vor, x und y wären nicht einfache ints, sondern Structs oder Klassen die noch einen ganzen Rattenschwanz an anderen Variablen haben. Das wären dann mehr als nur zwei pushs!!!

    Wer das immer noch nicht verstanden hat, kann so weiter machen wie er will. Ist mir auch letztendlich egal, was ihr in eurem Source macht. Hab besseres zu tun. 😃



  • Skippy ist ein TROLL oder hat KEINE AHNUNG.



  • Danke Leute ich habs jetzt woanders gefunden ihr konntet mir nich helfen



  • Skippy schrieb:

    erstens ist in c++ nirgends festgelegt das man alles erst eine zeile bevor man die variable braucht deklariert daraus folgt deine aussage ist schonmal falsch

    Da hast du was falsch verstanden. Ich habe weder eine Behauptung aufgestellt, noch eine Festlegung zitiert. Es war lediglich ein gut gemeinter Rat für sauberes Design. Sicherlich ist dieses nirgendwo definiert, viele gute C++ Programmierer halten sich aber an gewisse Richtlinien.

    Skippy schrieb:

    zweitens schau dich doch mal im netzt um (ich fasse es mal kurz zusammen)

    Da erzählst du uns nichts Neues. Schlechtes Design trifft man leider noch viel zu häufig an.

    Skippy schrieb:

    wenn es überall im programm gebraucht wird deklariert man das am anfang einer datei oder bei großen projekten mit vielen dateien kann man auch eine große header datei extra fürs deklarieren von variablen struct vectoren usw. anlegen

    Wenn man programmweit eine Instanz benötigt, dann wird sowas global realisiert. Das ist richtig. Ob das jetzt eine rohe globale Variable ist, ein Singleton oder was auch immer, ist erstmal egal. Fakt ist, dass ein gutes C++ Programm (auch grosse Projekte) mit sehr wenigen dieser globalen Instanzen auskommt. Die Probleme, die man nämlich sonst verursacht, können weitaus drastischer ausfallen, als ein paar Optimierungsarbeiten.

    Skippy schrieb:

    wenn etwas nur innerhalb einer funktion gebraucht wird wird es dort am anfang der funktion nicht irgendwo zwischendrin deklariert

    Gute Programmierer machen das aber so. Und dabei spielt nicht nur Laufzeit eine Rolle. In-place Deklaration hat noch andere Vorteile, zB lesbarerer Code oder weniger Abhängigkeiten. Wenn eine Variable zB für mehrere Sachen genutzt wird, so kann das schon mal Fehler kaschieren. Die fallen dir irgendwann auf die Füsse, nur nicht während der Testphase. Murphy lässt grüssen.

    Skippy schrieb:

    dies ist steht so in sämtlichen richtlinien und tutorial zu sauberen programmierstil

    Dir ist schon klar, dass wir im C++ Forum sind?

    Skippy schrieb:

    ausserdem wird es in firmen mit vielen entwicklern auch so verlangt Z.B. Simens

    Gutes Design ist leider nicht gesetztlich verankert. Da hast du vollkommen Recht.

    Skippy schrieb:

    da es nicht zuzumuten ist das ein entwickler eines teams z.b. deklaration eines chars im quelltext erst suchen muss

    Gute Programmierer verwenden gute IDE's. Ein Rechtsklick auf die Variable und "go to declaration" ausgewählt, und schon musst du nicht mehr suchen. 😉
    Wer nicht auf solche Annehmlichkeiten zurückgreifen kann, wird keinen Unterschied feststellen, ob er nun am Beginn einer Funktion nach der Deklaration suchen muss oder in der Nähe der betreffenden Codestelle.

    Skippy schrieb:

    ausserdem fördert dein ratschlag fehlerhaften code

    Sowas hat man nun von einer demokratischen Regierungsform. 🙄 Ich will dir deine Meinung auch nicht nehmen, mit meinen Ansichten deckt sich das jedoch nicht.

    Skippy schrieb:

    z.b.

    char1[255]
    char2[300]

    wenn du char2 in char1 kopieren willst fällt dir wenn beide untereinander sind sofort auf das char2 zu groß ist wenn man es aber wie du machst und zwischen beiden etliche zeilen code liegen fällt das nicht so schnell auf

    Du musst noch viel lernen, junger Padawan. Das müssen wir aber alle. Aber um nur mal ein Gegenargument zu deinem recht stark hinkendem Beispiel zu bringen, in C++ verwendet man bequeme Container.

    FireFlow schrieb:

    Kostet es Zeit Speicher auf den Stack zu legen?

    Artchi schrieb:

    Hehe, natürlich. Das ist doch ein Push-Befehl auf der CPU, bei einem einfachen Datentyp! Und weg nehmen kostet auch wieder ein Befehl. Das kann sich mächtig summieren.

    Hier muss ich noch eine Ergänzung zu Artchi's Beitrag machen. Diese push/pop Geschichten werden nur dann gemacht, wenn für Variablen direkt Register verwendet werden. Sollten nicht ausreichend Register zur Verfügung stehen oder der Speicher nicht in ein oder mehrere Register passen, wird Stack verwendet. Dazu wird am Beginn der Funktion der Stack-Pointer entsprechend angepasst und am Ende der Funktion wieder zurückgesetzt. Das braucht natürlich auch Zeit, aber nur wenige Takte. Praktisch nichts im Vergleich zu dynamischem Allokieren. Es spielt auch keine Rolle, ob du nur 10 int's oder ganze 1000 int's deklarierst.

    Skippy schrieb:

    speicheranfordern ist unter allen höheren betriebssytemen ein zeitraubendes unterfangen

    Je nach Speichermanager ist das durchaus mehr oder weniger korrekt. Das ist aber noch lange kein Grund, nur globale Variablen zu benutzen oder alle am Beginn der Funktion zu deklarieren. Optimierungsarbeiten kommen erst dann zum Zug, wenn dass Programm läuft. Und dann kann man immer noch die std::string Deklaration aus der millionenfach durchlaufenen Schleife rausziehen, so dass nicht immer von neuem Speicher reserviert und freigegeben wird. Programmierer mit gutem Weitblick machen sowas auch schon mal direkt bei der Implementierung.

    Matthias_2005 schrieb:

    Danke Leute ich habs jetzt woanders gefunden ihr konntet mir nich helfen

    Du hattest noch weitere Probleme? Dein ursprünglicher Fehler wurde doch bereits gefunden. 😕


Anmelden zum Antworten