C 변수 선언을 읽으십시오


41

배경

C의 변수 선언문 은 변수 이름 , 기본 유형유형 수정 자의 세 부분으로 구성됩니다 .

세 가지 유형의 수정자가 있습니다.

  • 포인터 *(접두사)
  • 배열 [N](접두사)
  • 기능 ()(접두사)
    • 괄호 안에 함수 인수 목록을 지정할 수 있지만,이 문제를 해결하기 위해 무시하고 사용하십시오 ()(기술적으로 "함수가 모든 종류의 인수를 취할 수 있음").

표기법을 읽는 방법은 다음과 같습니다.

int i;             // i is an int
float *f;          // f is a pointer to a float
my_struct_t s[10]; // s is an array of 10 my_struct_t
int func();        // func is a function returning an int

잡는 것은 배열의 배열 이나 함수 포인터의 배열 또는 포인터의 배열에 대한 포인터 와 같이 더 복잡한 유형을 형성하기 위해 이들을 모두 혼합 할 수 있다는 것 입니다 .

int arr[3][4];
// arr is an array of 3 arrays of 4 ints

int (*fptrs[10])();
// fptrs is an array of 10 pointers to functions returning an int

float *(*p)[16];
// p is a pointer to an array of 16 pointers to float

이 복잡한 진술을 어떻게 읽었습니까?

  1. 변수 이름에서 시작하십시오. (name) is ...
  2. 우선 순위가 가장 높은 수정자를 선택하십시오.
  3. 읽어:
    • * -> pointer to ...
    • [N] -> array of N ...
    • () -> function returning ...
  4. 수정자가 모두 소모 될 때까지 2와 3을 반복하십시오.
  5. 마지막으로 기본 유형을 읽으십시오. ... (base type).

C에서 접두사 연산자는 접두사 연산자보다 우선하며 유형 한정자는 예외가 아닙니다. 따라서, []()바인드 제 다음 *. (...)함수 연산자와 혼동하지 않아야 하는 한 쌍의 Parens 내부에있는 모든 것이 먼저 외부에 바인딩됩니다.

예시 된 예 :

int (*fptrs[10])();
      fptrs           fptrs is ...
           [10]       array of 10 ... // [] takes precedence over *
    (*         )      pointer to ...
                ()    function returning ...
int                   int

태스크

C로 작성된 변수 선언문의 행이 주어지면, 위에 표시된 방법을 사용하여 행을 설명하는 영어 표현식을 출력하십시오.

입력

입력은 단일 기본 유형, 단일 변수 이름, 0 개 이상의 유형 수정 자 및 끝 세미콜론을 포함하는 단일 C 문입니다. 위에서 다룬 모든 구문 요소와 함께 다음을 구현해야합니다.

  • 기본 유형과 변수 이름은 모두 정규식과 일치합니다 [A-Za-z_][A-Za-z0-9_]*.
  • 이론적으로 프로그램은 유형 한정자를 무제한 지원해야합니다.

다음과 같은 방법으로 다른 C 구문 요소를 단순화 할 수 있습니다 (전체 구현도 환영합니다).

  • 기본 유형은 항상 하나의 단어, 예를 들어 int, float, uint32_t, myStruct. 같은 unsigned long long것은 테스트되지 않습니다.
  • 배열 표기를 들어 [N], 숫자는 N항상 하나의 양의 정수 (10) 것들과 같은 기준으로 작성된 것입니다 int a[5+5], int a[SIZE]또는 int a[0x0f]테스트되지 않습니다.
  • 함수 표기법의 ()경우 위에서 지적한 것처럼 매개 변수가 전혀 지정되지 않습니다.
  • 공백의 경우 공백 문자 만 0x20사용됩니다. 예를 들어 프로그램을 공백의 특정 사용으로 제한 할 수 있습니다.
    • 기본 유형 다음에 한 칸만 사용하십시오.
    • 토큰 사이에 공간을 사용하십시오
  • 그러나 토큰 분리 자보다 많은 정보를 전달하기 위해 둘 이상의 연속 공백을 사용할 수 없습니다.

C 구문에 따르면 다음 세 가지 조합은 유효하지 않으므로 테스트되지 않습니다.

  • f()() 기능 반환 기능
  • f()[] 함수 반환 배열
  • a[]() N 함수의 배열

C 개발자는 이와 동등한 형식을 대신 사용합니다 (이 모든 것은 테스트 사례에서 다룹니다).

  • (*f())()함수를 가리키는 함수 반환 포인터
  • *f()배열의 첫 번째 요소에 대한 포인터를 반환하는 함수
  • (*a[])()함수에 대한 N 포인터의 배열

산출

