Cコード圧子


12

状況:あなたは高校の教師で、コンピューティングクラスにCプログラムの書き方を教えています。ただし、これは用語の始まりに過ぎないため、インデントとスペースの重要性については教えていません。あなたが彼らの作品に印をつけていると、あなたの目はとても痛くなり、あなたは苦痛に悲鳴を上げ、これが続くことができないことに気づきます。

タスク:任意の言語で、有効なCソースコードを入力として受け取り、適切にフォーマットされたプログラムを作成することにしました。人気のコンテストなので、適切にフォーマットされたコードを決定する必要があります。できるだけ多くの機能を実装することをお勧めします。以下に例を示します。

  • 各行の前に適切なインデントを追加します
  • 後にスペースを追加,変換例えば、およびその他の演算子をint a[]={1,2,3};しますint a[] = {1, 2, 3};。ただし、文字列リテラル内で演算子を処理しないでください。
  • 各行の末尾のスペースを削除します
  • ステートメントを複数の行に分割します。たとえば、生徒が書いtmp=a;a=b;b=tmp;たり、int f(int n){if(n==1||n==2)return 1;else return f(n-1)+f(n-2);}すべてを1行にしたりする場合、それらを別の行に分割できます。forただし、ループには注意してください。セミコロンが含まれていますが、分割する必要はないと思います。
  • 各関数を定義した後に新しい行を追加します
  • 生徒のコードを理解するのに役立つ他の機能もあります。

受賞基準:これは人気コンテストなので、ほとんどの賛成票で答えが勝ちます。同点の場合、実装されているほとんどの機能を備えた答えが優先されます。それが再び同点の場合、最短のコードが優先されます。

回答には、実装した機能のリスト、およびサンプルの入力と出力を含めることをお勧めします。

編集:ここのコメントで要求されているのはサンプル入力ですが、これは参照用であり、できるだけ多くの機能を実装することをお勧めします。

入力:

#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;}

これは私が通常このコードをフォーマットする方法です:(私は怠け者です)

#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;
}

これは私が読みやすいと思う方法です:

#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;
}




また、回答が開始されたので、投票数が最も多い回答は最後の回答の5日後に受け入れられます。つまり、5日以内に新しい回答がなければ、このコンテストは終了します。


2
反対票の理由は何ですか?
user12205 14

1
不要な空白(s/\s+/ /)をすべて削除して1日と呼ぶことができます
ラチェットフリーク14

1
@ratchet freakはできますが、これが多くの賛成票で答えになるとは思いません。
user12205 14

1
@Quincunxは、賞金を設定してくれてありがとう。私は私の質問が吸い込まれたと思った。
user12205 14

1
@CousinCocaine:これは人気のコンテキストです。それらは、エレガントで標準的な方法で問題を解決するように設計されていません。それらは、想像できる限りクールな方法で問題を解決するように設計されています。
SztupY 14

回答:


21

インデントと空白について話しているので、実際には空白を中心に設計された言語のプログラミングでコードを書くだけです。

解決策は次のとおりです。




















































































































































































































































































































































































































































これはbase64にあります:

