Zeichenkettenarithmetik



  • Hallo schönen guten Abend, Ich habe hier ein einfaches Programm, welches einen
    Text auf ein array einliest und es sind dann unterschiedliche Aufgaben gestellt... In diesem Teil habe Ich versucht den Text, nachdem er auf einem
    array abgespeichert wurde Wort für Wort auszugeben, indem Ich eine Schleife
    konstruiert habe die 'eigenlich' so dachte Ich Zeichen für Zeichen ausgeben soll und immer dann eine Pause machen soll wenn das Ende eines Wortes erreicht ist. ----> lasst euch nicht von der geschachtelten inneren for-Schleife verwirren , Ich hatte auf Linux trotz Angabe der Bibliothek vom compiler eine Fehlermeldung, bei dem Versuch

    system(pause);
    

    zu verwenden. Also habe Ich das Problem, dass der Rechner, doch bitte nach dem Ausgeben eines jeden Wortes, kurz warten soll so gelöst. Es funktioniert auch :
    bis auf ein Problem. Meine Bedingte Anweisung in Zeile 45 mit

    if (c== ' ' || c == '\n' || c == '\t')
    

    führt nicht dazu das der Compiler zwischen den Worten anhält , ? , er hält nur einmal bei der Ausgabe an, also gibt den Text in Zwei Teilen aus... unten ist das von mir verfasste Programm.

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    // Aufgabenteil g)
    main(){
    char text[]="Ein Herr faellt vom Stuhl (Erich Kaestner) Es ist bekannt, dass 
    Menschen, die im Sitzen einschlafen, vornueber sinken. Immer tiefer und tiefer. 
    Wenn die Koerpernerven, die trotz des Schlafens munter bleiben, spueren, dass 
    sich das Schwergewicht allzu sehr vom Stuhl entfernt, geben sie dem Kopf einen 
    Ruck. 012345Er fliegt nach rueckwaerts, und das sogenannte Einnicken kann 
    wieder von vorne beginnen. Wenn die Nerven aber den richtigen Augenblick 
    versaeumen, purzelt der Schlaefer vom Stuhl.Alfredo Torres, einem braven 
    Buerger von Buenos Aires, erging es so. Er schlief ein und fiel vom Stuhl. 
    Waere ihm das zu Hause passiert, haette es niemand weiter erfahren, und die 
    Oeffentlichkeit wuesste heute noch kein Wort ueber den Fall.Nun passierte die 
    Sache aber leider Herrn Torres nicht zu Hause, sondern im Theater. Die 
    Stuhlreihen waren schmal.Und nun interessiert sich eine ganze Stadt fuer die 
    Angelegenheit. Herr Torres hat naemlich die Rechnung, die der Arzt sandte, 
    keineswegs bezahlt, sondern dem Dramatiker geschickt, der an dem Malheur die 
    Schuld traegt. Denn - argumentiert der Rechtsanwalt des Verletzten - waere das 
    Theaterstueck amuesanter gewesen, waere Herr Torres nicht eingeschlafen. Waere 
    er nicht eingeschlafen, waere er nicht vom Stuehlchen gefallen. Waere er nicht 
    vom Stuehlchen gefallen, haette er sich nicht wehgetan. Also: er verletzte 
    sich, weil das Stueck schlecht war. Der Fall liegt eigentlich klar. Aber nur 
    fuer Herrn Torres und seinen Rechtsanwalt. Der Stueckeschreiber und dessen 
    Rechtsanwalt sind natuerlich ganz anderer Ansicht. Da waehrend der Auffuehrung 
    - wenn sie auch schlecht war - von zweitausend Besuchern nur ein einziger vom 
    Stuhl fiel, scheint dieser Fall doch wohl mehr auf Kosten dieses Besuchers, als 
    auf die des Stueckes gesetzt werden zu duerfen. Immerhin ist der Prozess noch 
    im Gange. Wir wollen hoffen, dass Herr Torres mit seiner Klage abgewiesen wird. 
    Denn wo kaemen wir hin, wenn es den Autoren so erschwert wuerde, langweilige 
    Dramen auffuehren zu lassen?";
    
    char wortspeicher[30];  
    int i,c,anz_zeichen,j,pausenvariable,stopphelfer;
    int pausenzeit;
    anz_zeichen=strlen(text);
    
    for (i=0;i<anz_zeichen;i++)
    	{
    	  		printf("%c",text[i]);
    			c=text[i];
    			if (c== ' ' || c == '\n' || c == '\t'){
    			for (pausenvariable=0;pausenvariable<=1000;pausenvariable++)
    			{
    			for (stopphelfer=0;stopphelfer<=1000;stopphelfer++)
    			pausenzeit=pausenvariable*stopphelfer;
    			}
    			}	
    
    	}
    }
    

    Weiss jemand woran es liegen könnte ? Habe es nicht lösen können...
    MFG


  • Mod

    Was sollen die inneren Schleifen machen? Ein wenig warten? Das machen die bestimmt nicht. Nimm so etwas wie

    #include <unistd.h>
    
    // ...
    if (c== ' ' || c == '\n' || c == '\t')
      sleep(1);
    

    Unterscheide auch klar, was der Compiler ist und was nicht. Der Compiler ist ein Programm, das deinen Quelltext in Maschinencode übersetzt. Der führt dein Programm nicht Schritt für Schritt aus wie ein Interpreter.



  • Danke für den Hinweis, (Ich werde mir den Befehl merken) aber dadurch hat sich jetzt nur die Wartezeit geändert. Der Text wird in zwei Teilen ausgegeben . Durch den von dir vorgeschlagenen Befehl hält der Compiler nur länger an... Er sollte ja durch if (c== ' ' ||.... nach jedem Wort anhalten, das macht er nicht?

    (Wer das Programm ausprobieren will, sollte die Zeilenumbrüche aus dem Beispieltext
    wieder entfernen, wenn er es in den Editor eingibt. Habe beim posten diese
    eingefügt damit der Text von Html nicht in einer Zeile ausgegeben wird...)



  • es muss theoretisch daran liegen, dass er die Bedingte Anweisung nicht so interpretiert wie geplant

    if (c== ' ' || c == '\n' || c == '\t')
    

    er scheint das " ' ' " nicht als Leerstelle zu interpretieren... ?



  • Du solltest vor den Pausen den Ausgabepuffer leeren, damit die bisher aufgelaufenen auszugebenden Daten auch wirklich ausgegeben werden:

    fflush(stdout);
    

    Das passiert bei Konsolenausgaben normalerweise nach jeder Zeile automatisch, aber dein langer Text enthält anscheinend keine Zeichenumbrüche, so dass das nicht anschlägt.



  • richtig, die Zeilenumbrueche hatte Ich vorher entfernen müssen



  • Volltreffer es hat funktioniert!!!!

    for (i=0;i<anz_zeichen;i++)
    	{
    	  		printf("%c",text[i]);
    			c=text[i];
    			fflush(stdout);	
    			if (c== ' ' || c == '\n' || c == '\t'){
    			for (pausenvariable=0;pausenvariable<=1000;pausenvariable++)
    			{
    			for (stopphelfer=0;stopphelfer<=1000;stopphelfer++)
    			pausenzeit=pausenvariable*stopphelfer;
    			}
    			}	
    
    	}
    

    Warum es genau Zeile 5 ist weiss Ich noch nicht ? War in diesem Fall Glück
    beim ersten Versuch
    Danke für eure Hinweise !



  • Beeindruckend wie schnell ein 64 Bit Rechner die Schleifen hochzählt,
    Selbst wenn man die Zählköpfe der for Schleifen auf 5000 setzt und
    dem Rechner zwischen jedem Wort aufträgt einen Zahlenkörper von dieser
    Größe durchzukalkulieren ----ohne Ausgabe---- dauert es doch immer nur Sekundenbruchteile



  • softpad schrieb:

    Beeindruckend wie schnell ein 64 Bit Rechner die Schleifen hochzählt,
    Selbst wenn man die Zählköpfe der for Schleifen auf 5000 setzt und
    dem Rechner zwischen jedem Wort aufträgt einen Zahlenkörper von dieser
    Größe durchzukalkulieren ----ohne Ausgabe---- dauert es doch immer nur Sekundenbruchteile

    Können die Schleifen nicht eh optimiert werden zu:

    pausenvariable = 1000;
    stopphelfer = 1000;
    pausenzeit = 1000 * 1000;
    

    ?


  • Mod

    softpad schrieb:

    Beeindruckend wie schnell ein 64 Bit Rechner die Schleifen hochzählt,
    Selbst wenn man die Zählköpfe der for Schleifen auf 5000 setzt und
    dem Rechner zwischen jedem Wort aufträgt einen Zahlenkörper von dieser
    Größe durchzukalkulieren ----ohne Ausgabe---- dauert es doch immer nur Sekundenbruchteile

    Das ist einfach totaler Unsinn, so eine Zeitschleife zu programmieren. Erstens zählt ein Computer sowieso ungeheuer schnell, wenn er sonst nichts tut; zweitens wird die Schleife wahrscheinlich sowieso vollständig wegoptimiert, da sie einfach nichts tut; drittens ist busy-waiting schlechter Stil; viertens passt das nicht mehr, wenn dein Rechner schneller oder langsamer wird. Wenn du zeitabhängiges Programmverhalten möchtest dann nimm auch Funktionen die von der Zeit abhängen.



  • Wenn du den Compiler optimieren lässt, merkt der sogar, dass da nichts passiert und optimiert das weg -> keine Pause.
    Darum ja das sleep.

    pause ist auch ein Befehl von Windows.
    Der wartet auf einen Tastendruck. Also auch etwas anderes als eine bestimmte Zeit warten.
    Mit getchar kannst du das auch erreichen.

    Es reicht auch, das fflush im if-Zweig zu machen (und nicht nach jedem Zeichen).

    Schau dir mal isspace aus ctype.h an.



  • Falls man mal echt aktiv warten will, bei mir hat sich immer

    for(...)
       cout<<"";//ups, ist ja C, denke printf("") geht auch.
    

    bewährt, da hat sich noch kein Optimierer rangetraut.

    Und indem ich meinen Trick hier poste, riskiere ich, daß in der nächsten Compiler-Version jemand genau das wegoptimiert. 🤡

    Dann muss ich nachlegen mit Chaos-Berechnungen, wie

    global double x=LaufzeitzufallZwischen(-2,+2);
    

    und je

    for(int i=0;i<wartezeit;++i)
       x=x*x-2;//Ich liebe diese Folge! Sie bleibt brav zwischen -2 und +2 
       //eingesperrt. Sie ist fehlerverstärkend, chaotisch. Und doch soo einfach. 
       //Übrigens ein Beispiel für einen Zufallszahlengenerator, der 
       //zwar langfristig total nicht vorhersagbar ist, wie das Wetter in Tübingen, 
       //der aber kurzfristig so unirdisch schlecht ist, daß man weinen müßte. 
       //Schon im zweidimenionalen Phasenraum ist er nicht im Mindesten irgendwie 
       //gleichverteilt, sondern zeichnet eine scharfe Parabel mit nochtmal einem 
       //leisen Halo drumherum.
    

    Wobei ich dann x auf jeden Fall bei Programmende auf den Bildschirm bringen muss! Tue ich es nicht, kann der Compiler alle meine Zeitschleifen wegoptimieren.
    Es reicht ja,

    if(x==0.2)
       cout<<"(Diese Zeile bitte ignorieren, sie ist nur dazu da, den "
          "Compiler zu ver*****en.)\n";//kommt praktisch nie vor, vielleicht einmal 
          //in 2^40 Läufen oder so.
    


  • volkard schrieb:

    Und indem ich meinen Trick hier poste, riskiere ich, daß in der nächsten Compiler-Version jemand genau das wegoptimiert. 🤡

    Aufrufe externer Bibliotheksfunktionen (bin jetzt zu faul den exakten Wortlaut nachzuschlagen, you get the idea...) gehören zum beobachtbaren Verhalten.

    Dann muss ich nachlegen mit Chaos-Berechnungen, wie

    global double x=LaufzeitzufallZwischen(-2,+2);
    

    Wenn da volatile statt global steht, gehört das auch zum beobachtbaren Verhalten. Insbesondere darf der Compiler nichtmal bei

    volatile int x;
    x = 0;
    x = 0;
    

    eine einzige Zuweisung wegschmeißen.

    (Nicht dass ich das je zum Warten benutzen würde.)


  • Mod

    Bashar schrieb:

    volkard schrieb:

    Und indem ich meinen Trick hier poste, riskiere ich, daß in der nächsten Compiler-Version jemand genau das wegoptimiert. 🤡

    Aufrufe externer Bibliotheksfunktionen (bin jetzt zu faul den exakten Wortlaut nachzuschlagen, you get the idea...) gehören zum beobachtbaren Verhalten.

    Wenn die Implementierung aber beweisen kann, was diese Bibliotheksfunktion macht (weil sie die Standardbibliothek kennt und auch erkennt, dass du gegen diese linkst*), dann ist die Optimierung wieder erlaubt. Es wird nämlich nirgendwo explizit die von dir beschriebene Klausel verlangt, sondern sie ist lediglich indirekt eine Folge davon dass eine unbekannte, externe Funktion Nebeneffekte haben könnte.

    Das erlaubt überhaupt erst Optimierungen der Standardbibliotheksfunktionen, wie printf("%s\n", foo); zu puts(foo); und ähnliches, die durchaus durchgeführt werden. Oder sqrt(2) zu 1.41421356237 und viele andere mehr. Sehr wichtige Optimierungsmöglichkeit.

    *: Beim GCC läuft dieser "Beweis" des Linkens gegen die Standardbibliothek beispielsweise so, dass du nicht die built-in Funktionen abgeschaltet hast. Auf diese Weise kann schon der Compiler die Optimierung durchführen.



  • Das hier ist der Satz, allerdings aus dem C++-Standard, den ich anscheinend meinte.

    The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and calls to library I/O functions.

    In C gibt es das, wie so oft, nicht so klar ausgedrückt.



  • Bashar schrieb:

    volkard schrieb:

    Und indem ich meinen Trick hier poste, riskiere ich, daß in der nächsten Compiler-Version jemand genau das wegoptimiert. 🤡

    Aufrufe externer Bibliotheksfunktionen (bin jetzt zu faul den exakten Wortlaut nachzuschlagen, you get the idea...) gehören zum beobachtbaren Verhalten.

    klar gottete ich die idea. Was extern ist, ist extern. Fertig.

    Aber std::-Sachen nenne ich nicht "externe Bibliotheksfunktionen"! War da nicht der MSVC6.1 so schlau, std::swap je nach Typ auf einen Dreieckstausch oder auf einen asm XCHG zu legen, während ein händisch geschriebenes swap mit genau dem selben Sourcecode IMMER zu einem Dreieckstausch wurde?

    Ich hoffe, der Standard verspricht, daß cout<<"" nix tut. Falls er es nicht verspricht, ist das doch eine Lücke.


  • Mod

    Bashar schrieb:

    The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and calls to library I/O functions.

    In C gibt es das, wie so oft, nicht so klar ausgedrückt.

    Auch in C++ bedeutet das nicht, dass jeder istream::operator<< unoptimierbar ist. Der Call an die Library I/O Funktion ist der letztlich daraus resultierende OS-Call (z.B. read/write unter Linux). Davor darf da gerne optimiert werden wie der Compiler lustig ist.



  • Ok Ich hab's schon verstanden! werde natürlich in Zukunft die von
    dir vorgeschlagen Funktion sleep verwenden. sleep(1) hatte Ich auch ausprobiert.. es wartet allerdings eine Minute zwischen den Worten... das man
    so eine Schleife nicht beim echten Programmieren als Wartezeit benutzt ist mir
    klar! Ich werde mir die Arbeitsweise von sleep genauer anschauen... und es in dem Programm ersetzen ... Danke für eure Tips!


  • Mod

    softpad schrieb:

    Ok Ich hab's schon verstanden! werde natürlich in Zukunft die von
    dir vorgeschlagen Funktion sleep verwenden. sleep(1) hatte Ich auch ausprobiert.. es wartet allerdings eine Minute zwischen den Worten... das man
    so eine Schleife nicht beim echten Programmieren als Wartezeit benutzt ist mir
    klar! Ich werde mir die Arbeitsweise von sleep genauer anschauen... und es in dem Programm ersetzen ... Danke für eure Tips!

    sleep ist halt keine portable Funktion und kann je nach Plattform was anderes machen (bei Linux wartet es z.B. Sekunden, bei Windows in Millisekunden), aber ein sleep, das in Minuten wartet ist mir neu. Gibt bestimmt auch andere Funktionen dieser Art auf der Plattform (unter Linux gibt es z.B. usleep, wenn man weniger als 1 Sekunde warten möchte).



  • Jepp, Danke für den Hinweis!


Anmelden zum Antworten