C Code Indenter


12

Situation: Sie sind Gymnasiallehrer und bringen Ihrer Computerklasse das Schreiben von C-Programmen bei. Da dies jedoch erst der Anfang des Semesters ist, haben Sie ihnen nicht die Bedeutung von Einrückungen und Abständen beigebracht. Während Sie ihre Arbeit markieren, schmerzen Ihre Augen so sehr, dass Sie vor Qual schreien und feststellen, dass dies nicht weitergehen kann.

Aufgabe: Sie haben sich entschieden, ein Programm in einer beliebigen Sprache zu schreiben, das einen gültigen C-Quellcode als Eingabe und Ausgabe verwendet, der gut formatiert ist. Sie sollten entscheiden, was ein gut formatierter Code ist, da es sich um einen Beliebtheitswettbewerb handelt. Es wird empfohlen, so viele Funktionen wie möglich zu implementieren. Nachfolgend einige Beispiele:

  • Fügen Sie vor jeder Zeile die richtige Einrückung hinzu
  • Fügen Sie Leerzeichen nach ,und andere Operatoren hinzu, z . B. Konvertieren int a[]={1,2,3};nach int a[] = {1, 2, 3};. Denken Sie jedoch daran, Operatoren nicht innerhalb von String-Literalen zu verarbeiten.
  • Entfernen Sie nach jeder Zeile nachfolgende Leerzeichen
  • Wenn Sie Anweisungen in mehrere Zeilen aufteilen, z. B. kann der Schüler tmp=a;a=b;b=tmp;oder int f(int n){if(n==1||n==2)return 1;else return f(n-1)+f(n-2);}alle in einer Zeile schreiben , können Sie sie in verschiedene Zeilen aufteilen. Achten Sie jedoch auf forSchleifen, in denen Semikolons enthalten sind, aber ich glaube nicht, dass Sie sie aufteilen sollten.
  • Fügen Sie nach dem Definieren jeder Funktion eine neue Zeile hinzu
  • Weitere Funktionen, mit denen Sie die Codes Ihrer Schüler nachvollziehen können.

Gewinnkriterien: Dies ist ein Beliebtheitswettbewerb, daher gewinnt die Antwort mit den meisten positiven Stimmen. Bei einem Unentschieden gewinnt die Antwort mit den meisten implementierten Funktionen. Wenn dies erneut ein Gleichstand ist, gewinnt der kürzeste Code.

Es wird empfohlen, in Ihre Antwort eine Liste der von Ihnen implementierten Funktionen sowie eine Beispieleingabe und -ausgabe aufzunehmen.

Bearbeiten: Wie in den Kommentaren angefordert, handelt es sich hier um eine Beispieleingabe. Beachten Sie jedoch, dass dies nur als Referenz dient. Es wird empfohlen, so viele Funktionen wie möglich zu implementieren.

Eingang:

#include <stdio.h>
#include<string.h>
int main() {
int i;
char s[99];
     printf("----------------------\n;;What is your name?;;\n----------------------\n"); //Semicolon added in the string just to annoy you
             /* Now we take the input: */
    scanf("%s",s);
    for(i=0;i<strlen(s);i++){if(s[i]>='a'&&s[i]<='z'){
        s[i]-=('a'-'A'); //this is same as s[i]=s[i]-'a'+'A'
}}printf("Your name in upper case is:\n%s\n",s);
   return 0;}

So würde ich diesen Code normalerweise formatieren: (Ich bin eine faule Person)

#include <stdio.h>
#include <string.h>
int main() {
    int i;
    char s[99];
    printf("----------------------\n;;What is your name?;;\n----------------------\n"); //Semicolon added in the string just to annoy you
    /* Now we take the input: */
    scanf("%s",s);
    for(i=0;i<strlen(s);i++) {
        if(s[i]>='a'&&s[i]<='z') {
            s[i]-=('a'-'A'); //this is same as s[i]=s[i]-'a'+'A'
        }
    }
    printf("Your name in upper case is:\n%s\n",s);
    return 0;
}

Das ist meiner Meinung nach leichter zu lesen:

#include <stdio.h>
#include <string.h>
int main() {
    int i;
    char s[99];
    printf("----------------------\n;;What is your name?;;\n----------------------\n"); //Semicolon added in the string just to annoy you
    /* Now we take the input: */
    scanf("%s", s);
    for(i = 0; i < strlen(s); i++) {
        if(s[i] >= 'a' && s[i] <= 'z') {
            s[i] -= ('a' - 'A'); //this is same as s[i]=s[i]-'a'+'A'
        }
    }
    printf("Your name in upper case is:\n%s\n", s);
    return 0;
}




Da ich nun Antworten habe, wird die Antwort mit der höchsten Stimmenzahl 5 Tage nach der letzten Antwort akzeptiert. Wenn also innerhalb von 5 Tagen keine neuen Antworten mehr vorliegen, endet dieser Wettbewerb.


2
Irgendwelche Gründe für die Abwahlen?
user12205

1
Ich könnte alle unnötigen Leerzeichen entfernen ( s/\s+/ /) und es einen Tag nennen
Ratschenfreak

1
@ratchet Freak könnte man, aber ich glaube nicht, dass dies eine Antwort mit vielen positiven Stimmen wäre.
user12205

1
@Quincunx danke für die Einrichtung des Kopfgeldes. Ich dachte meine Frage wäre beschissen.
user12205

1
@ CousinCocaine: Dies ist ein Beliebtheitskontext. Sie sind nicht dazu gedacht, das Problem auf elegante oder übliche Weise zu lösen. Sie wurden entwickelt, um das Problem auf die coolste Art und Weise zu lösen, die Sie sich vorstellen können.
SztupY

Antworten:


21

Da es sich um Einrückungen und Leerzeichen handelt, müssen wir den Code nur in einer Programmiersprache schreiben, die eigentlich auf Leerzeichen ausgelegt ist , da dies am einfachsten sein muss, oder?

Die Lösung lautet also:




















































































































































































































































































































































































































































Hier ist es in base64:

ICAgCQogICAgCgkJICAgIAkgCiAgICAKCQkgICAgCQkKICAgIAoJCSAgICAJICAKICAgIAoJCSAgICAJIAkKICAgIAoJCSAKIAogCQoKICAgCSAKICAgCQoJCQkgICAJCQkgCQkKCSAgCQoJICAJICAKICAgCQoJCQkgICAJIAkgCgkgIAkKCSAgCSAJCiAgIAkKCQkJICAgCSAgCQoJICAJCgkgIAkgCQogICAJCgkJCSAgIAkgICAgIAoJICAJCgkgIAkgCQogICAJCgkJCSAgIAkJCQkJIAkKCSAgCQoJICAJCSAKICAgCQoJCQkgICAJICAgCSAKCSAgCQoJICAJICAgIAogICAJCgkJCSAgIAkgCSAgIAoJICAJCgkgIAkgICAJCQogICAJCgkJCSAgIAkgCSAgCQoJICAJCgkgIAkgIAkgIAogICAJIAogICAJCgkJIAogCSAJCQkKICAgCQoJCQkJCiAgCgkKCiAgIAkgIAogICAJCgkJCQkKICAKCQoKICAgCSAJCgoJCgogICAJCSAKICAgCQkKICAgCQkKCQkJICAgCQoJICAJCQkgICAgCSAKICAgCQoJCSAKIAkgCQkJCiAgIAkKCQkJCQogIAoJCgogICAJICAgIAogICAJIAogICAJIAoJCSAKIAkgCQkJCiAgIAkKCQkJCQogIAoJCgogICAJICAgCQkKICAgCSAJCiAgIAkgCQoJCQkgICAJCgkgICAJCSAgICAJIAogICAJCgkJIAogCSAJCQkKICAgCQoJCQkJCiAgCgkKCiAgIAkgIAkgIAogICAJIAkKICAgCSAJCgkJCSAgIAkKCSAgCQkJICAgIAkgCiAgIAkKCQkgCiAJIAkJCQogICAJCgkJCQkKICAKCQoKICAgCQkKICAgCQoJCQkgICAJIAkgCgkgIAkKCSAgCQkgIAogICAJCgkJCSAgIAkJCQkgCQkKCSAgCQoJICAJCSAJCiAgIAkKCQkJICAgCQkJCQkgCQoJICAJCgkgIAkJCSAKICAgCQoJCQkgICAJCQkgCQkKCSAgCQoJICAJCQkJCiAgIAkKCQkJICAgCSAgIAkgCgkgIAkKCSAgCQkgCQkKICAgCQoJCQkgICAJIAkgCSAKCSAgCQoJICAJCQkgIAogICAJCgkJCSAgIAkgCQkJCQoJICAJCgkgIAkJCSAJCiAgIAkKCQkJICAgCSAJICAgCgkgIAkKCSAgCSAgCSAJCiAgIAkKCQkJICAgCSAJICAJCgkgIAkKCSAgCSAgCQkgCiAgIAkKCQkJCQogIAoJCgogICAJCSAgCiAgIAkgCiAgICAKCQkgCgkKCiAgIAkJIAkKICAgCQoJCQkJCiAgICAgCSAKICAgIAoJCSAgICAJCQogICAJCQoJCQkgICAJCgkgICAJCSAKCQoKICAgCQkJIAogICAJCQogICAJCQoJCQkgICAJCgkgIAkJCSAKIAkgCQkJCiAgIAkKCQkJCQogICAgIAkgCiAgICAKCQkgCgkKCiAgIAkJCQkKICAgCQoJCQkJCiAgICAgCSAJCgkJCQoJICAJIAkgCgoJCgogICAJICAJCQkKICAgCSAKICAgIAoJCSAKCQoKICAgCQkgCQkKICAgCQoJCQkJCiAgICAgCSAKICAgCSAKCQkgCgkKCiAgIAkJCSAgCiAgIAkgIAoJCQkgICAJIAkJCQkKCSAgCQoJICAJCQkJIAogICAJCgkJCQkKICAKCQoKICAgCQkJIAkKICAgCSAgCgkJCSAgIAkgCQkJCQoJICAJCgkgIAkJCQkJCiAgIAkKCQkJCQogIAoJCgogICAJCQkJIAogICAJCgkJCQkKICAgICAJIAogICAJCQoJCSAKCQoKICAgCQkJCQkKICAgCQoJCQkJCiAgICAgCSAKICAgCSAgCgkJIAoJCgogICAJICAJIAkKICAgCSAJCiAgIAkgCQoJCQkgICAJCgkgICAJCSAgICAJCgkJCQkKICAKCQoKICAgCSAgCQkgCiAgIAkgCQogICAJIAkKCQkJICAgCQoJICAJCQkgICAgCQoJCQkJCiAgCgkKCiAgIAkJCQogICAJIAkgCgkKICAgICAJCQoJCQkKICAgCSAgCQogCiAKCSAgCSAgIAogCiAKCQkgCSAgIAogICAJICAgICAKCQogICAgIAkgICAgIAoJCiAgICAgCQoJICAJCiAKIAkgIAkKCiAgIAkgICAKCgkKCiAgIAkgCSAJCiAgIAkKCQkJICAgCSAJIAoJICAJCgkgIAkJICAgCiAgIAkKCQkJICAgCSAgIAkgCgkgIAkKCSAgCQkgIAkKICAgCQoJCQkJCiAgCgkKCiAgIAkJICAgCiAgIAkgCiAgICAKCQkgCgkKCiAgIAkJICAJCiAgIAkgIAoJCQkgICAJIAkJCSAgCgkgIAkKCSAgCQkgCSAKICAgCSAKICAgCQoJCSAgICAJCgkJCQkKICAKCQoKICAgCQkgCSAKICAgCQoJCQkJCiAgCgkKCiAgIAkgCQkgCiAgIAkKCQkJICAgCSAJCQkJCgkgIAkKCSAgCSAgICAgCiAgIAkKCQkJCQogIAoJCgogICAJICAgICAKICAgCSAgCgkJCSAgIAkgCSAJIAoJICAJCgkgIAkgICAgCQogICAJCgkJCQkKICAKCQoKICAgCSAgICAJCiAgIAkKCQkJCQogICAgIAkgCiAgIAkKCQkgCgkKCiAgIAkgCQkJCiAgIAkKCQkJICAgCSAJIAoJICAJCgkgIAkgICAJIAogICAJCgkJCQkKICAKCQoKICAgCSAgIAkgCiAgIAkgCiAgICAKCQkgCgkKCiAgIAkKICAgCSAgCiAgIAkKCQkJCQkgICAgCQoJCgkgICAgCSAKCQkJCgkgIAkgCSAKICAgCSAKCQkJICAgCQoJICAJCgkgIAkgICAJCiAgIAkgCgkJCSAgIAkgCgkgIAkKCSAgCSAgCSAKICAgCSAKCQkJICAgCQkKCSAgCQoJICAJICAJCQogICAJIAoJCQkgICAJICAKCSAgCQoJICAJIAkgIAoKICAgCSAgIAkKCiAJIAkJCgogCiAJIAkJCgogICAJIAkgCgogCSAJIAoKIAogCSAJCQoKICAgCSAgCSAKCiAJIAkgCSAJCgogCiAJIAkJCgogICAJICAJCQoKIAkgCSAJCSAKCiAKIAkgCQkKCiAgIAkgCSAgCgogCSAJIAkJCQoKICAgCSAJCQoKIAogCQoKCgo=

