Hintergrund
Die Variablendeklarationsanweisung in C besteht aus drei Teilen: dem Namen der Variablen, ihrem Basistyp und den Typmodifikatoren .
Es gibt drei Arten von Typmodifikatoren:
- Zeiger
*
(Präfix) - Array
[N]
(Postfix) - Funktion
()
(Postfix)- Sie können eine Liste von Funktionsargumenten in den Parens angeben. Um diese Herausforderung zu bewältigen, ignorieren wir sie und verwenden einfach
()
(was technisch bedeutet, dass die Funktion alle Arten von Argumenten annehmen kann).
- Sie können eine Liste von Funktionsargumenten in den Parens angeben. Um diese Herausforderung zu bewältigen, ignorieren wir sie und verwenden einfach
Und ein Weg, um die Notationen auszulesen, ist wie folgt:
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
Der Haken ist, dass wir all diese Elemente mischen können, um einen komplizierteren Typ zu bilden, beispielsweise ein Array von Arrays oder ein Array von Funktionszeigern oder einen Zeiger auf ein Array von Zeigern :
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
Wie habe ich diese komplizierten Aussagen gelesen?
- Beginnen Sie mit dem Variablennamen.
(name) is ...
- Wählen Sie den Modifikator mit der höchsten Priorität.
- Lies es:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- Wiederholen Sie 2 und 3, bis die Modifikatoren erschöpft sind.
- Lesen Sie abschließend den Basistyp.
... (base type).
In C haben Postfix-Operatoren Vorrang vor Präfix-Operatoren, und Typmodifikatoren sind keine Ausnahme. Also, []
und dann erst ()
binden *
. Alles innerhalb eines Paares von Parens (...)
(nicht zu verwechseln mit dem Funktionsoperator) wird zuerst über alles außerhalb gebunden.
Illustriertes Beispiel:
int (*fptrs[10])();
fptrs fptrs is ...
[10] array of 10 ... // [] takes precedence over *
(* ) pointer to ...
() function returning ...
int int
Aufgabe
Geben Sie bei einer in C geschriebenen Zeile der Variablendeklarationsanweisung den englischen Ausdruck aus, der die Zeile beschreibt, und verwenden Sie dabei die oben gezeigte Methode.
Eingang
Die Eingabe ist eine einzelne C-Anweisung, die einen einzelnen Basistyp, einen einzelnen Variablennamen, null oder mehr Typmodifizierer und das abschließende Semikolon enthält. Sie müssen alle oben beschriebenen Syntaxelemente implementieren, plus:
- Sowohl der Basistyp als auch der Variablenname stimmen mit dem regulären Ausdruck überein
[A-Za-z_][A-Za-z0-9_]*
. - Theoretisch sollte Ihr Programm eine unbegrenzte Anzahl von Typmodifikatoren unterstützen.
Sie können andere C-Syntaxelemente auf folgende Weise vereinfachen (eine vollständige Implementierung ist ebenfalls willkommen):
- Der Basistyp ist immer ein einziges Wort, zum Beispiel
int
,float
,uint32_t
,myStruct
. So etwasunsigned long long
wird nicht getestet. - Für die Array - Notation
[N]
, die ZahlN
wird immer eine einzige positive ganze Zahl in der Basis geschrieben sein 10. Dinge wieint a[5+5]
,int a[SIZE]
oderint a[0x0f]
nicht getestet werden. - Für die Funktionsnotation
()
werden, wie oben ausgeführt, überhaupt keine Parameter angegeben. - Bei Leerzeichen wird nur das Leerzeichen
0x20
verwendet. Sie können Ihr Programm auf die Verwendung von Leerzeichen beschränken, z- Verwenden Sie nach dem Basistyp nur ein Leerzeichen
- Verwenden Sie überall zwischen Token ein Leerzeichen
- Sie können jedoch nicht zwei oder mehr aufeinanderfolgende Leerzeichen verwenden, um mehr Informationen zu übermitteln, als ein Tokentrennzeichen zu sein.
Laut C-Syntax sind die folgenden drei Kombinationen ungültig und werden daher nicht getestet:
f()()
Funktion, die Funktion zurückgibtf()[]
Array, das die Funktion zurückgibta[]()
Array von N Funktionen
C-Entwickler verwenden stattdessen diese äquivalenten Formulare (und alle diese werden in den Testfällen behandelt):
(*f())()
Funktion, die den Zeiger auf die Funktion zurückgibt*f()
Funktion, die den Zeiger auf das erste Element des Arrays zurückgibt(*a[])()
Array von N Zeigern, die funktionieren sollen
Ausgabe
Die Ausgabe ist ein einzelner englischer Satz. Sie müssen die englische Grammatik nicht respektieren (können dies aber tun), z. B. die Verwendung von a, an, the
Singular- / Pluralformen und den Endpunkt (Punkt). Jedes Wort sollte durch ein oder mehrere Leerzeichen (Leerzeichen, Tabulator, Zeilenvorschub) getrennt sein, damit das Ergebnis für den Menschen lesbar ist.
Hier ist wieder der Konvertierungsprozess:
- Beginnen Sie mit dem Variablennamen.
(name) is ...
- Wählen Sie den Modifikator mit der höchsten Priorität.
- Lies es:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- Wiederholen Sie 2 und 3, bis die Modifikatoren erschöpft sind.
- Lesen Sie abschließend den Basistyp.
... (base type).
Testfälle
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 */
Scoring & Winning-Kriterium
Dies ist eine Code-Golf- Herausforderung. Das Programm mit der geringsten Anzahl von Bytes gewinnt.
int arr[3][4];
ist an array of 3 arrays of 4 ints
(wie du sagst), oder an array of 4 arrays of 3 ints
?
sizeof(arr[0]) == sizeof(int[4])
, so arr
enthält ein Gegenstand von vier int
s.
;
am Ende der Zeile?