ICAgCQogICAgCgkJICAgIAkgCiAgICAKCQkgICAgCQkKICAgIAoJCSAgICAJICAKICAgIAoJCSAgICAJIAkKICAgIAoJCSAKIAogCQoKICAgCSAKICAgCQoJCQkgICAJCQkgCQkKCSAgCQoJICAJICAKICAgCQoJCQkgICAJIAkgCgkgIAkKCSAgCSAJCiAgIAkKCQkJICAgCSAgCQoJICAJCgkgIAkgCQogICAJCgkJCSAgIAkgICAgIAoJICAJCgkgIAkgCQogICAJCgkJCSAgIAkJCQkJIAkKCSAgCQoJICAJCSAKICAgCQoJCQkgICAJICAgCSAKCSAgCQoJICAJICAgIAogICAJCgkJCSAgIAkgCSAgIAoJICAJCgkgIAkgICAJCQogICAJCgkJCSAgIAkgCSAgCQoJICAJCgkgIAkgIAkgIAogICAJIAogICAJCgkJIAogCSAJCQkKICAgCQoJCQkJCiAgCgkKCiAgIAkgIAogICAJCgkJCQkKICAKCQoKICAgCSAJCgoJCgogICAJCSAKICAgCQkKICAgCQkKCQkJICAgCQoJICAJCQkgICAgCSAKICAgCQoJCSAKIAkgCQkJCiAgIAkKCQkJCQogIAoJCgogICAJICAgIAogICAJIAogICAJIAoJCSAKIAkgCQkJCiAgIAkKCQkJCQogIAoJCgogICAJICAgCQkKICAgCSAJCiAgIAkgCQoJCQkgICAJCgkgICAJCSAgICAJIAogICAJCgkJIAogCSAJCQkKICAgCQoJCQkJCiAgCgkKCiAgIAkgIAkgIAogICAJIAkKICAgCSAJCgkJCSAgIAkKCSAgCQkJICAgIAkgCiAgIAkKCQkgCiAJIAkJCQogICAJCgkJCQkKICAKCQoKICAgCQkKICAgCQoJCQkgICAJIAkgCgkgIAkKCSAgCQkgIAogICAJCgkJCSAgIAkJCQkgCQkKCSAgCQoJICAJCSAJCiAgIAkKCQkJICAgCQkJCQkgCQoJICAJCgkgIAkJCSAKICAgCQoJCQkgICAJCQkgCQkKCSAgCQoJICAJCQkJCiAgIAkKCQkJICAgCSAgIAkgCgkgIAkKCSAgCQkgCQkKICAgCQoJCQkgICAJIAkgCSAKCSAgCQoJICAJCQkgIAogICAJCgkJCSAgIAkgCQkJCQoJICAJCgkgIAkJCSAJCiAgIAkKCQkJICAgCSAJICAgCgkgIAkKCSAgCSAgCSAJCiAgIAkKCQkJICAgCSAJICAJCgkgIAkKCSAgCSAgCQkgCiAgIAkKCQkJCQogIAoJCgogICAJCSAgCiAgIAkgCiAgICAKCQkgCgkKCiAgIAkJIAkKICAgCQoJCQkJCiAgICAgCSAKICAgIAoJCSAgICAJCQogICAJCQoJCQkgICAJCgkgICAJCSAKCQoKICAgCQkJIAogICAJCQogICAJCQoJCQkgICAJCgkgIAkJCSAKIAkgCQkJCiAgIAkKCQkJCQogICAgIAkgCiAgICAKCQkgCgkKCiAgIAkJCQkKICAgCQoJCQkJCiAgICAgCSAJCgkJCQoJICAJIAkgCgoJCgogICAJICAJCQkKICAgCSAKICAgIAoJCSAKCQoKICAgCQkgCQkKICAgCQoJCQkJCiAgICAgCSAKICAgCSAKCQkgCgkKCiAgIAkJCSAgCiAgIAkgIAoJCQkgICAJIAkJCQkKCSAgCQoJICAJCQkJIAogICAJCgkJCQkKICAKCQoKICAgCQkJIAkKICAgCSAgCgkJCSAgIAkgCQkJCQoJICAJCgkgIAkJCQkJCiAgIAkKCQkJCQogIAoJCgogICAJCQkJIAogICAJCgkJCQkKICAgICAJIAogICAJCQoJCSAKCQoKICAgCQkJCQkKICAgCQoJCQkJCiAgICAgCSAKICAgCSAgCgkJIAoJCgogICAJICAJIAkKICAgCSAJCiAgIAkgCQoJCQkgICAJCgkgICAJCSAgICAJCgkJCQkKICAKCQoKICAgCSAgCQkgCiAgIAkgCQogICAJIAkKCQkJICAgCQoJICAJCQkgICAgCQoJCQkJCiAgCgkKCiAgIAkJCQogICAJIAkgCgkKICAgICAJCQoJCQkKICAgCSAgCQogCiAKCSAgCSAgIAogCiAKCQkgCSAgIAogICAJICAgICAKCQogICAgIAkgICAgIAoJCiAgICAgCQoJICAJCiAKIAkgIAkKCiAgIAkgICAKCgkKCiAgIAkgCSAJCiAgIAkKCQkJICAgCSAJIAoJICAJCgkgIAkJICAgCiAgIAkKCQkJICAgCSAgIAkgCgkgIAkKCSAgCQkgIAkKICAgCQoJCQkJCiAgCgkKCiAgIAkJICAgCiAgIAkgCiAgICAKCQkgCgkKCiAgIAkJICAJCiAgIAkgIAoJCQkgICAJIAkJCSAgCgkgIAkKCSAgCQkgCSAKICAgCSAKICAgCQoJCSAgICAJCgkJCQkKICAKCQoKICAgCQkgCSAKICAgCQoJCQkJCiAgCgkKCiAgIAkgCQkgCiAgIAkKCQkJICAgCSAJCQkJCgkgIAkKCSAgCSAgICAgCiAgIAkKCQkJCQogIAoJCgogICAJICAgICAKICAgCSAgCgkJCSAgIAkgCSAJIAoJICAJCgkgIAkgICAgCQogICAJCgkJCQkKICAKCQoKICAgCSAgICAJCiAgIAkKCQkJCQogICAgIAkgCiAgIAkKCQkgCgkKCiAgIAkgCQkJCiAgIAkKCQkJICAgCSAJIAoJICAJCgkgIAkgICAJIAogICAJCgkJCQkKICAKCQoKICAgCSAgIAkgCiAgIAkgCiAgICAKCQkgCgkKCiAgIAkKICAgCSAgCiAgIAkKCQkJCQkgICAgCQoJCgkgICAgCSAKCQkJCgkgIAkgCSAKICAgCSAKCQkJICAgCQoJICAJCgkgIAkgICAJCiAgIAkgCgkJCSAgIAkgCgkgIAkKCSAgCSAgCSAKICAgCSAKCQkJICAgCQkKCSAgCQoJICAJICAJCQogICAJIAoJCQkgICAJICAKCSAgCQoJICAJIAkgIAoKICAgCSAgIAkKCiAJIAkJCgogCiAJIAkJCgogICAJIAkgCgogCSAJIAoKIAogCSAJCQoKICAgCSAgCSAKCiAJIAkgCSAJCgogCiAJIAkJCgogICAJICAJCQoKIAkgCSAJCSAKCiAKIAkgCQkKCiAgIAkgCSAgCgogCSAJIAkJCQoKICAgCSAJCQoKIAogCQoKCgo=