Für diejenigen, die Probleme haben, den Code auf Papier auszudrucken, ist hier die kommentierte Version (einen Compiler finden Sie am Ende der Antwort):

# heap structure:
# 1: read buffer
# 2: parser state
#   0: before indentation
#   1: after indentation
#   2: inside a string literal
#   3: inside a multiline comment
#   4: inside a single line comment
# 3: identation
# 4: old read buffer
# 5: parenthesis nesting amount

# -------------------
# initialize heap
# -------------------
SS 1 | SS 0 | TTS # [1] := 0
SS 2 | SS 0 | TTS # [2] := 0
SS 3 | SS 0 | TTS # [3] := 0
SS 4 | SS 0 | TTS # [4] := 0
SS 5 | SS 0 | TTS # [5] := 0
LSL 1 # goto L1

# -------------------
# sub: determine what to do in state 0
# -------------------
LSS 2 # LABEL L2
SS 1 | TTT | SS  59 | TSST | LTS 4 # if [1] == ; GOTO L4
SS 1 | TTT | SS  10 | TSST | LTS 5 # if [1] == \n GOTO L5
SS 1 | TTT | SS   9 | TSST | LTS 5 # if [1] == \t GOTO L5
SS 1 | TTT | SS  32 | TSST | LTS 5 # if [1] == ' ' GOTO L5
SS 1 | TTT | SS 125 | TSST | LTS 6 # if [1] == } GOTO L6
SS 1 | TTT | SS  34 | TSST | LTS 16 # if [1] == " GOTO L16
SS 1 | TTT | SS  40 | TSST | LTS 35 # if [1] == ( GOTO L35
SS 1 | TTT | SS  41 | TSST | LTS 36 # if [1] == ) GOTO L36

SS 2 | SS 1 | TTS # [2] := 1
LST 7 # call L7
SS 1 | TTT | TLSS # print [1]
LTL # return

LSS 4 # label L4 - ; handler
SS 1 | TTT | TLSS # print [1]
LTL # return

LSS 5 # label L5 - WS handler
LTL # return

LSS 6 # label L6 - } handler
# decrease identation by one
SS 3 | SS 3 | TTT | SS 1 | TSST | TTS # [3] := [3] - 1
SS 2 | SS 1 | TTS # [2] := 1
LST 7 # call L7
SS 1 | TTT | TLSS # print [1]
LTL # return

LSS 16 # label L16 - " handler
SS2 | SS 2 | TTS # [2] := 2
LST 7 # call L7
SS1 | TTT | TLSS # print [1]
LTL

LSS 35
SS 5 | SS 5 | TTT | SS 1 | TSSS | TTS # [5] := [5] + 1
SS 2 | SS 1 | TTS # [2] := 1
LST 7 # call L7
SS1 | TTT | TLSS # print [1]
LTL

LSS 36
SS 5 | SS 5 | TTT | SS 1 | TSST | TTS # [5] := [5] - 1
SS 2 | SS 1 | TTS # [2] := 1
LST 7 # call L7
SS1 | TTT | TLSS # print [1]
LTL

# -------------------
# sub: determine what to do in state 1
# -------------------
LSS 3 # LABEL L3
SS 1 | TTT | SS  10 | TSST | LTS 12 # if [1] == \n GOTO L12
SS 1 | TTT | SS 123 | TSST | LTS 13 # if [1] == { GOTO L13
SS 1 | TTT | SS 125 | TSST | LTS 14 # if [1] == } GOTO L14
SS 1 | TTT | SS  59 | TSST | LTS 15 # if [1] == ; GOTO L15
SS 1 | TTT | SS  34 | TSST | LTS 27 # if [1] == " GOTO L27
SS 1 | TTT | SS  42 | TSST | LTS 28 # if [1] == * GOTO L28
SS 1 | TTT | SS  47 | TSST | LTS 29 # if [1] == / GOTO L29
SS 1 | TTT | SS  40 | TSST | LTS 37 # if [1] == ( GOTO L37
SS 1 | TTT | SS  41 | TSST | LTS 38 # if [1] == ) GOTO L38
SS 1 | TTT | TLSS # print [1]
LTL # return

LSS 12 # LABEL L12 - \n handler
SS 2 | SS 0 | TTS # [2] := 0
LTL # return

LSS 13 # LABEL L13 - { handler
SS 1 | TTT | TLSS # print [1]
SS 2 | SS 0 | TTS # [2] := 0
SS 3 | SS 3 | TTT | SS 1 | TSSS | TTS # [3] := [3] + 1
LTL # return