결과는 단일 영어 문장입니다. 영어 문법 (예 : a, an, the, 단수 / 복수 형식, 끝점 (마침표))을 사용할 필요는 없습니다 (그러나 원하는 경우 가능 ). 각 단어는 하나 이상의 공백 (공백, 탭, 개행)으로 구분되어야 결과를 사람이 읽을 수 있습니다.

다시, 변환 과정은 다음과 같습니다.

  1. 변수 이름에서 시작하십시오. (name) is ...
  2. 우선 순위가 가장 높은 수정자를 선택하십시오.
  3. 읽어:
    • * -> pointer to ...
    • [N] -> array of N ...
    • () -> function returning ...
  4. 수정자가 모두 소모 될 때까지 2와 3을 반복하십시오.
  5. 마지막으로 기본 유형을 읽으십시오. ... (base type).

테스트 사례

int i;              // i is int
float *f;           // f is pointer to float
my_struct_t s[10];  // s is array of 10 my_struct_t
int func();         // func is function returning int
int arr[3][4];      // arr is array of 3 array of 4 int
int (*fptrs[10])(); // fptrs is array of 10 pointer to function returning int
float *(*p)[16];    // p is pointer to array of 16 pointer to float

_RANdom_TYPE_123 (**(*_WTH_is_TH15)())[1234][567];
/* _WTH_is_TH15 is pointer to function returning pointer to pointer to array of
   1234 array of 567 _RANdom_TYPE_123 */

uint32_t **(*(**(*(***p)[2])())[123])[4][5];
/* p is pointer to pointer to pointer to array of 2 pointer to function returning
   pointer to pointer to array of 123 pointer to array of 4 array of 5 pointer to
   pointer to uint32_t */

uint32_t (**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5]);
// Same as above, just more redundant parens

some_type (*(*(*(*(*curried_func())())())())())();
/* curried_func is function returning pointer to function returning pointer to
   function returning pointer to function returning pointer to
   function returning pointer to function returning some_type */

득점 및 당첨 기준

이것은 도전입니다. 바이트 수가 가장 적은 프로그램이 승리합니다.


9
관련 : cdecl.org
user202729

int arr[3][4];이다 an array of 3 arrays of 4 ints(당신이 말한대로), 또는 an array of 4 arrays of 3 ints?
Charlie

1
@Charlie 전자가 맞습니다. sizeof(arr[0]) == sizeof(int[4])의 항목에 arr4 개가 들어 있습니다 int.
Bubbler

1
입력 ;에 줄 끝에 포함되어 있습니까?
Black Owl Kai

2
@KamilDrakari 후자입니다. "포인터에 대한 포인터의 배열"은 본질적으로 "포인터의 배열"이며 C에서 완벽하게 유효합니다.
Bubbler

답변:


17

파이썬 3 , 3313129494240240 바이트

from re import*
class V(str):__pos__=lambda s:V(s+'pointer to ');__call__=lambda s:V(s+'function returning ');__getitem__=lambda s,i:V(s+'array of %i '%i)
t,e=input().split()
print(eval(sub('\*','+',sub('(\w+)',r'V("\1 is ")',e[:-1],1)))+t)

온라인으로 사용해보십시오!

파이썬 2로 전환하고 클래스 정의를 exec

Kevin Cruijssen 덕분에 정규식을에서 [a-zA-Z_][a-zA-Z0-9_]*로 변경하여 -18 바이트\\w+

Lynn 덕분에 클래스 정의 마법을 사용하고 str을 사용하여 -33 바이트, 파이썬 3으로 다시 변경

infmagic2047 덕분에 여러 정규 표현식을 병합하여 -21 바이트

입력에 하나의 공백 만 포함해야합니다 (유형과 표현식 사이).

나는 이것이 문제에 대한 매우 독특한 접근법이라고 생각합니다. 이것은 주로 파이썬 자체가 문자열을 평가 (**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5])하고 올바른 함수 호출 순서, 배열 인덱스 및 포인터를 얻을 수 있다는 사실을 사용합니다 .


1
멋진 접근 방식, 나에게서 +1! 골프 [a-zA-Z_][A-Za-z0-9_]*를 치고 [a-zA-Z_]\\w*몇 바이트를 절약 할 수 있습니다 . 편집 : 실제로, 당신은 \\w+대신 대신 사용할 수 있다고 생각합니다 [a-zA-Z_][A-Za-z0-9_]*.
Kevin Cruijssen

나는이 접근법을 좋아한다 :) 여기에 그것은 253 바이트이다
Lynn

1
그건 좋은 지적이야. 261 그때입니다.
Lynn

1
당신이 사용할 수있는 [0]대신에 .group()파이썬 3.6 있기 때문이다.
infmagic2047

1
그리고 여기에 240 바이트 버전이 있습니다.
infmagic2047

13

