C değişkeni bildirimini okuyun


41

Arka fon

C'deki değişken bildirim ifadesi üç bölümden oluşur: değişkenin adı , temel türü ve tür değiştirici (ler) .

Üç tür tip değiştirici vardır:

  • İşaretçi *(önek)
  • Dizi [N](postfix)
  • İşlev ()(postfix)
    • Parenler içindeki işlev argümanlarının bir listesini belirleyebilirsiniz, ancak bu zorluğun uğruna, onu görmezden gelelim ve kullanalım ()(teknik olarak "işlevin herhangi bir argümanı alabileceği" anlamına gelir).

Ve notasyonları okumanın bir yolu şöyledir:

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

Catch, dizilerin dizisi veya işlev işaretçiler dizisi veya işaretçi dizisine işaretçi dizisi gibi daha karmaşık bir tür oluşturmak için bunların hepsini karıştırabiliriz :

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

Bu karmaşık ifadeleri nasıl okudum?

  1. Değişken isminden başlayın. (name) is ...
  2. En yüksek önceliğe sahip değiştiriciyi seçin.
  3. Oku onu:
    • * -> pointer to ...
    • [N] -> array of N ...
    • () -> function returning ...
  4. Değiştiriciler tükenene kadar 2 ve 3'ü tekrarlayın.
  5. Son olarak, baz türünü okuyun. ... (base type).

C'de, postfix operatörleri prefix operatörlerine göre önceliklidir ve type değiştiricileri istisna değildir. Bu nedenle, []ve ()bağlama, sonra *. Bir çift ebeveynin içindeki herhangi bir şey (...)(işlev operatörü ile karıştırılmaması gereken) ilk önce dışarıdaki herhangi bir şeyin üzerine bağlanır.

Resimli örnek:

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

Görev

C ile yazılmış bir değişken bildirim ifadesi satırı göz önüne alındığında, yukarıda gösterilen yöntemi kullanarak satırı tanımlayan İngilizce ifadeyi çıktı alın.

Giriş

Giriş, tek bir temel tip, tek bir değişken adı, sıfır veya daha fazla tip değiştirici ve bitiş noktalı virgül içeren tek bir C ifadesidir. Yukarıda belirtilen tüm sözdizimi öğelerini uygulamalısınız, artı:

  • Hem temel tür hem de değişken adı normal ifadeyle eşleşir [A-Za-z_][A-Za-z0-9_]*.
  • Teorik olarak, programınız sınırsız sayıda tür değiştiriciyi desteklemelidir.

Diğer C sözdizimi öğelerini aşağıdaki şekillerde basitleştirebilirsiniz (tam uygulama da açığız):

  • Baz türü her zaman tek bir kelime, örneğin int, float, uint32_t, myStruct. Gibi bir şey unsigned long longtest edilmeyecek.
  • Dizi açıklamasında için [N], sayı Nher zaman tek pozitif tamsayı 10. şeyler gibi baz yazılmış olacak int a[5+5], int a[SIZE]ya da int a[0x0f]test edilmeyecektir.
  • İşlev gösterimi için (), yukarıda belirtildiği gibi hiçbir parametre belirtilmeyecektir.
  • Beyaz alanlar için, yalnızca boşluk karakteri 0x20kullanılacaktır. Programınızı beyaz boşlukların belirli kullanımlarıyla sınırlayabilirsiniz; örneğin,
    • Temel türden sonra yalnızca bir boşluk kullanın
    • Jetonlar arasında her yerde bir boşluk kullanın
  • Bununla birlikte, bir simge ayırıcı olmaktan daha fazla bilgi iletmek için iki veya daha fazla ardışık boşluk kullanamazsınız.

C sözdizimine göre, aşağıdaki üç kombinasyon geçersizdir ve bu nedenle test edilmeyecektir:

  • f()() İşlev döndürme işlevi
  • f()[] İşlev dönen dizi
  • a[]() N fonksiyonlarının dizisi

C geliştiricileri bunun yerine bu eşdeğer formları kullanır (ve bunların tümü test durumlarında ele alınmıştır):

  • (*f())()İşlev gösteren gösterici işlevi döndürüyor
  • *f()İşlev , ilk göstericiye dönen gösterici
  • (*a[])()Çalışacak N işaretçi dizisi

