读出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语言中,后缀运算符优先于前缀运算符,类型修饰符也不例外。因此,[]()结合第一,然后*。一对括号中的任何内容(...)(不要与函数运算符混淆)首先绑定外部的任何内容。

图解示例:

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

任务

给定一行用C编写的变量声明语句,请使用上述方法输出描述该行的英语表达式。

输入项

输入是单个C语句,其中包括单个基本类型,单个变量名,零个或多个类型修饰符以及结尾的分号。您必须实现上面介绍的所有语法元素,以及:

  • 基本类型和变量名称都与正则表达式匹配[A-Za-z_][A-Za-z0-9_]*
  • 从理论上讲,您的程序应支持无限数量的类型修饰符。

您可以通过以下方式简化其他C语法元素(也欢迎完全实现):

  • 基类型是总是一个字,例如intfloatuint32_tmyStruct。诸如此类的东西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 */

得分标准

这是一个挑战。字节数最少的程序获胜。



int arr[3][4];an array of 3 arrays of 4 ints(如您所说),还是an array of 4 arrays of 3 ints
查理

1
@查理前者是正确的。sizeof(arr[0]) == sizeof(int[4]),因此其中一个项目arr包含四个ints。
Bubbler '18

1
输入是否;在行尾包含?
黑猫头鹰Kai

2
@KamilDrakari是后者。“指向函数的指针数组”本质上是“指针数组”,在C语言中完全有效
。– Bubbler

Answers:


17

Python 3中331个312 294 261 240字节

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)

在线尝试!

切换到python 2并将类定义放入-19个字节中 exec

-18字节通过从改变正则表达式[a-zA-Z_][a-zA-Z0-9_]*\\w+,由于凯文Cruijssen

-33字节,通过工作一些类定义魔术并利用str,感谢Lynn,改回python 3

通过合并多个正则表达式来获得-21个字节,这要感谢infmagic2047

要求输入中仅包含一个空格(类型和表达式之间)。

我认为这是解决该问题的非常独特的方法。这主要是因为Python本身可以像这样评估字符串,(**((*(**(((*(((**(*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_]*
凯文·克鲁伊森

我喜欢这种方法:)这里是253个字节
Lynn

1
那是个很好的观点。然后是261
林恩

1
从Python 3.6开始,您可以使用[0]代替.group()
infmagic2047 18/10/26

1
这是一个240字节的版本
infmagic2047

13

视网膜0.8.2142个 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

爪哇11,469个 467 463 450字节

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

@Bubbler啊,没有注意到那个新的测试用例。幸运的是,这很容易解决。
凯文Cruijssen

6

Bash + cdecl + GNU sed,180

cdecl是一个古老的Unix实用程序,它执行此处所需的大部分操作,但是为了满足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 /-在行的开头添加“解释结构”
  • s/struct (int|char double|float|void) /\1 /- struct处理C语言类型时删除
  • s/\bfunc/_func/g -cdecl将“ func”识别为关键字-禁止显示

sed后处理:

  • s/^declare // -删除行首的“声明”
  • s/as/is/ -不言自明
  • s/struct //g -删除所有“结构”关键字
  • s/([0-9]+) of/of \1/g -正确排序“ of”
  • 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'
尼尔

6

PIP -s152 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

JavaScript(ES6),316 ... 268253字节

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('()','!')],但是我意识到这是完全相同的字节数.. :)
Kevin Cruijssen

@KevinCruijssen主要原因是s.replace('()','!')只能替换第一次出现的情况。
Arnauld

嗯当然了 忘记JS替换与Java不同。在Java中,.replace替换所有匹配项,并.replaceAll在启用正则表达式的情况下替换所有匹配项。一直以为Java中的这两种方法的命名是很糟糕的,因为我会称呼它们.replaceAll和/ .regexReplaceAll或类似的东西,但是我想对于codegolf来说,它的缩写为.replaceand .replaceAll
凯文·克鲁伊森

1
顺便说一句,我注意到~在发布我自己答案的第一个版本后,您正在使用相同的技术(和)。我想,好主意也是如此。: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中的功能中,可方便地一次测试所有测试用例。

首先,我们使用Regex将表单的输入转换type ...name...;..."name is"..."type"()然后使用高级串联运算符将函数符号转换为文本。不幸的是,我们也必须替换为*+因为前者作为一元运算符是不可接受的。其余的由eval带有重载运算符的R完成。


1
聪明的解决方案!
J.Doe

3

Perl 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

JavaScript 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))

说明:

基本上,它是从buffer读取的,该缓冲区a是标记化的输入。它将令牌从缓冲区连续移到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
尽管看起来很简单,但这却花了我很多小时。我可能每小时要敲5-10个字节,以350个字符开头。我确实没有生命。
Nicholas Pipitone

2
当我想到“我用当前的算法达到最佳效果-rip”时,我的年纪约为325,但是由于某种原因,尽管每次敲击都跟着“好,这绝对是最佳结果”。击中250是任意的,因为它是第一个击败253的人,所以即使我仍然说“好的,这绝对是最佳结果”,但仍有很多需要优化。
Nicholas Pipitone

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

这只是本书中代码从C语言到APL的一种转换:Brian W. Kerninghan和Dennis M. Ritchie的“ Linguaggio C”章节5.12。我不知道如何减少所有这些,因为我不了解100%的代码,并且因为我对APL不太了解。我认为只允许150个嵌套的括号'('')'错误返回一个带有一个负值的字符串或字符串说明(如果一切正常)。即使减少了字符数,这似乎也不比另一个版本好,因为另一个可以更好地看到错误。一些测试:

  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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.