망막 0.8.2 , 142 138 128 117 바이트

(\w+) (.+);
($2) $1
\(\)
 function returning
\[(\d+)?]
 array of$#1$* $1
+`\((\**)(.+)\)
$2$1
\*
 pointer to
1` 
 is 

온라인으로 사용해보십시오! 링크에는 테스트 사례가 포함됩니다. 더 나은 문법 . 편집 : @DLosc의 Pip 솔루션을 이식하여 10 21 바이트를 절약했습니다. 설명:

(\w+) (.+);
($2) $1

유형을 끝으로 이동하고 ()외부 선언 이 포함 된 경우 나머지 선언을 s로 랩핑하십시오 *.

\(\)
 function returning

모든 기능을 처리하십시오.

\[(\d+)?]
 array of$#1$* $1

모든 배열을 처리하십시오.

+`\((\**)(.+)\)
$2$1

포인터를 괄호의 ​​끝으로 이동하고 괄호를 삭제하고 가장 바깥 쪽 괄호 세트에서 안쪽으로 반복해서 작업하십시오.

\*
 pointer to

포인터를 처리하십시오.

1` 
 is 

을 삽입하십시오 is.


7

Java 11, 469 4466 4450450 바이트

s->{String r="",t,S[];for(s=s.replace("()","~");s.contains("(");s=s.replace(t,"").replace("()",""),r+=t+";")t=s.replaceAll(".*(\\([^()]+\\)).*","$1");S=s.split(" ");t=S[0];r+=r.isEmpty()?S[1]:s;S=r.split(";");r=S[0].replaceAll(".*?(\\w+).*","$1 is ");for(var p:S)r+=p.replaceAll("[A-Za-z_]+\\d+|[^\\[\\d]","").replaceAll("\\[(\\d+)","array of $1 ")+(p.contains("~")?"function returning ":"")+"pointer to ".repeat(p.split("\\*").length-1);return r+t;}

온라인으로 사용해보십시오.

설명:

s->{               // Method with String as both parameter and return-type
  String r="",     //  Result-String, starting empty
         t,        //  Temp-String, starting uninitialized
         S[];      //  Temp String-array, starting uninitialized
  for(s=s.replace("()","~");
                   //  Replace all "()" in the input `s` with "~"
      s.contains("(");
                   //  Loop as long as the input `s` still contains "("
      ;            //    After every iteration:
       s=s.replace(t,"")
                   //     Remove `t` from `s`
          .replace("()",""),
                   //     And also remove any redundant parenthesis groups
       r+=t+";")   //     Append `t` and a semi-colon to the result-String
    t=s.replaceAll(".*(\\([^()]+\\)).*","$1");
                   //   Set `t` to the inner-most group within parenthesis
  S=s.split(" ");  //  After the loop, split the remainder of `s` on the space
  t=S[0];          //  Set `t` to the first item (the type)
  r+=              //  Append the result-String with:
    r.isEmpty()?   //   If the result-String is empty
                   //   (so there were no parenthesis groups)
     S[1]          //    Set the result-String to the second item
    :              //   Else:
     s;            //    Simple append the remainder of `s`
  S=r.split(";");  //  Then split `r` on semi-colons
  r=S[0].replaceAll(".*?(\\w+).*",
                   //  Extract the variable name from the first item
     "$1 is ");    //  And set `r` to this name appended with " is "
  for(var p:S)     //  Loop over the parts split by semi-colons:
    r+=            //   Append the result-String with:
      p.replaceAll("[A-Za-z_]+\\d+
                   //    First remove the variable name (may contain digits)
         |[^\\[\\d]","")
                   //    And then keep only digits and "["
       .replaceAll("\\[(\\d+)",
                   //    Extract the number after "["
         "array of $1 ")
                   //    And append the result-String with "array of " and this nr
      +(p.contains("~")?
                   //    If the part contains "~"
         "function returning "
                   //     Append the result-String with "function returning "
       :           //    Else:
        "")        //     Leave the result-String the same
      +"pointer to ".repeat(
                   //    And append "pointer to " repeated
         p.split("\\*").length-1);
                   //    the amount of "*" in the part amount of time
  return r         //  Then return the result-String
          +t;}     //  appended with the temp-String (type)

괄호가 중복 된 테스트 케이스에서 실패합니다.
Bubbler

@ 버블 러 아, 그 새로운 테스트 사례를 보지 못했습니다. 운 좋게도 쉽게 고칠 수 있습니다.
Kevin Cruijssen

6

배쉬 + cdecl + GNU sed, 180

cdecl여기에 필요한 대부분의 작업을 수행하는 유닉스 유틸리티입니다. 그러나 I / O 요구 사항을 충족시키기 위해서는 일부 sed사전 및 사후 처리가 필요합니다.

sed -r 's/^/explain struct /;s/struct (int|char double|float|void) /\1 /;s/\bfunc/_func/g'|cdecl|sed -r 's/^declare //;s/as/is/;s/struct //g;s/([0-9]+) of/of \1/g;s/\b_func/func/g'
  • 문법을 고치려고 시도하지 않았습니다.

sed 전처리 :

  • s/^/explain struct /- 모든 줄 의 시작 부분에 "explain struct"를 추가하십시오
  • s/struct (int|char double|float|void) /\1 /struct-C 언어 유형을 다룰 때 제거
  • s/\bfunc/_func/g - "func"는 cdecl에 의해 키워드로 인식됩니다.

sed 후 처리 :

  • s/^declare // -줄의 시작에서 "선언"을 제거
  • s/as/is/ -자기 설명
  • s/struct //g -모든 "struct"키워드를 제거하십시오
  • s/([0-9]+) of/of \1/g - "의"의 올바른 순서
  • s/\b_func/func/g -전처리 과정에서 교체 된 "_func"를 되돌립니다.

실제로 :

$ < cdecls.txt sed -r 's/^/explain struct /;s/struct (int|char double|float|void) /\1 /;s/\bfunc/_func/g'|cdecl|sed -r 's/^declare //;s/as/is/;s/struct //g;s/([0-9]+) of/of \1/g;s/\b_func/func/g'
i is int
f is pointer to float
s is array of 10 my_struct_t
func is function returning int
arr is array of 3 array of 4 int
fptrs is array of 10 pointer to function returning int
p is pointer to array of 16 pointer to float
_WTH_is_TH15 is pointer to function returning pointer to pointer to array of 1234 array of 567 _RANdom_TYPE_123
p is pointer to pointer to pointer to array of 2 pointer to function returning pointer to pointer to array of 123 pointer to array of 4 array of 5 pointer to pointer to uint32_t
p is pointer to pointer to pointer to array of 2 pointer to function returning pointer to pointer to array of 123 pointer to array of 4 array of 5 pointer to pointer to uint32_t
curried_func is function returning pointer to function returning pointer to function returning pointer to function returning pointer to function returning pointer to function returning some_type
$ 

s/\bfu/_fu/g전체 func교체 의 바이트를 저장하고 저장하는 것으로 충분 합니까?
DLosc

정말 유용한 유틸리티입니다? 나는 항상 그것이 웹 사이트의 이름이라고 생각했습니다
phuclv

@phuclv cdecl은 실제 유틸리티이며 C 선언을 확인하는 데 실제로 유용합니다.
Patricia Shanahan


이름이 지정된 변수 as(공백을 수정하기 위해 +4 바이트)에 실패합니다 . 액세스 할 수 cdecl없지만을 사용하여 64 바이트를 절약 할 수 있다고 생각합니다 sed -r 's/^(\w+)(\W+)/explain struct \1_\2_/'|cdecl|sed -r 's/^declare struct _|_$//;s/ as / is /;s/([0-9]+) of/of \1/g'.
Neil

6

-s , 152 150 148 139 137 126 125 123 바이트

세번째 접근!

YaRs" ("R';')R`\[(\d+)]`` array of \1`R"()"" function returning"L#aYyR`\((\**)(.+)\)`{c." pointer to"X#b}{[b"is"g@>2a]}Vy^s

선언을 명령 행 입력으로 사용합니다. 온라인으로 사용해보십시오!

설명

코드는 세 부분으로 구성됩니다. 초기 설정 및 함수 및 배열 처리; 괄호와 포인터를 처리하는 루프; 그리고 최종 재배치.

설정, 기능 및 배열

우리는 전체 선언이 우리가 변경할 수 있도록 (이 루프 나중에에 도움) 괄호로 할 type ...;type (...). 그런 다음 함수 및 배열에 대한 설명으로 재정렬이 수행되지 않으므로 최종 출력에 영향을주지 않고 모든 대체 작업을 먼저 수행 할 수 있습니다.

Y                         Yank into y variable...
 a                        The result of a (the cmdline arg)...
  R s                     Replace the space
   " ("                    with " ("
  R ';                    Replace the semicolon
   ')                      with a closing paren
  R `\[(\d+)]`            Replace digits in square brackets
   ` array of \1`          with " array of <digits>"
  R "()"                  Replace function parens
   " function returning"   with " function returning"

우리의 원래 입력이 있었다면 float *((*p()))[16];, 우리는 이제 float (*((*p function returning)) array of 16)입니다.

괄호와 포인터

우리는 가장 바깥 쪽 괄호 쌍과 여는 괄호 안에 즉시있는 별표를 대체하여 루프를 실행합니다.

L#a                   Loop len(a) times (enough to complete all replacements):
 Y                    Yank into y variable...
  y                   The result of y...
   R `\((\**)(.+)\)`  Replace open paren, 0 or more asterisks (group 1), 1 or more
                      characters (group 2), and close paren
    {                  with this callback function (b = group 1, c = group 2):
     c .               The stuff in the middle, concatenated to...
      " pointer to"    that string
       X #b            repeated len(asterisks) times
    }

예제 단계 :

float (*((*p function returning)) array of 16)
float ((*p function returning)) array of 16 pointer to
float (*p function returning) array of 16 pointer to
float p function returning pointer to array of 16 pointer to

대청소

남은 것은 유형을 끝으로 옮기고 "is"를 추가하는 것입니다.

{[b"is"g@>2a]}Vy^s
               y^s  Split y on spaces
{            }V     Use the resulting list as arguments to this function:
 [          ]        Return a list of:
  b                   2nd argument (the variable name)
   "is"               That string
       g@>2           All arguments after the 2nd
           a          1st argument (the type)
                    The resulting list is printed, joining on spaces (-s flag)

와 같은 정의의 int x;경우이 방법을 사용하면 추가 공간이 생겨 도전에 의해 허용됩니다.


5

자바 스크립트 (ES6), 316 ... 268 253 바이트

s=>(g=s=>[/\d+(?=])/,/\*/,/!/,/.+ /,/\w+/].some((r,i)=>(S=s.replace(r,s=>(O=[O+`array of ${s} `,O+'pointer to ','function returning '+O,O+s,s+' is '+O][i],'')))!=s)?g(S):'',F=s=>(O='',S=s.replace(/\(([^()]*)\)/,g))!=s?O+F(S):g(s)+O)(s.split`()`.join`!`)