Çıktı

Çıktı, tek bir İngilizce cümledir. İngilizce gramerine (örneğin a, an, the, tekil / çoğul formlar ve bitiş noktası (dönem) kullanımı gibi) ingilizce dilbilgisine saygı göstermeniz gerekmez (ancak dilerseniz ). Her kelime bir veya daha fazla boşlukla (boşluk, sekme, yeni satır) ayrılmalıdır, böylece sonuç insan tarafından okunabilir.

Yine, işte dönüşüm süreci:

  1. Değişken isminden başlayın. (name) is ...
  2. En yüksek önceliğe sahip değiştiriciyi seçin.
  3. Oku onu:
    • * -> pointer to ...
    • [N] -> array of N ...
    • () -> function returning ...
  4. Değiştiriciler tükenene kadar 2 ve 3'ü tekrarlayın.
  5. Son olarak, baz türünü okuyun. ... (base type).

Test durumları

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

Puanlama ve Kazanma kriteri

Bu bir mücadelesi. En küçük bayt sayısına sahip olan program kazanır.



int arr[3][4];olduğu an array of 3 arrays of 4 ints(dediğin gibi) veya an array of 4 arrays of 3 ints?
Charlie

1
@Charlie Eski doğru. sizeof(arr[0]) == sizeof(int[4]), yani bir öğe arrdört ints içerir .
Bubbler

1
Giriş ;satırın sonunda mı içeriyor ?
Black Owl Kai

2
@KamilDrakari İkincisi. "fonksiyonuna işaretçi dizisi" C'de mükemmel geçerli olan "işaretçi dizisi", esas olarak
Bubbler

Yanıtlar:


17

Python 3 , 331 312 294 261 240 bayt

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)

Çevrimiçi deneyin!

-19 bayt python 2'ye geçerek ve sınıf tanımını bir exec

Dan regex değiştirerek -18 bayt [a-zA-Z_][a-zA-Z0-9_]*için \\w+Kevin Cruijssen sayesinde

-33 byte bazı sınıf tanım sihirlerini çalıştırarak ve str kullanarak, Lynn sayesinde tekrar python 3'e geçerek

İnfmagic2047 sayesinde çoklu regexleri bir araya getirerek -21 bayt

Girişte yalnızca bir boşluk olmasını gerektirir (tür ile ifade arasında).

Bence bu soruna oldukça özel bir yaklaşım. Bu çoğunlukla Python'un kendisi gibi dizeleri değerlendirebilir (**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5])ve işlev çağrıları, dizi dizinleri ve işaretçilerin doğru sırasını alabilir - ve kullanıcının bunları aşırı yükleyebileceği gerçeğini kullanır .


1
Güzel yaklaşım, benden +1! Birkaç byte tasarruf [a-zA-Z_][A-Za-z0-9_]*etmek [a-zA-Z_]\\w*için golf oynayabilirsiniz . EDIT: Aslında, \\w+yerine kullanabileceğini düşünüyorum [a-zA-Z_][A-Za-z0-9_]*.
Kevin Cruijssen

Bu yaklaşımı seviyorum :) burada 253 baytta
Lynn

1
İyi bir noktaya değindin. 261 o zaman.
Lynn

1
Sen kullanabilirsiniz [0]yerine .group()Python 3.6 beri.
infmagic2047


13

Retina 0.8.2 , 142 138 128 117 bayt

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

Çevrimiçi deneyin! Link, test durumlarını içerir. Daha iyi dilbilgisi . Düzenleme: @ DLosc's Pip çözümünü taşıyarak 10 21 bayt kurtardı. Açıklama:

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

Türü sonuna kadar kaydırın ve bildirimin geri kalanını ()bir dış kısım içerecek şekilde sarın *.

\(\)
 function returning

Herhangi bir işlevi işleyin.

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

Herhangi bir diziyi işleyin.

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

Herhangi bir işaretçiyi braketlerinin ucuna taşıyın ve tekrar tekrar en dıştaki braket grubundan çalışarak braketleri silin.

\*
 pointer to

İşaretçileri işle.