LSS 14 # LABEL L14 - } handler
SS 3 | SS 3 | TTT | SS 1 | TSST | TTS # [3] := [3] - 1
LST 7 # call L7
SS 1 | TTT | TLSS # print [1]
SS 2 | SS 0 | TTS # [2] := 0
LTL # return

LSS 15 # LABEL L15 - ; handler
SS 1 | TTT | TLSS # print [1]
SS 5 | TTT | LTS 10 # if [5] == 0 GOTO L39
LTL

LSS 39
SS 2 | SS 0 | TTS # [2] := 0
LTL # return

LSS 27 # label L27 - " handler
SS1 | TTT | TLSS # print [1]
SS2 | SS 2 | TTS # [2] := 2
LTL

LSS 28 # label L28 - * handler - this might start a comment
SS 4 | TTT | SS  47 | TSST | LTS 30 # if [4] == / GOTO L30
SS1 | TTT | TLSS # print [1]
LTL

LSS 29 # label L29 - / handler - this might start a comment
SS 4 | TTT | SS  47 | TSST | LTS 31 # if [4] == / GOTO L31
SS1 | TTT | TLSS # print [1]
LTL

LSS 30 # label L30 - /* handler
SS1 | TTT | TLSS # print [1]
SS2 | SS 3 | TTS # [2] := 3
LTL

LSS 31 # label L31 - // handler
SS1 | TTT | TLSS # print [1]
SS2 | SS 4 | TTS # [2] := 4
LTL

LSS 37
SS 5 | SS 5 | TTT | SS 1 | TSSS | TTS # [5] := [5] + 1
SS1 | TTT | TLSS # print [1]
LTL

LSS 38
SS 5 | SS 5 | TTT | SS 1 | TSST | TTS # [5] := [5] - 1
SS1 | TTT | TLSS # print [1]
LTL

# -------------------
# sub: print identation
# -------------------
LSS 7 # label L7 - print identation
SS 10 | TLSS # print \n
SS 3 | TTT # push [3]
LSS 9 # label L9 - start loop
SLS | LTS 8 # if [3] == 0 GOTO L8
SLS | LTT 8 # if [3] < 0 GOTO L8 - for safety
SS 32 | TLSS # print ' '
SS 32 | TLSS # print ' '
SS 1  | TSST # i := i - 1
LSL 9 # GOTO L9
LSS 8 # label L8 - end loop
LTL #

# -------------------
# sub: L21 - string literal handler
# -------------------
LSS 21
SS 1 | TTT | SS  10 | TSST | LTS 24 # if [1] == \n GOTO L24
SS 1 | TTT | SS  34 | TSST | LTS 25 # if [1] == " GOTO L25
SS 1 | TTT | TLSS # print [1]
LTL

LSS 24 # \n handler - this should never happen, but let's be prepared and reset the parser
SS 2 | SS 0 | TTS # [2] := 0
LTL # return

LSS 25 # " handler - this might be escaped, so be prepared
SS 4 | TTT | SS  92 | TSST | LTS 26 # if [4] == \ GOTO L26
SS 2 | SS 1 | TTS # [2] := 1
SS 1 | TTT | TLSS # print [1]
LTL

LSS 26 # \\" handler - escaped quotes don't finish the literal
SS 1 | TTT | TLSS # print [1]
LTL

# -------------------
# sub: L22 - multiline comment handler
# -------------------
LSS 22
SS 1 | TTT | SS  47 | TSST | LTS 32 # if [1] == / GOTO L32
SS 1 | TTT | TLSS # print [1]
LTL

LSS 32
SS 4 | TTT | SS  42 | TSST | LTS 33 # if [4] == * GOTO L33
SS 1 | TTT | TLSS # print [1]
LTL

LSS 33
SS 1 | TTT | TLSS # print [1]
SS 2 | SS 1 | TTS # [2] := 1
LTL
# -------------------
# sub: L23 - singleline comment handler
# -------------------
LSS 23
SS 1 | TTT | SS  10 | TSST | LTS 34 # if [1] == \n GOTO L34
SS 1 | TTT | TLSS # print [1]
LTL

LSS 34
SS 2 | SS 0 | TTS # [2] := 0
LTL

# -------------------
# main loop
# -------------------
LSS 1 # LABEL L1
SS 4 | SS 1 | TTT | TTS # [4] := [1]
SS 1 | TLTS # [1] := read

SS 2 | TTT | LTS 10 # if [2] == 0 GOTO L10
SS 2 | TTT | SS 1 | TSST | LTS 17 # if [2] == 1 GOTO L17
SS 2 | TTT | SS 2 | TSST | LTS 18 # if [2] == 2 GOTO L18
SS 2 | TTT | SS 3 | TSST | LTS 19 # if [2] == 3 GOTO L19
SS 2 | TTT | SS 4 | TSST | LTS 20 # if [2] == 4 GOTO L20

LSS 17
LST 3  # call L3
LSL 11 # GOTO L11

LSS 10 # label L10
LST 2  # call L2
LSL 11

LSS 18
LST 21
LSL 11

LSS 19
LST 22
LSL 11

LSS 20
LST 23

LSS 11 # label L11
LSL 1  # goto L1
LLL # END

Dies ist noch in Arbeit, obwohl es hoffentlich die meisten Kriterien erfüllen sollte!