온라인으로 사용해보십시오!

댓글

도우미 기능

g = s =>                             // s = expression to parse
  [                                  // look for the following patterns in s:
    /\d+(?=])/,                      //   array
    /\*/,                            //   pointer
    /!/,                             //   function
    /.+ /,                           //   type
    /\w+/                            //   variable name
  ].some((r, i) =>                   // for each pattern r at index i:
    ( S = s.replace(                 //   S = new string obtained by removing
      r,                             //       the pattern matching r from s
      s => (                         //     using the first match s and the index i,
        O = [                        //     update the output O:
          O + `array of ${s} `,      //       array
          O + 'pointer to ',         //       pointer
          'function returning ' + O, //       function
          O + s,                     //       type
          s + ' is ' + O             //       variable name
        ][i],                        //
        ''                           //     replace the match with an empty string
    )))                              //   end of replace()
    != s                             //   make some() succeed if S is not equal to s
  ) ?                                // end of some(); if truthy:
    g(S)                             //   do a recursive call with S
  :                                  // else:
    ''                               //   stop recursion and return an empty string

주요 부분

s => (                 // s = input
  g = …,               // define the helper function g (see above)
  F = s => (           // F = recursive function, taking a string s
    O = '',            //   O = iteration output, initialized to an empty string
    S = s.replace(     //   S = new string obtained by removing the next expression from s
      /\(([^()]*)\)/,  //     look for the deepest expression within parentheses
      g                //     and process it with the helper function g
    )                  //   end of replace()
  ) != s ?             // if S is not equal to s:
    O + F(S)           //   append O to the final output and do a recursive call with S
  :                    // else (we didn't find an expression within parentheses):
    g(s) + O           //   process the remaining expression with g and return O
)(s.split`()`.join`!`) // initial call to F with all strings '()' in s replaced with '!'

당신이 사용하는 이유 궁금 해서요 [...s.split`()`.join`!`]대신의 [...s.replace('()','!')],하지만 난 그것을 동일한 바이트 카운트의 실현 .. :)
케빈 Cruijssen

@KevinCruijssen 주된 이유는 s.replace('()','!')첫 번째 항목 만 대체하기 때문입니다 .
Arnauld

아 물론 이죠 JS 교체를 잊어 버린 것은 Java와 다릅니다. Java에서는 .replace모든 발생을 .replaceAll대체하고 모든 발생을 정규식 사용으로 대체합니다. 항상 내가 그들라는 것으로 명명은, 자바에서 이러한 두 가지 방법에 대한 아주 나쁜 생각 .replaceAll.regexReplaceAll그 라인을 따라 또는 뭔가를하지만, 나는 그것이 짧아입니다 codegolf에 대해 생각 .replace하고 .replaceAll.
Kevin Cruijssen

1
BTW, 나는 당신이 ~내 대답의 첫 번째 버전을 게시 한 직후에 같은 기술을 사용하고 있음을 알았습니다 . 좋은 생각은 비슷하게 생각합니다. : p
Arnauld

