Wettbewerb für C Anfänger: Aufgabe aus K&R Buch - Wer schreibt den besseren Code?



  • Ich hab nochmal dein Progamm geprüft.
    Der Fehler tritt grundsätzlich genau dann auf, wenn du innerhalb eines Tabblocks zuerst irgendein Zeichen, gefolgt von einem oder mehreren Leerzeichen und dann Tab eingibst.

    D.h. aus so etwas:

    AB*****\t\n
    
    macht dein Programm:
    AB*****\t\n
    
    Und das ist falsch.
    Richtig wäre:
    AB\n
    
    Und fall es:
    AB*****\tCDE\t\n
    heißt, dann müßte das da rauskommen:
    AB\tCDE\n
    

    Deswegen sag ich ja, so trivial wie man meint ist es nicht. 😉
    Das alles fehlerfrei zu berücksichtigen ist nicht trivial.



  • Mein Programm ist nicht ohne Grund so komlex geworden.
    Am Anfang war es auch ganz schlank und klein, bis ich auf die ganzen Spezialfälle stoß, die es zu berücksichtigen gilt.



  • Ich sehe gerade, dein Programm enthält noch einen weiteren Fehler, den gleichen wie mein Programm.

    Aus einem:

    *\t\n
    
    macht dein Programm ein:
    \t\n
    

    Das ist also ein Tab zuviel.
    Eine komplett leere Zeile wird also auch nicht berücksichtigt.



  • C Anfänger schrieb:

    Ich sehe gerade, dein Programm enthält noch einen weiteren Fehler, den gleichen wie mein Programm.

    Aus einem:

    *\t\n
    
    macht dein Programm ein:
    \t\n
    

    Das ist also ein Tab zuviel.
    Eine komplett leere Zeile wird also auch nicht berücksichtigt.

    EDIT

    Ok ganz gleich sind die Fehler nicht, deines macht einen Fehler mehr.
    Wenn man folgendes eingibt:

    \tA\t\n
    
    Dann macht dein Programm ein
    \tA\t\n
    draus, während meines immerhin den zweiten Tab entfernt.
    \tA\n
    


  • Im großen und ganzen, so weit ich das bis jetzt feststellen konnte und wie die Beispiele zeigen macht dein Programm also bei Spezialfällen insgesamt schon 3 Fehler.
    Meines liegt da nur bei einem Fehler.



  • Du bist vielleicht ein Troll... Von Spezialfällen hast du nicht erwähnt, die meisten angeblichen Fehler sind nicht vorhanden, mach die Augen auf.

    So wie du es geschrieben hast arbeitet meins fehlerfrei. Und wenn du nicht merkst, dass bei deinem oft nicht Leerzeichen ersetzt werden, dann kann man dir nicht helfen.

    PS: Das Forum hat eine Editfunktion.



  • Ich verstehe die Aufgabenstellung irgendwie nicht...

    Es sollen also eine gewisse Anzahl von folgenden Leerzeichen als Tab dargestellt werden. Außerdem sollen Leerzeichen und Tabs am Ende der Eingabe entfernt werden.

    Ist das alles?

    #include <stdio.h>
    
    #define TAB_SIZE 8
    
    int main()
    {
    	char ch;
    
    	printf("|\t|\t|\t|\t|\t\n");
    
    	while ((ch = getchar()) != EOF)
    	{
    		if (ch == ' ')
    		{
    			int counter = 1;
    			int tab = 0;
    
    			while ((ch = getchar()) == ' ' || ch == '\t')
    			{
    				if (ch == ' ')
    				{
    					++counter;
    				}
    				else if (ch == '\t')
    				{
    					counter += TAB_SIZE;
    				}
    
    				if (counter >= TAB_SIZE)
    				{
    					tab = counter / TAB_SIZE;;
    					break;
    				}
    			}
    
    			if (tab)
    			{
    				//int i;
    
    				//for (i = 0; i < tab; ++i)
    				{
    					putchar('\t');
    				}
    			}
    			else
    			{
    				int i;
    
    				if (ch != '\n')
    				{
    					for (i = 0; i < counter; ++i)
    					{
    						putchar('*');
    					}
    				}
    
    				putchar(ch);
    			}
    		}
    		else
    		{
    			putchar(ch);
    		}
    	}
    
    	return 0;
    }
    

    Ich könnte das Programm anbieten. Da mir aber nicht klar ist, was wirklich verlangt ist, kann ich es nicht wirklich testen.



  • HighLigerBiMBam schrieb:

    Du bist vielleicht ein Troll... Von Spezialfällen hast du nicht erwähnt, die meisten angeblichen Fehler sind nicht vorhanden, mach die Augen auf.

    Die Aufgabenstellung ist eindeutig. Dort steht nämlich ganz klar drin:
    "Sollte die Eingabe mit Leerzeichen oder Tabs enden, so sollte sie durch ein Newlinezeichen ersetzt werden."

    Außerdem kannst du dir mal deinen Ton sparen.

    So wie du es geschrieben hast arbeitet meins fehlerfrei.

    Nein, das tut es nicht.
    Es besteht ja nicht einmal die Testbeispiele korrekt.

    Und wenn du nicht merkst, dass bei deinem oft nicht Leerzeichen ersetzt werden, dann kann man dir nicht helfen.

    Es werden da Leerzeichen ersetzt, wo es machbar ist, also bis zum nächsten Tab.
    Vor dem Tab z.b. 3 Leerzeichen durch ein Tab ersetzen kann man nicht, da das Tab ja bis zum Ende springt und dann das Spacing nicht mehr stimmt.

    Es ist doch ganz klar, daß du die Aufgabenstellung überhaupt nicht verstanden hast.
    Anstatt an deinem Programm weiterzuarbeiten versuchst du hier jetzt dein Programm zu rechtfertigen und die Aufgabenstellung falsch zu interpretieren.

    PS: Das Forum hat eine Editfunktion.

    Die geht nicht für Gäste.



  • hhhh schrieb:

    Ich verstehe die Aufgabenstellung irgendwie nicht...

    Es sollen also eine gewisse Anzahl von folgenden Leerzeichen als Tab dargestellt werden. Außerdem sollen Leerzeichen und Tabs am Ende der Eingabe entfernt werden.

    ...
    Ich könnte das Programm anbieten. Da mir aber nicht klar ist, was wirklich verlangt ist, kann ich es nicht wirklich testen.

    Ich werde nachher noch etwas dazu schreiben. Ich muß jetzt aber noch schnell einkaufen gehen.



  • Also, da es hier wohl Mißverständnisse bezüglich der Aufgabenstellung gibt, werde ich diese nochmal etwas ausführlicher hinschreiben.

    Es soll eine Zeile eingegeben werden können und unter folgenden Bedingungen wieder ausgegeben werden.

    1. Grundsätzlich gilt, daß sichtbare Zeichen (z.b. A-Z, a-z usw.) bei der Ausgabe an den gleichen Position stehen müssen, wie bei der Eingabe.
    2. Endet der Satz auf Leerzeichen oder Tabs, so sind diese Tabs und Leerzeichen zu entfernen und durch ein \n Newline auszutauschen.
    3. Enthält der Satz vor oder zwischen den Wörtern Leerzeichen, dann sollen diese durch Tabs ersetzt werden, wenn dieses möglich ist. Zu beachten ist hierbei, daß Regel 1 dabei nicht verletzt werden darf.
    4. Besteht die eingegebene Zeile ausschließlich nur aus Leerzeichen und Tabs (kein Zeichen sichtbar!), dann darf nur ein \n Newline ausgegeben werden.
    5. Die Tablänge beträgt 8 Zeichen.

    Beispiele: (* entsprechen Leerzeichen, /t sind Tabs und /n ist ein Newline
    
    [B]Zu Regel 2:[/B]
    ABCD**\n
    wird zu:
    ABCD\n
    
    ABCD****\n
    wird zu:
    ABCD\n
    
    ABCD******\n
    wird zu
    ABCD\n
    
    ABCD********\n
    wird zu
    ABCD\n
    
    ABCD\t*\n
    wird zu
    ABCD\n
    
    ABCD**\t***\n
    wird zu 
    ABCD\n
    
    abcdefgh12345678*\t\n
    wird zu
    abcdefgh12345678\n
    
    [B]Zu Regel 3[/B]
    ABC**DE\n
    wird zu
    ABC**DE\n
    // Man beachte, ein Tab ist hier nicht möglich, weil dann DE bei Tab=8 Regel 1 verletzten würde.
    
    ABCD********EF\n
    wird zu:
    ABCD\t****EF\n
    // Man beachte, daß, obwohl hier 8 Leerzeichen eingegeben wurden ein nach D 
    eingegebenes Tab nur die nächsten 4 Leerzeichen ersetzen kann, weil danach der 
    Tabstopp kommt und die 4 Leerzeichen danach einzeln eingegeben werden müssen.
    
    ABCD************EF\n
    wird zu:
    ABCD\t\tEF\n
    
    ABCD*****EF\n
    wird zu:
    ABCD\t*EF
    
    AB***C**DE\n
    wird zu:
    AB***C\tDE\n
    // Vor D kommt ein TAB, weil die letzten 2 Leerzeichen vor dem Tabstopp kamen.
    
    AB**\tDE\n 
    wird zu:
    AB\tDE\n
    
    **ABCD\n
    wird zu:
    **ABCD\n
    
    ********ABCD\n
    wird zu:
    \tABCD\n
    
    *******ABCD\n
    wird zu:
    *******ABCD\n
    // Es sind nur 7 Leerzeichen, daß reicht nicht für ein Tab bis zum nächsten Tabstopp
    
    **\t*ABCD\n
    wird zu:
    \t*ABCD\n
    
    [B]Zu Regel 4[/B]
    *\t**\n
    wird zu:
    \n
    
    \t**\n
    wird zu:
    \n
    
    **\t\n
    wird zu:
    \n
    

    So, diese Beispiele sollten, so weit ich das beurteilen kann, die genannten Regeln abdecken, wobei ich hier keine Gewähr gebe.
    D.h. eventuell habe ich noch ein Eingabebeispiel übersehen, daß hier noch nicht bedacht wurde, aber sich aus den Regeln ergibt.
    Zu bedenken ist nämlich hier, daß kaum eines der Beispiele über mehr als 16 Zeichen hinausgeht. D.h. gibt man eine > 16 Zeichen lange Eingabe ein, dann sollte das Programm die genannten Regeln ebenfalls erfüllen können.
    Als ich mein Programm schrieb, fielen mir nämlich solche Fälle auch auf.
    Bei kurzen Eingaben war alles korrekt, aber bei langen Zeilen mußte ich dann nochmal nachbessern.

    Auch solltet ihr berücksichtigen, daß je nach Programmcode Fehler beim Bearbeiten der vorherigen Eingaben auf die Bearbeitung der späteren Eingaben auswirken könnten und sich die Fehler aufaddieren.
    Das war bei mir so. Ich mußte daher das Programm öfters komplett neu starten um
    einen resetteten Zustand zu haben.
    Außerdem ist ein Debugger sehr hilfreich.
    Insbesondere bei Regel 2, da man hier schnell einen ausgegebenen \t Tab der gleich vor dem \n Newline Zeichen noch folgt übersehen könnte.
    Notfalls kann man, an der Codestelle wo die Newlines ausgegeben werden, noch
    eine optionales anderes Zeichen vor dem Newline auf die klassische Debugging Methode zum Debuggen ausgeben. für den Wettbewerb sollte diese Ausgabe aber dann wenigstens ausgeschaltet sein.

    So, ich hoffe es ist nun für jeden klarer, das ist das was funktional am Ende rauskommen soll. Die Siegbedingungen bezügl. Geschwindigkeit, Eleganz usw. sind weitere Bedingungen und schon ausführlich im ersten Posting beschrieben.
    Und bei Unklarheiten fragt ihr besser vorher, bevor ihr euer Programm postet. Ich denke nämlich, daß das Streit spart.

    @ hhhh
    Dein Programm verletzt z.b. Regel 3, das müßtest du noch nachbessern.
    Beispiel:
    Diesist\n
    wird bei dir zu:
    Dies
    ist\n
    Da aber der Tabstop bis zum 8 Zeichen geht sollte es so etwas ergeben:
    Dies\t*ist\n

    Auf komplett leere Zeilen habe ich dein Programm noch nicht getestet.
    Das müßte ich mit dem Debugger machen und vielleicht willst du erstmal das Problem bezügl. Regel 3 beheben.



  • Lösungen zu K&R-Aufgaben gibt es bereits, solltest du wohl auch kennen:
    http://www.clc-wiki.net/wiki/K%26R2_solutions:Chapter_1:Exercise_21

    Ich biete mal was an, was die getline gleich mit ersetzt und strikt C89 ist:

    #include <stdio.h>
    
    #define TABSPACE 8
    
    int main()
    {
      int c=EOF-1, tnum=0;
      do if( c!=EOF-1 )
         {
           if( c==EOF || c=='\n' )
             {tnum?putchar('\n'):1;break;}
           else if( c==' '||c=='\t' )
             tnum+=c==' '?1:TABSPACE;
           else
           {
             while( tnum>=TABSPACE ) putchar('\t'),tnum-=TABSPACE;
             while( tnum ) putchar('*'),--tnum;
             putchar(c);
           }
         } while( c=getchar(),1 );
      return 0;
    }
    


  • Wutz schrieb:

    Lösungen zu K&R-Aufgaben gibt es bereits, solltest du wohl auch kennen:
    http://www.clc-wiki.net/wiki/K%26R2_solutions:Chapter_1:Exercise_21

    Richtig und die sind alle nach den Aufgabenstellungen falsch.
    Ich finde es unglaublich, wie so etwas ungeprüft auf die Seite kommen kann.

    Wäre die Diskussionsseite ohne Registrierung zugänglich, dann würde ich die Fehler der Programme alle aufzählen.

    Ich biete mal was an, was die getline gleich mit ersetzt und strikt C89 ist:

    Es hat schon einen Fehler.
    Gib mal folgendes ein:

    Es**\tist
    Dein Programm macht aus der Eingabe
    Es\t**ist
    
    richtig wäre:
    Es\tist
    


  • Und, habt ihr an eurem Code schon gearbeitet?



  • @wutz

    war in c89 switch verboten oder wieso machst da so ne if geschichte?

    @edit: bevor ichs vergess,, es gewinnt nicht wer den unleserlichsten code produziert... dafür gibts den IOCCC 😉



  • C Anfänger schrieb:

    Es**\tist
    Dein Programm macht aus der Eingabe
    Es\t**ist
    
    richtig wäre:
    Es\tist
    

    Nach welcher Regel? Das verletzt Regel 1 (so wie du sie verstehst).



  • Michael E. schrieb:

    C Anfänger schrieb:

    Es**\tist
    Dein Programm macht aus der Eingabe
    Es\t**ist
    
    richtig wäre:
    Es\tist
    

    Nach welcher Regel? Das verletzt Regel 1 (so wie du sie verstehst).

    Nein, das tut es nicht. Gerade dein Progamm verletzt Regel 1.
    Denn wenn das Tab 8 Zeichen weit ist, dann fängt das i erst wieder an Position 9 an (wir zählen von 1 aus).
    D.h. ob du vor dem 9. Zeichen 2 Leerzeichen und ein Tab setzt, mit dem dann i ja zu Position 9 springt, oder die 2 Leerzeichen entfernst und dann mit dem Tab für i zu Position 9 springst macht keinen unterschied.
    i Bleibt an Position 9, so wie es sein sollte und die Regel 1 wird erfüllt.

    Bei deinem Programm ist es genau umgekehrt.
    Nach Es springst du mit dem Tab auf Position 9 und dann gibst du noch 2 Leerzeichen aus, womit i zwangsläufig auf Position 11 landet.

    Dein Code ist also falsch.



  • _-- schrieb:

    @wutz

    war in c89 switch verboten oder wieso machst da so ne if geschichte?

    Beachte die Aufgabenstellung: kein Switch!

    Grund steht in der Aufgabenstellung.



  • Hast Recht, wenn man die Regeln so wie du interpretiert. Aber es ist nicht mein Code.



  • Michael E. schrieb:

    Hast Recht, wenn man die Regeln so wie du interpretiert.

    Da gibt's nichts zu interpretieren, jetzt sind die Regeln ja wohl eindeutig ausformuliert.

    Die Tabsize ist 8, d.h. jeder Tab wird zwangsläufig immer bis zum nächsten Tabsttopspringen, der in 8 er Schritten von Position 1 aus verläuft.

    [/QUOTE]
    Aber es ist nicht mein Code.[/quote]
    Ja, hast Recht. Es ist Wutzs Code.



  • wer hat eigentlich die competition gewonnen 😕 oder wars wutz weil sonst keine teilnehmer hat?


Anmelden zum Antworten