紙にコードを印刷するのに問題がある人のために、ここに注釈付きのバージョンがあります(答えの最後にこのためのコンパイラがあります)。

# 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

これはまだ進行中の作業ですが、ほとんどの基準に合格するはずです!

現在サポートされている機能:

  • {および}文字に基づいて識別を修正します。
  • 後に改行を追加 ;
  • 文字列リテラル内のインデント文字を処理する(文字列リテラルがに遭遇したときに閉じられないという事実を含む\"
  • 単一行および複数行のコメント内のインデント文字を処理します
  • 括弧内(forブロックなど)の場合、改行文字を追加しません

入力例(エッジケースベースのQuincunxのコメントを追加したので、適切に動作することを確認できます):

    /* 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;}

出力例:

[~/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;;
}

空白はEOFチェックをサポートしていないため、インタープリターは例外をスローしますが、これを抑制する必要があります。ホワイトスペースではEOFをチェックする方法がないため(これが私の最初のホワイトスペースプログラムである限り)、これは避けられないものであり、解決策が重要であることを願っています。

これは、注釈付きバージョンを適切な空白にコンパイルするために使用したスクリプトです。

#!/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

走る:

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

(注)この離れ変換からのSL及びTの文字が、またして単一行のコメントを許可し#て、自動的にその空白の表現に数字と単純な文字リテラルを変換することができます。必要に応じて、他の空白プロジェクトに自由に使用してください


悪くない!:)しかし、forループを3行に分割しない方が良いでしょう(少なくとも私の意見では...決定するのはまだ投票者次第です)。リマインダとして、Cにおけるforループ構文を有するfor(i=0;i<10;i++)
user12205

2
@ace:Whitespaceは高水準言語ではないため、この種の例外を追加するのはそれほど簡単ではありません。つまり、私はまだコメントとリテラルに関する2つの問題を修正しようとし、ループも修正しようとしています(;内部(/ )ブロックを無視するだけで十分だと思います)。これらは、ソリューションを「使用可能」と見なすのに十分なはずだと思います。
SztupY 14

1
@ace:例外を追加できたので、生成されたコードは適切にインデントされているようです。あなたの1に例を変更
SztupY

9

Vim 技術的に1文字のみを使用して、簡単な方法でします。=

私はvimの第一人者ではありませんが、その力を過小評価することはありませんし、プログラミング言語と見なす人もいます。私にとって、このソリューションはとにかく勝者です。

vimでファイルを開きます。

vim file.c

vim内で次のキーを押します

gg=G

説明:

gg ファイルの先頭に移動します

= インデントを修正するコマンドです

G ファイルの最後まで操作を実行するように指示します。

保存して終了できます :wq

させることが可能であるvim、これはまた、ワンライナーで行うことができるので、コマンドラインからコマンドを実行しますが、私は知っている人にそれを残してvim、より良い私よりも。


Vimは 、不正なインデントを持つ有効な入力ファイル(fibonacci.c)の例を示します。

/* 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;
}

vimで開く:をvim fibonacci.c押しますgg=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;
}


これはに短縮できます=GZZ。(Vim golf ftw!)
ドアノブ

7

これは、教師が生徒のコードをよりよく理解するために使用されるため、最初に入力をサニタイズすることが重要です。プリプロセッサディレクティブは不要であり、混乱を招くだけであり、マクロも悪意のあるコードをファイルに導入する可能性があります。そんなことはしたくない!また、とにかく完全に役に立たないので、学生が書いた元のコメントを保持することは完全に不要です。

代わりに、インデントと構造を修正する以外に、良いコードには良いコメントが必要だと誰もが知っているので、結果をさらに理解しやすくするために、コードの主要なポイントの周りに非常に有用なコメントを追加してみてください!これは間違いなく、教師が生徒の行った作業を評価するのに役立ちます!

だからこれから:

    /* 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;}

これを作りましょう:

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;
}

式を囲む便利なコメントがすべて揃っているため、はるかに優れていると思いませんか?


これは、Cパーサーであるgemを利用したルビーソリューションです(はい、私は浮気しています)。これによりコードが解析され、最初から再印刷されるため、結果が完全にインデントされ、一貫性が保たれます。たとえば:cast

  • ブロックレベルに基づいたコード全体の適切なインデント
  • 式、ステートメント、条件などの周りの一貫したホワイトスペース
  • コードの構造に基づいた完全な再インデント

また、コードがどのように機能するかについて非常に有用なコメントが含まれます。これは、生徒と教師の両方にとって非常に便利です!

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
+1it is completely unnecessary to retain the original comments the student wrote, as they are probably completely useless anyway
SeinopSys 14

これらのコメントは私には説明的ではありません。次の行を単純に言い換えているため、混乱が生じます。
ジャスティン14

@Quincunx皮肉なタグを見逃したと思います。これは人気コンテストです。
SztupY 14

5

Bash、35文字

入力ファイルには「input.c」という名前を付け、現在の作業ディレクトリに配置する必要があります。

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

元の質問の入力が入力された出力例: http://i.imgur.com/JEI8wa9.png

ハードウェアによっては実行に数秒かかる場合がありますので、しばらくお待ちください:)


これはコードゴルフではないことを知っていますよね?
ジャスティン

1
AStyleをオンザフライでダウンロードおよびコンパイルするための+1 だから削除するrm
tomsmeding

これはコードゴルフではないので、ペーストビンの内容をここに置いた方が良いと思います。簡単に見ると、実際には外部コマンドでコードを適切にフォーマットしていることに気づきさえしませんでした
SztupY

@Quincunx:それはちょっとしたトロールの答えになることを意図しています:P
Riot

@tomsmeding:私は私のコードが、予期せず、ユーザーのディスクスペースを占有などの副作用を、持っているのは嫌だ...
暴動

3

ルビー

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;}

出力:

#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;
}

出力 SztupYのエッジケース入力@について:

#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;
}

これまでの機能:

  • [x] 各行の前に適切なインデントを追加します
  • [x]後にスペースを追加,変換例えば、およびその他の演算子をint a[]={1,2,3};しますint a[] = {1, 2, 3};。ただし、文字列リテラル内で演算子を処理しないでください。
  • [x] 各行の末尾のスペースを削除します
  • [x]ステートメントをいくつかの行に分けます。たとえば、生徒は次のように書くtmp=a;a=b;b=tmp;か、int f(int n){if(n==1||n==2)return 1;else return f(n-1)+f(n-2);}すべてを1行にしたりする場合、それらを別の行に分割できます。forただし、ループには注意してください。セミコロンが含まれていますが、分割する必要はないと思います。
  • [ ] 各関数を定義した後に新しい行を追加します
  • [ ] 生徒のコードを理解するのに役立つ他の機能もあります。

3

これはpythonで書かれ、GNUコーディング標準に基づいています。

これまでの機能:

  • インデントブロック
  • 行の分割(あるべきではないものを分割する可能性があります)
  • GNUスタイルの関数定義

コード:

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

入力例(引数としてファイル名を渡す):

#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;}

出力例:

#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;
}

これはバグがあります。


0

。ネット

Visual Studioを使用してそのファイルを開く

入力:

#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;}

出力:

ここに画像の説明を入力してください


2
これは良い考えですが、課題はプログラミングコンテストです。このファイルをビジュアルスタジオで開き、きれいに印刷して保存するプログラムを作成できますか?
ジャスティン14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.