3

클린 , 415 바이트

import StdEnv,Text
$s#(b,[_:d])=span((<>)' ')(init s)
=join" "(?d++[""<+b])
?[]=[]
?['()':s]=["function returning": ?s]
?['*':s]= ?s++["pointer to"]
?['[':s]#(n,[_:t])=span((<>)']')s
=["array of "<+n: ?t]
?s=case@0s of(['(':h],t)= ?(init h)++ ?t;(h,t)|t>[]= ?h++ ?t=[h<+" is"]
~c=app2((++)[c],id)
@n[c:s]=case c of'('= ~c(@(n+1)s);')'|n>1= ~c(@(n-1)s)=([c],s);_|n>0= ~c(@n s)=span(\c=c<>'('&&c<>'[')[c:s]
@_ e=(e,e)

온라인으로 사용해보십시오!


3

R , 225 218 바이트

g=gsub
"&"="@"=paste
"["=function(a,b)a&"array of"&b
"+"=function(a)a&"pointer to"
eval(parse(t=g('\\(\\)','@"function returning"',g('(\\w+) (.*?)([A-Za-z_]\\w*)(.*);','\\2"\\3 is"\\4&"\\1"',g('\\*','+',readline())))))

온라인으로 사용해보십시오!

모든 테스트 사례를 한 번에 편리하게 테스트 할 수 있도록 TIO의 기능에 포함 된 전체 프로그램

첫째, 우리는 형태의 입력 변환 정규식을 사용 type ...name...;하는 방법에 대해 ..."name is"..."type". 함수 표기법 ()은 우선 순위가 높은 연결 연산자를 사용하여 텍스트로 변환됩니다. 불행하게도, 우리는 또한 교체해야 *+전자가 단항 연산자로 허용되지 않습니다있다. 나머지는 eval과부하 된 연산자 로 R에 의해 수행됩니다 .


1
영리한 솔루션!
J.Doe

3

펄 (6) , 209 (190) 171 162 153 바이트