Derzeit unterstützte Funktionen:

  • Beheben Sie die Identifikation anhand der Zeichen {und }.
  • Füge danach eine neue Zeile hinzu ;
  • Einrückungszeichen in String-Literalen behandeln (einschließlich der Tatsache, dass String-Literale nicht geschlossen werden, wenn auf ein gestoßen wird \")
  • Behandeln Sie Einrückungszeichen in ein- und mehrzeiligen Kommentaren
  • fügt keine Zeilenumbrüche hinzu, wenn diese in Klammern stehen (wie ein forBlock)

Beispieleingabe (Ich habe einige Randfälle hinzugefügt, die auf dem Kommentar von Quincunx basieren, damit Sie überprüfen können, ob es sich richtig verhält):

    /* Hai Worldz. This code is to prevent formatting: if(this_code_is_touched){,then+your*program_"doesn't({work)}correctl"y.} */
#include<stdio.h>
#include<string.h>
int main() {
int i;
char s[99];
     printf("----------------------\n;;What is your name?;;\n----------------------\n\""); //Semicolon added in the {;} string just to annoy you
             /* Now we take the {;} input: */
    scanf("%s",s);
    for(i=0;i<strlen(s);i++){if(s[i]>='a'&&s[i]<='z'){
        s[i]-=('a'-'A'); //this is same as s[i]=s[i]-'a'+'A'
}}printf("Your \"name\" in upper case is:\n%s\n",s);
   return 0;}

Beispielausgabe:

[~/projects/indent]$ cat example.c | ./wspace indent.ws 2>/dev/null

/* Hai Worldz. This code is to prevent formatting: if(this_code_is_touched){,then+your*program_"doesn't({work)}correctl"y.} */
#include<stdio.h>
#include<string.h>
int main() {
  int i;;
  char s[99];;
  printf("----------------------\n;;What is your name?;;\n----------------------\n\"");; //Semicolon added in the {;} string just to annoy you
  /* Now we take the {;} input: */
  scanf("%s",s);;
  for(i=0;i<strlen(s);i++){
    if(s[i]>='a'&&s[i]<='z'){
      s[i]-=('a'-'A');; //this is same as s[i]=s[i]-'a'+'A'
    }
  }
  printf("Your \"name\" in upper case is:\n%s\n",s);;
  return 0;;
}

Beachten Sie, dass der Interpreter eine Ausnahme auslöst, die wir unterdrücken müssen, da Whitespace die EOF-Prüfung nicht unterstützt. Da es im Whitespace keine Möglichkeit gibt, nach EOF zu suchen (soweit ich weiß, dass dies mein erstes Whitespace-Programm ist), ist dies etwas Unvermeidbares. Ich hoffe, dass die Lösung weiterhin zählt.

Dies ist das Skript, mit dem ich die mit Anmerkungen versehene Version in einen korrekten Leerraum kompiliert habe:

#!/usr/bin/env ruby
ARGF.each_line do |line|
  data = line.gsub(/'.'/) { |match| match[1].ord }
  data = data.gsub(/[^-LST0-9#]/,'').split('#').first
  if data
    data.tr!('LST',"\n \t")
    data.gsub!(/[-0-9]+/){|m| "#{m.to_i<0?"\t":" "}#{m.to_i.abs.to_s(2).tr('01'," \t")}\n" }
    print data
  end
end

Laufen:

./wscompiler.rb annotated.ws > indent.ws

Beachten Sie, dass dies, abgesehen von der Konvertierung der Zeichen S, Lund T, auch einzeilige Kommentare mit zulässt #und automatisch Zahlen und einfache Zeichenliterale in ihre Leerraumdarstellung konvertieren kann. Wenn Sie möchten, können Sie es auch für andere Whitespace-Projekte verwenden


Nicht schlecht! :) aber es wäre schöner, wenn es eine for-Schleife nicht in drei Zeilen aufteilen würde (zumindest meiner Meinung nach ... die Entscheidung liegt immer noch bei den Wählern). Zur Erinnerung, die for-Schleife in C hat die Syntaxfor(i=0;i<10;i++)
user12205

2
@ace: Da Whitespace nicht gerade eine Hochsprache ist, ist das Hinzufügen solcher Ausnahmen nicht so einfach. Das heißt, ich versuche immer noch, die beiden Probleme mit Kommentaren und Literalen zu beheben, und versuche auch, die Schleifen zu beheben (ich denke, das Ignorieren von ;inside (/ )blocks würde ausreichen). Ich denke, diese sollten ausreichen, um die Lösung als "brauchbar" zu betrachten.
SztupY

1
@ace: Ich glaube, ich habe die Ausnahmen hinzugefügt, so dass der generierte Code nun ordnungsgemäß eingerückt zu sein scheint. Das Beispiel wurde zu Ihrem Beispiel geändert
SztupY

9

Vim der einfache Weg, technisch nur mit einem Zeichen:=

Ich bin kein Vim-Guru, aber ich unterschätze niemals seine Macht und manche betrachten es als Programmiersprache. Für mich ist diese Lösung sowieso ein Gewinner.

Öffne die Datei in vim:

vim file.c

Drücken Sie innerhalb von vim die folgenden Tasten

gg=G

Erläuterung:

gg geht an den Anfang der Datei

= ist ein Befehl zum Beheben der Einrückung

G Weist ihn an, den Vorgang bis zum Ende der Datei auszuführen.

Sie können mit speichern und beenden :wq

Es ist möglich, den vimBefehl von der Befehlszeile aus ausführen zu lassen , dies kann also auch in einem Einzeiler erfolgen, aber das überlasse ich Leuten, die es vimbesser wissen als ich.


Vim Beispiel eine gültige Eingabedatei (fibonacci.c) mit falschem Einzug.

/* Fibonacci Series c language */
#include<stdio.h>

int main()
{
int n, first = 0, second = 1, next, c;

            printf("Enter the number of terms\n");
scanf("%d",&n);
  printf("First %d terms of Fibonacci series are :-\n",n);

          for ( c = 0 ; c < n ; c++ )
   {
if ( c <= 1 )
         next = c;
 else
                                     {
next = first +    second;
              first = second;
        second = next;
      }
      printf("%d\n",next);
   }
 return 0;
}

In vim öffnen: vim fibonacci.cdrückengg=G

/* Fibonacci Series c language */
#include<stdio.h>

int main()
{
  int n, first = 0, second = 1, next, c;

  printf("Enter the number of terms\n");
  scanf("%d",&n);
  printf("First %d terms of Fibonacci series are :-\n",n);

  for ( c = 0 ; c < n ; c++ )
  {
    if ( c <= 1 )
      next = c;
    else
    {
      next = first +    second;
      first = second;
      second = next;
    }
    printf("%d\n",next);
  }
  return 0;
}


Dies kann auf gekürzt werden =GZZ. (Vim golf ftw!)
Türklinke

7

Da dies verwendet wird, um dem Lehrer zu helfen, den Code des Schülers besser zu verstehen, ist es wichtig, die Eingabe zuerst zu bereinigen. Pre-Prozessor-Direktiven sind nicht erforderlich, da sie nur Unordnung verursachen und Makros auch schädlichen Code in die Datei einschleusen können. Das wollen wir nicht! Es ist auch völlig unnötig, die ursprünglichen Kommentare des Schülers beizubehalten, da sie wahrscheinlich sowieso völlig unbrauchbar sind.

Stattdessen, da jeder weiß, dass guter Code gute Kommentare benötigt, abgesehen von der Korrektur der Einrückung und der Struktur, sollten Sie einige äußerst nützliche Kommentare um die Hauptpunkte des Codes hinzufügen, um das Ergebnis noch verständlicher zu machen! Dies wird dem Lehrer definitiv dabei helfen, die geleistete Arbeit des Schülers einzuschätzen!

Also daraus:

    /* Hai Worldz. This code is to prevent formatting: if(this_code_is_touched){,then+your*program_"doesn't({work)}correctl"y.} */
#include<stdio.h>
#include<string.h>
int main() {
int i;
char s[99];
     printf("----------------------\n;;What is your name?;;\n----------------------\n\""); //Semicolon added in the {;} string just to annoy you
             /* Now we take the {;} input: */
    scanf("%s",s);
    for(i=0;i<strlen(s);i++){if(s[i]>='a'&&s[i]<='z'){
        s[i]-=('a'-'A'); //this is same as s[i]=s[i]-'a'+'A'
}}printf("Your \"name\" in upper case is:\n%s\n",s);
   return 0;}

Lassen Sie uns das produzieren:

int main() {
    /* This will declare i. */
    int i;
    /* This will declare s[99]. */
    char s[99];
    /* This will call the function called printf with 1 parameters */
    printf("----------------------\n;;What is your name?;;\n----------------------\n\"");
    /* This will call the function called scanf with 2 parameters */
    scanf("%s", s);
    /* This will start a for loop, with initializator i = 0. It will loop until i < strlen(s), and will i++ at each iteration */
    for (i = 0; i < strlen(s); i++) {
        /* This will check, whether s[i] >= 'a' && s[i] <= 'z' is true or not. */
        if (s[i] >= 'a' && s[i] <= 'z') {
            s[i] -= 'a' - 'A';
        }
    }
    /* This will call the function called printf with 2 parameters */
    printf("Your \"name\" in upper case is:\n%s\n", s);
    /* This will return from the function. */
    return 0;
}

Ist es nicht viel besser mit all den nützlichen Kommentaren rund um die Ausdrücke?


Das ist also eine Rubinlösung , die den castEdelstein verwendet, der ein C-Parser ist (Ja, ich betrüge) . Dadurch wird der Code analysiert und neu gedruckt. Dies bedeutet, dass das Ergebnis perfekt eingerückt und auch konsistent ist. Beispiel:

  • Richtige Einrückung im gesamten Code basierend auf der Blockebene
  • Konsistente Leerzeichen um Ausdrücke, Anweisungen, Bedingungen usw.
  • Vollständige Neueinrückung basierend auf der Struktur des Codes
  • etc.

Außerdem enthält es nützliche Kommentare zur Funktionsweise des Codes, die sowohl für die Schüler als auch für die Lehrer sehr nützlich sind!

indent.rb

#!/usr/bin/env ruby
require 'cast'

code = ''
ARGF.each_line do |line|
  if line=~/\A#/
    code << "// #{line.strip}\n"
  else
    code << line
  end
end

class Comment < C::Literal
  field :val
  initializer :val
  def to_s
    "/* #{val} */"
  end
end

tree = C.parse(code)
tree.preorder do |n|
  break if n.kind_of?(Comment)
  if n.kind_of?(C::Declaration)
    dd = []
    n.declarators.each do |d|
      dd << "declare #{d.indirect_type ? d.indirect_type.to_s(d.name) : d.name}"
      dd.last << " and set it to #{d.init}" if d.init
    end
    unless dd.empty?
      n.insert_prev(Comment.new("This will #{dd.join(", ")}."))
    end
  end rescue nil
  n.parent.insert_prev(Comment.new("This will call the function called #{n.expr} with #{n.args.length} parameters")) if n.kind_of?(C::Call) rescue nil
  n.insert_prev(Comment.new("This will start a for loop, with initializator #{n.init}. It will loop until #{n.cond}, and will #{n.iter} at each iteration")) if n.kind_of?(C::For) rescue nil
  n.insert_prev(Comment.new("This will check, whether #{n.cond} is true or not.")) if n.kind_of?(C::If) rescue nil
  n.insert_prev(Comment.new("This will return from the function.")) if n.kind_of?(C::Return) rescue nil
end

puts tree

Gemfile

source "http://rubygems.org"
gem 'cast', '0.2.1'

3
+1 fürit is completely unnecessary to retain the original comments the student wrote, as they are probably completely useless anyway
SeinopSys

Diese Kommentare sind für mich nicht aussagekräftig. Sie führen Unordnung ein, weil sie einfach die folgende Zeile wiederholen.
Justin

@ Quincunx Ich glaube, Sie haben den Sarkasmus-Tag verpasst. Dies ist ein Beliebtheitswettbewerb.
SztupY

5

Bash, 35 Zeichen

Die Eingabedatei muss den Namen "input.c" haben und im aktuellen Arbeitsverzeichnis abgelegt sein.

sh <(wget -q -O- http://x.co/3snpk)

Beispielausgabe, nachdem die Eingabe in der ursprünglichen Frage eingegeben wurde: http://i.imgur.com/JEI8wa9.png

Je nach Hardware kann es einige Sekunden dauern, bis das Programm ausgeführt wird. Seien Sie also geduldig :)


Sie wissen, dass dies kein Code-Golf ist, oder?
Justin

1
+1 zum Herunterladen und Kompilieren von AStyle im Handumdrehen Oo Würdest du AStyle nicht einfach dort lassen, um es dem Benutzer zu erleichtern? Also das entfernen rm?
Tomsmeding

Da dies kein Code-Golf ist, halte ich es für besser, nur den Inhalt Ihres Pastebins hier abzulegen, da ich bei einem kurzen Blick nicht einmal bemerkte, dass Sie den Code tatsächlich mit einem externen Befehl richtig formatieren
SztupY

@ Quincunx: Es soll eine Art Troll-Antwort sein: P
Riot

@ Tomsmeding: Ich möchte nicht, dass mein Code Nebenwirkungen hat, wie beispielsweise, dass der Speicherplatz des Benutzers unerwartet belegt wird ...
Riot

3

Rubin

code = DATA.read

# first, we need to replace strings and comments with tilde escapes to avoid parsing them
code.gsub! '~', '~T'
lineComments = []
code.gsub!(/\/\/.*$/) { lineComments.push $&; '~L' }
multilineComments = []
code.gsub!(/\/\*.*?\*\//m) { multilineComments.push $&; '~M' }
strs = []
code.gsub!(/"(\\.|[^"])*"|'.'/) { strs.push $&; '~S' } # character literals are considered strings

# also, chop out preprocessor stuffs
preprocessor = ''
code.gsub!(/(^#.*\n)+/) { preprocessor = $&; '' }

# clean up newlines and excess whitespace
code.gsub! "\n", ' '
code.gsub! /\s+/, ' '
code.gsub!(/[;{}]/) { "#{$&}\n" }
code.gsub!(/[}]/) { "\n#{$&}" }
code.gsub! /^\s*/, ''
code.gsub! /\s+$/, ''

# fix for loops (with semicolons)
code.gsub!(/^for.*\n.*\n.*/) { $&.gsub ";\n", '; ' }

# now it's time for indenting; add indent according to {}
indentedCode = ''
code.each_line { |l|
    indentedCode += ('    ' * [indentedCode.count('{') - indentedCode.count('}') - (l =~ /^\}/ ? 1 : 0), 0].max) + l
}
code = indentedCode

# finally we're adding whitespace for more readability. first get a list of all operators
opsWithEq = '= + - * / % ! > < & | ^ >> <<'
opsNoEq = '++ -- && ||'
ops = opsWithEq.split + opsWithEq.split.map{|o| o + '=' } + opsNoEq.split
ops = ops.sort_by(&:length).reverse
# now whitespace-ize them
code.gsub!(/(.)(#{ops.map{|o| Regexp.escape o }.join '|'})(.)/m) { "#{$1 == ' ' ? ' ' : ($1 + ' ')}#{$2}#{$3 == ' ' ? ' ' : (' ' + $3)}" }

# special-cases: only add whitespace to the right
ops = ','.split
code.gsub!(/(#{ops.map{|o| Regexp.escape o }.join '|'})(.)/m) { "#{$1}#{$2 == ' ' ? ' ' : (' ' + $2)}" }
# special-cases: only add whitespace to the left
ops = '{'.split
code.gsub!(/(.)(#{ops.map{|o| Regexp.escape o }.join '|'})/m) { "#{$1 == ' ' ? ' ' : ($1 + ' ')}#{$2}" }

# replace the tilde escapes and preprocessor stuffs
stri = lci = mci = -1
code.gsub!(/~(.)/) {
    case $1
    when 'T'
        '~'
    when 'S'
        strs[stri += 1]
    when 'L'
        lineComments[lci += 1] + "\n#{code[0, $~.begin(0)].split("\n").last}"
    when 'M'
        multilineComments[mci += 1]
    end
}
code = (preprocessor + "\n" + code).gsub /^ +\n/, ''

puts code
__END__
    /* Hai Worldz. This code is to prevent formatting: if(this_code_is_touched){,then+your*program_"doesn't({work)}correctl"y.} */
#include<stdio.h>
#include<string.h>
int main() {
int i;
char s[99];
     printf("----------------------\n;;What is your name?;;\n----------------------\n\""); //Semicolon added in the {;} string just to annoy you
             /* Now we take the {;} input: */
    scanf("%s",s);
    for(i=0;i<strlen(s);i++){if(s[i]>='a'&&s[i]<='z'){
        s[i]-=('a'-'A'); //this is same as s[i]=s[i]-'a'+'A'
}}printf("Your \"name\" in upper case is:\n%s\n",s);
   return 0;}

Ausgabe:

#include <stdio.h>
#include<string.h>

int main() {
    int i;
    char s[99];
    printf("----------------------\n;;What is your name?;;\n----------------------\n");
    //Semicolon added in the string just to annoy you
     /* Now we take the input: */ scanf("%s", s);
    for(i = 0; i < strlen(s); i ++ ) {
        if(s[i] >= 'a' && s[i] <= 'z') {
            s[i] -= ('a' - 'A');
            //this is same as s[i]=s[i]-'a'+'A'
        }
    }
    printf("Your name in upper case is:\n%s\n", s);
    return 0;
}

Ausgabe für @ SztupYs Edge Case-Eingabe:

#include<stdio.h>
#include<string.h>

/* Hai Worldz. This code is to prevent formatting: if(this_code_is_touched){,then+your*program_"doesn't({work)}correctl"y.} */ int main() {
    int i;
    char s[99];
    printf("----------------------\n;;What is your name?;;\n----------------------\n\"");
    //Semicolon added in the {;} string just to annoy you
     /* Now we take the {;} input: */ scanf("%s", s);
    for(i = 0; i < strlen(s); i ++ ) {
        if(s[i] >= 'a' && s[i] <= 'z') {
            s[i] -= ('a' - 'A');
            //this is same as s[i]=s[i]-'a'+'A'
        }
    }
    printf("Your \"name\" in upper case is:\n%s\n", s);
    return 0;
}

Bisherige Features:

  • [x] Fügen Sie vor jeder Zeile die richtige Einrückung hinzu
  • [x]Fügen Sie Leerzeichen nach ,und andere Operatoren hinzu, z . B. Konvertieren int a[]={1,2,3};nach int a[] = {1, 2, 3};. Denken Sie jedoch daran, Operatoren nicht innerhalb von String-Literalen zu verarbeiten.
  • [x] Entfernen Sie nach jeder Zeile nachfolgende Leerzeichen
  • [x]Wenn Sie Anweisungen in mehrere Zeilen aufteilen, z. B. kann der Schüler tmp=a;a=b;b=tmp;oder int f(int n){if(n==1||n==2)return 1;else return f(n-1)+f(n-2);}alle in einer Zeile schreiben , können Sie sie in verschiedene Zeilen aufteilen. Achten Sie jedoch auf forSchleifen, in denen Semikolons enthalten sind, aber ich glaube nicht, dass Sie sie aufteilen sollten.
  • [ ] Fügen Sie nach dem Definieren jeder Funktion eine neue Zeile hinzu
  • [ ] Weitere Funktionen, mit denen Sie die Codes Ihrer Schüler nachvollziehen können.

3

Dies ist in Python geschrieben und basiert auf den GNU Coding Standards.

Bisherige Features:

  • Blöcke einrücken
  • Linien teilen (kann Dinge teilen, die nicht sein sollten)
  • Funktionsdefinitionen im GNU-Stil

Code:

import sys

file_in = sys.argv[1]

# Functions, for, if, while, and switch statements
def func_def(string):
    ret = ["", "", ""]
    func_name = ""
    paren_level = -1
    consume_id = False

    for x in string[::-1]:
        if x == "{":
            ret[2] = "{"
        elif ret[1] == "":
            if x == "(":
                paren_level -= 1
                func_name += x
            elif x == ")":
                paren_level += 1
                func_name += x
            elif paren_level == -1 and x.isspace():
                if consume_id:
                    ret[1] = func_name[::-1]
            elif paren_level == -1:
                consume_id = True
                func_name += x
            else:
                func_name += x
        else:
            # Return Type
            ret[0] += x
    else:
        ret[1] = func_name[::-1]

    ret[0] = ret[0][::-1]

    # Handle the case in which this is just a statement
    if ret[1].split("(")[0].strip() in ["for", "if", "while", "switch"]:
        ret = [ret[1], ret[2]] # Don't print an extra line

    return ret

with open(file_in) as file_obj_in:
    line_len = 0
    buffer = ""
    in_str = False
    no_newline = False
    indent_level = 0
    tab = " " * 4
    no_tab = False
    brace_stack = [-1]

    while True:
        buffer += file_obj_in.read(1)
        if buffer == "":
            break
        elif "\n" in buffer:
            if not no_newline:
                print(("" if no_tab else indent_level * tab) + buffer, end="")
                buffer = ""
                line_len = indent_level * 4
                no_tab = False
                continue
            else:
                buffer = ""
                line_len = indent_level * 4
                no_newline = False
                continue
        elif buffer[-1] == '"':
            in_str = not in_str
        elif buffer.isspace():
            buffer = ""
            continue

        if "){" in "".join(buffer.split()) and not in_str:
            for x in func_def(buffer):
                print(indent_level * tab + x)
            buffer = ""
            line_len = indent_level * 4
            no_newline = True
            indent_level += 1
            brace_stack[0] += 1
            brace_stack.append((brace_stack[0], True))
            continue
        elif buffer[-1] == "}" and not in_str:
            brace_stack[0] -= 1
            if brace_stack[-1][1]: # If we must print newline and indent
                if not buffer == "}":
                    print(indent_level * tab + buffer[:-1].rstrip("\n"))
                indent_level -= 1
                print(indent_level * tab + "}")
                buffer = ""
                line_len = indent_level * 4
            else:
                pass
            brace_stack.pop()
        line_len += 1

        if line_len == 79 and not in_str:
            print(indent_level * tab + buffer)
            buffer = ""
            line_len = indent_level * 4
            continue
        elif line_len == 78 and in_str:
            print(indent_level * tab + buffer + "\\")
            buffer = ""
            line_len = indent_level * 4
            no_tab = True
            continue

Beispieleingabe (Dateiname als Argument übergeben):

#include <stdio.h>
#include<string.h>
int main() {
int i;
char s[99];
     printf("----------------------\n;;What is your name?;;\n----------------------\n"); //Semicolon added in the string just to annoy you
             /* Now we take the input: */
    scanf("%s",s);
    for(i=0;i<strlen(s);i++){if(s[i]>='a'&&s[i]<='z'){
        s[i]-=('a'-'A'); //this is same as s[i]=s[i]-'a'+'A'
}}printf("Your name in upper case is:\n%s\n",s);
   return 0;}

Beispielausgabe:

#include <stdio.h>
#include<string.h>
int
main()
{
    int i;
    char s[99];
    printf("----------------------\n;;What is your name?;;\n------------------\
----\n"); //Semicolon added in the string just to annoy you
    /* Now we take the input: */
    scanf("%s",s);
    for(i=0;i<strlen(s);i++)
    {
        if(s[i]>='a'&&s[i]<='z')
        {
            s[i]-=('a'-'A'); //this is same as s[i]=s[i]-'a'+'A'
        }
    }
    printf("Your name in upper case is:\n%s\n",s);
    return 0;
}

Dies wird Fehler haben.


0

.Netz

Öffnen Sie diese Datei mit Visual Studio

Eingang:

#include<stdio.h>
#include<string.h>
int main() {
int i;
char s[99];
     printf("----------------------\n;;What is your name?;;\n----------------------\n\""); //Semicolon added in the {;} string just to annoy you
             /* Now we take the {;} input: */
    scanf("%s",s);
    for(i=0;i<strlen(s);i++){if(s[i]>='a'&&s[i]<='z'){
            s[i]-=('a'-'A'); //this is same as s[i]=s[i]-'a'+'A'
    }
}printf("Your \"name\" in upper case is:\n%s\n",s);
       return 0;}

Ausgabe:

Bildbeschreibung hier eingeben


2
Das ist eine gute Idee, aber die Herausforderung ist ein Programmierwettbewerb. Können Sie ein Programm schreiben, das diese Datei mit visuellen Studios öffnet und sie dann in hübschem Druck speichert?
Justin
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.