1` 
 is 

Yerleştirin is.


7

Java 11, 469 467 463 450 bayt

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

Çevrimiçi deneyin.

Açıklama:

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)

Yedekli parantez ile test durumunda başarısız olur.
Bubbler

@ Bubler Ah, bu yeni test davası fark etmedi. Neyse ki bu kolay bir düzeltme.
Kevin Cruijssen

6

Bash + cdecl + GNU sed, 180

cdeclburada ihtiyaç duyulanın çoğunu yapan saygın bir Unix aracıdır, ancak G / Ç gereksinimlerini eşleştirmek için bazı sedişlem öncesi ve işlem sonrası işlemlerin yapılması gerekir:

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'
  • Dilbilgisini düzeltmek için hiçbir girişimde bulunulmaz.

sed Ön işleme:

  • s/^/explain struct /- Her satırın başına "açıklamayı" ekleyin
  • s/struct (int|char double|float|void) /\1 /- structC dili türleriyle uğraşırken kaldır
  • s/\bfunc/_func/g - "func", cdecl tarafından bir anahtar kelime olarak tanınır - bunu bastırın

işleme sonrası:

  • s/^declare // - satır başında "bildir" i kaldır
  • s/as/is/ - açıklayıcı
  • s/struct //g - tüm "struct" anahtar kelimeleri kaldır
  • s/([0-9]+) of/of \1/g - "/" nın doğru sıralanması
  • s/\b_func/func/g - ön işleme işleminde değiştirilen "_func" öğelerini geri alın

Eylemde:

$ < 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/gTam funcdeğiştirmenin baytını yapmak ve kaydetmek yeterli olur mu?
DLosc

bekle gerçek bir yardımcı program mı? Her zaman web sitesinin adı olduğunu düşündüm
phuclv

@phuclv cdecl gerçek bir yardımcı programdır ve C bildirimlerini kontrol etmek için gerçekten yararlıdır.
Patricia Shanahan


Bir değişken as(+4 bayt düzeltmek için boşluklar) adlı bir değişken için başarısız . Erişimim yok cdeclancak 64 byte kullanarak tasarruf edebileceğinizi düşünüyorum 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

Pip -s , 152 150 148 139 137 126 125 123 bayt

Üçüncü yaklaşım!

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

Beyanı komut satırı girişi olarak alır. Çevrimiçi deneyin!

açıklama

Kod üç bölümden oluşmaktadır: fonksiyonların ve dizilerin ilk kurulum ve kullanımı; parantez ve işaretçilerle ilgilenen bir döngü; ve son bir düzenleme.

Kurulum, fonksiyonlar ve diziler

Biz bütün deklarasyon biz değiştirmek, böylece (bu döngü daha sonra yardımcı olur) parantez içinde istediğiniz type ...;içine type (...). Ardından, fonksiyonların ve dizilerin tanımlarıyla yeniden sıralama yapılmadığını gözlemleyin, bu nedenle ilk olarak tüm bu değiştirmeleri nihai çıktıyı etkilemeden gerçekleştirebiliriz.

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"

Özgün girişimiz öyleyse float *((*p()))[16];, şimdi sahip olduk float (*((*p function returning)) array of 16).

Parantez ve işaretçiler

En dıştaki parantez çiftini ve hemen açılış parenin içinde bulunan yıldızları değiştirerek bir döngü çalıştırırız.

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
    }

Örnek adımlar:

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

Temizlemek

Kalan tek şey türü sonuna kadar taşımak ve "is" eklemek:

{[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)

Gibi tanımları için int x;, bu yaklaşım meydan okuma tarafından izin verilen fazladan bir boşluk ile sonuçlanacaktır.


5

JavaScript (ES6), 316 ... 268 253 bayt

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`!`)

Çevrimiçi deneyin!

Yorumlananlar

Yardımcı işlevi

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

Ana bölüm

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 '!'

Neden [...s.split`()`.join`!`]onun yerine kullanıldığını merak ediyordum [...s.replace('()','!')], ama tam olarak aynı byte-count olduğunu anladım .. :)
Kevin Cruijssen

@KevinCruijssen Birincil nedeni, s.replace('()','!')sadece ilk oluşumun yerini almasıdır .
Arnauld

Ah, elbette. JS'yi unuttum yerine Java ile aynı değildir. Java'da .replacetüm oluşumları .replaceAlldeğiştirir ve tüm olayları regex etkin olarak değiştirir. Her zaman isimlendirmenin Java'daki bu iki yöntem için oldukça kötü olduğunu düşünmüştüm, çünkü onları .replaceAllve .regexReplaceAllya da bu satırlar boyunca bir şeyleri söyleyecektim, ama kodgolf için sanırım .replaceve kısaydı .replaceAll.
Kevin Cruijssen

1
BTW, ~cevabımın ilk versiyonunu yayınladıktan hemen sonra aynı tekniği kullandığınızı fark ettim . Sanırım büyük beyinler aynı şekilde düşünüyor. : p
Arnauld,

3

415 bayt temiz

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)

Çevrimiçi deneyin!


3

R , 225 218 bayt

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

Çevrimiçi deneyin!

Tüm programların bir kerede rahat bir şekilde test edilebilmesi için TIO işlevine dahil edilmiş tam program.

İlk olarak, formun girişini dönüştürmek için Regex kullanmak type ...name...;için ..."name is"..."type". İşlev gösterimi ()daha sonra bir öncelik önceliği birleştirme işleci ile metne dönüştürülür. Ne yazık ki, daha da değiştirmek zorunda *olan +eski bir tekli operatör olarak kabul edilebilir değil gibi. Gerisi R's tarafından evalaşırı yüklenmiş operatörlerle yapılır.


1
Akıllıca bir çözüm!
J.Doe

3

Perl 6 , 209 190 171 162 153 bayt

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

Çevrimiçi deneyin!

Özyinelemeli regex yaklaşımı. 3 bayt pahasına kaçınılabilecek bazı ekstra boşluk karakterleri üretir .

açıklama

{     # 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 Bayt [249?]

Bu 250 Bayt kullanır:

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çıklama:

Temel olarak, abelirtilmiş girdi olan bir tampondan okuyor . Değerlendirme modu tetiklenene kadar belirteçleri tampondan abir yığına sürekli olarak taşır s. Değerlendirme modunun sonek işlemleri tüketecektir (), []tampon ve daha sonra ön ek operatör tüketecektir *yığından. Değerlendirme modu, devlet bir kelimenin bulunduğu yerde olduğu zaman tetiklenir (Ya yazici ismi bulunur ve tüketilir, veya bir bitiş )bulunur ve silinir). Daha fazla önek / postek operatörü bulunamadığında değerlendirme modu devre dışı bırakılır.

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
)

NOT

Doğru şekilde "Jetonlar arasında her yerde bir boşluk kullan" seçeneğini anlarsam:

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

teknik olarak geçerlidir ve kullanır

249 Bayt

Her belirteç arasında bir boşluk olduğunu varsayalım.


2
Basit görünmesine rağmen bu beni uzun saatler aldı. Muhtemelen 350 karakterden başlayarak 5-10 byte / saat çaldı. Gerçekten de hayatım yok.
Nicholas Pipitone

2
Ben de "benim şimdiki algoritma ile optimaliteye çarptı - rip" düşündüm ben 325 hakkında idi, ama sonra nedense hala 5-10 / saat vurmak başardı her tarafından takip edilmekte tak rağmen "Tamam, bu kesinlikle optimum sonuç ". 250'ye vurmak, egemenliği 253 yenen ilk kişi olduğu için keyfi oldu, bu yüzden hala "Tamam, kesinlikle en iyi sonuç budur" dememe rağmen, hala optimize etmek için daha fazlası olabilir.
Nicholas Pipitone

1

Kırmızı , 418 410 bayt

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]]

Çevrimiçi deneyin!

Açıklama:

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), karakter 625, bayt 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

bu, C dilinden APL'ye kitaptaki koddan sadece bir geçiş: "Linguaggio C", Brian W. Kerninghan ve Dennis M. Ritchie bölüm 5.12. Bunları nasıl azalttığımı bilmiyorum çünkü bu kodu% 100 anlamadım ve APL hakkında fazla bir şey bilmediğim için… Egzersiz fonksiyonu f; Bence sadece 150 yuvalanmış parantez '(' ')' hatası için izin verilir. Diğer hataları daha iyi gördüğü için daha az karakter olsa bile, bu diğer sürümden daha iyi görünmüyor. Bazı test:

  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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.