{~({(.[1]Z'is'),.<e>.&?BLOCK,('array of'X .[2]),('function returning','pointer to'Zxx.[3,0])if $_}(m:g/(\*)*[(\w+)+|\(<e=~~>.][\[(\d+).]*(\(.)*/[1]),$0)}

온라인으로 사용해보십시오!

재귀 정규식 접근 방식. 3 바이트의 비용 으로 피할 수있는 추가 공백 문자를 생성 합니다 .

설명

{     # Anonymous block
 ~(   # Convert list to string
   {  # Block converting a regex match to a nested list
     (.[1]            # Array of 0 or 1 variable names
       Z'is'),        # zipped with string "is"
     .<e>.&?BLOCK,    # Recursive call to block with subexpression
     ('array of'      # String "array of"
       X .[2]),       # prepended to each array size
     ('function returning',  # Strings "function returning"
      'pointer to'           # and "pointer to"
      Zxx             # zipped repetition with
      .[3,0])         # number of function and pointer matches
     if $_            # Only if there's an argument
   }
   (             # Call block
     m:g/        # Input matched against regex
      (\*)*      # Sequence of asterisks, stored in [0]
      [          # Either
       (\w+)+    # the variable name, stored as 1-element array in [1]
       |         # or
       \(        # literal (
         <e=~~>  # the same regex matched recursively, stored in <e>
       .         # )
      ]
      [\[(\d+).]*  # Sequence of "[n]" with sizes stored in [2]
      (\(.)*       # Sequence of "()" stored in [3]
     /
     [1]  # Second match
   ),
   $0     # First match (base type)
 )
}

2

자바 스크립트 250 바이트 [249?]

이것은 250 바이트를 사용합니다 :

k=>(a=k.match(/\W|\w+/g),s=[v=j=r=""],f=y=>!j&!a[i+1]||(m=a[i],v?(r+=v=m=='['?`array of ${a[i+=3,i-2]} `:m<')'?(i+=2,"function returning "):s[j-1]=='*'?j--&&"pointer to ":""):m==')'?v=j--|i++:m<'+'?s[j++]=a[i++]:r+=a[v=i++]+" is ",f(),r+a[0]),f(i=2))

설명:

기본적으로 a토큰 화 된 입력 인 buffer에서 읽습니다 . 평가 모드가 트리거 될 때까지 토큰을 버퍼 a에서 스택 으로 계속 이동 s합니다. 평가 모드는 제 후위 동작을 소비한다 (), []상기 버퍼에서, 그리고, 그것은 프리픽스 연산자 소비 할 *스택에서를. 평가 모드는 상태가 단어가있는 위치에있을 때 트리거됩니다 (유형 이름을 찾아서 소비하거나 끝 )을 찾아서 제거). 더 이상 접두사 / 접두사 연산자가 없으면 평가 모드가 비활성화됩니다.

k=>( // k is input
    a=k.match(/\W|\w+/g), // split by symbol or word
    s=[v=j=r=""], // j=0, v=false, r="", s=[]
    // s is the stack, r is the return string,
    // v is true if we're in evaluation mode (Consume (), [], *)
    // v is false if we're waiting to see a ) or token, which triggers evaluation
    // j is the index of the top of the stack (Stack pointer)
    f=y=>!j&!a[i+1]||( // !j means stack is empty, !a[i+1] means we're at the ;
        m=a[i], // Save a[i] in a variable
        v // Are we evaluating?
        ?(
        r+=v=
            m=='[' // Array
            ?`array of ${a[i+=3,i-2]} ` // Skip three tokens: "[", "10", "]"
                                        // a[i-2] is the "10"
            :m<')' // m == '('
                ?(i+=2,"function returning ") // Skip two tokens: "(", ")"
                :s[j-1]=='*' // Stack has a pointer
                    ?j--&&"pointer to " // Pop the stack
                    :"" // Set v to be false, r+=""
        )
        :m==')'
            ?v=j--|i++ // Pop the '(', skip over the ')', v = Evaluation mode
            :m<'+' // m == '*' || m == '('
                ?s[j++]=a[i++] // push(s, pop(a))
                :r+=a[v=i++]+" is " // Otherwise we have the token
        , f(), r+a[0] // Recurse f(), and return r+a[0]. a[0] is the type.
    ),
    f(i=2) // Set i=2, and call f(), which returns the final value r + type
    // a = ["type", " ", ...], so i=2 give the first real token
    // This soln assumes there is only one space, which is an allowed assumption
)

노트

"토큰 사이에 공간 사용"을 올바르게 이해하면 :

k=>(a=k.split(" "),s=[v=j=r=""],f=y=>!j&!a[i+1]||(v?(r+=v=a[i]=='['?`array of ${a[i+=3,i-2]} `:a[i]<')'?(i+=2,"function returning "):s[j-1]=='*'?j--&&"pointer to ":""):a[i]==')'?v=j--|i++:a[i]<'+'?s[j++]=a[i++]:r+=a[v=i++]+" is ",f(),r+a[0]),f(i=1))

기술적으로 유효하며

249 바이트

모든 토큰 사이에 공백이 있다고 가정합니다.


2
똑바로 보였지만 많은 시간이 걸렸습니다. 350 문자로 시작하여 5-10 바이트 / 시간을 노크했을 것입니다. 나는 실제로 생명이 없다.
Nicholas Pipitone

2
나는 "나는 나의 현재의 알고리즘을 최적 히트 - RIP"를 생각했을 때 내가 325에 대한 있었다, 그러나 어떤 이유로 난 아직도 5-10 / 시간을 노크 할 수 있었다 각각 다음되는 노크에도 불구하고, "좋아,이는 확실히 최적의 결과 ". 그것이 내가 여전히 "좋아,이 말하는 순간에도, 재위 253를 이길 첫 번째 이후 250 명중하는 것은 임의했다 확실히 , 아직 최적화에 더있을 수 있습니다 최적의 결과".
니콜라스 피피 톤

1

빨강 , 418410 바이트

func[s][n: t:""a: charset[#"a"-#"z"#"A"-#"Z"#"0"-#"9""_"]parse s[remove[copy x thru" "(t: x)]to a
change[copy x[any a](n: x)]"#"]b: copy[]until[c: next find s"#"switch c/1[#"("[append
b"function returning"take/part c 2]#"["[parse c[remove[skip copy d to"]"(append b
reduce["array of"d])skip]]]#")"#";"[take c c: back back c while[#"*"= c/1][take c
c: back c append b"pointer to"]take c]]s =""]reduce[n"is"b t]]

온라인으로 사용해보십시오!

설명:

f: func [ s ] [
    n: t: 0                                         ; n is the name, t is the type
    a: charset [ #"a"-#"z" #"A"-#"Z" #"0"-#"9" "_" ]; characters set for parsing 
    parse s[                                        ; parse the input with the following rules
        remove [ copy x thru " " ](t: x)            ; find the type, save it to t and remove it from the string
        to a                                        ; skip to the next alphanumerical symbol
        change [ copy n [ any a ] (n: x) ] "#"      ; save it to n and replace it with '#'
    ]
    b: copy [ ]                                     ; block for the modifiers 
    until [                                         ; repeat 
       c: next find s "#"                           ; find the place of the name   
       switch c/1 [                                 ; and check what is the next symbol
           #"(" [ append b "function returning"     ; if it's a '('- it's a function - add the modifier       
                  take/part c 2                     ; and drop the "()"
                ]
           #"[" [ parse c [                         ; '[' - an array
                     remove [ skip copy d to "]"    ; save the number
                             (append b reduce [     ; and add the modifier 
                                  "array of" d
                              ] )                   
                             skip ]                 ; and remove it from the string
                     ]
                ]
           #")"                                     ; a closing bracket 
           #";" [ take c                            ; or ';' - drop it
                    c: back back c                  ; go to the left 
                    while [ #"*" = c/1 ]            ; and while there are '*'
                    [
                        take c                      ; drop them
                        c: back c                   ; go to the left
                        append b "pointer to"       ; add the modifier
                    ]
                    take c                          ; drop '(' (or space)
                 ]
       ]
       s = ""                                       ; until the string is exhausted
    ]
    reduce [ n "is" b t ]                     ; display the resul
]

0

APL (NARS), 문자 625, 바이트 1250

CH←⎕D,⎕A,⎕a,'_'⋄tkn←nm←∆←''⋄in←⍬⋄⍙←lmt←lin←0
eb←{∊(1(0 1 0)(0 1)(1 0))[⍺⍺¨⍵]}
tb←{x←({⍵='[':3⋄⍵=']':4⋄⍵∊CH,' ':1⋄2}eb⍵)\⍵⋄(x≠' ')⊂x}

gt
tkn←''⋄→0×⍳⍙>lin⋄tkn←∊⍙⊃in⋄⍙+←1⋄→0×⍳(⍙>lin)∨'('≠↑tkn⋄→0×⍳')'≠↑⍙⊃in⋄tkn←tkn,⍙⊃in⋄⍙+←1

r←dcl;n
   n←0
B: gt⋄→D×⍳'*'≠↑tkn⋄n+←1⋄→B×⍳tkn≢''
D: r←ddcl⋄∆←∆,∊n⍴⊂'pointer to '

r←ddcl;q
   r←¯1⋄→0×⍳0>lmt-←1
   →A×⍳∼'('=↑tkn⋄q←dcl⋄→F×⍳')'=↑tkn⋄→0
A: →B×⍳∼(↑tkn)∊CH⋄nm←tkn⋄→F
B: r←¯2⋄→0
F: gt⋄→G×⍳∼tkn≡'()'⋄∆←∆,'function that return '⋄→F
G: →Z×⍳∼'['=↑tkn⋄∆←∆,'array of ',{''≡p←(¯1↓1↓tkn):''⋄p,' '}⋄→F
Z: r←0

r←f w;q
   nm←∆←''⋄in←tb w⋄⍙←1⋄lin←↑⍴in⋄lmt←150⋄gt⋄→A×⍳∼0>q←dcl⋄r←⍕q⋄→0
A: r←nm,' is a ',∆,1⊃in

이것은 Brian W. Kerninghan과 Dennis M. Ritchie 챕터 5.12의 "Linguaggio C"책의 코드에서 C 언어에서 APL 로의 한 번의 번역 일뿐입니다. 나는 그 코드를 100 % 이해하지 못했기 때문에, 그리고 APL에 대해 너무 많이 알지 못하기 때문에 모든 것을 줄이는 방법을 모르겠습니다 ... 운동을위한 함수는 f입니다. 나는 오류에 대해 150 개의 중첩 된 부모 '(' ')'만 허용된다고 생각하면 하나의 음수 값으로 하나의 strign을 반환하거나 모든 것이 정상이면 문자열 설명이 허용됩니다. 다른 문자가 오류를 더 잘 볼 수 있기 때문에 문자가 적더라도 다른 버전보다 낫지 않은 것 같습니다. 몇 가지 테스트 :

  f 'int f()()'
f is a function that return function that return int
  f 'int a[]()'
a is a array of function that return int
  f 'int f()[]'
f is a function that return array of int
  f 'int i;'
i is a int
  f 'float *f;'
f is a pointer to float
  f 'my_struct_t s[10];'
s is a array of 10 my_struct_t
  f 'int func();'
func is a function that return int
  f 'int arr[3][4];'
arr is a array of 3 array of 4 int
  f 'int (*fptrs[10])();'
fptrs is a array of 10 pointer to function that return int
  f 'float *(*p)[16]; '
p is a pointer to array of 16 pointer to float
  f '_RANdom_TYPE_123 (**(*_WTH_is_TH15)())[1234][567];'
_WTH_is_TH15 is a pointer to function that return pointer to pointe
  r to array of 1234 array of 567 _RANdom_TYPE_123
  f 'uint32_t (**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5]);'
p is a pointer to pointer to pointer to array of 2 pointer to funct
  ion that return pointer to pointer to array of 123 pointer to
   array of 4 array of 5 pointer to pointer to uint32_t
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.