Contexte
L'instruction de déclaration de variable en C se compose de trois parties: le nom de la variable, son type de base et le modificateur de type .
Il existe trois types de modificateurs de type:
- Pointeur
*
(préfixe) - Tableau
[N]
(postfixe) - Fonction
()
(postfixe)- Vous pouvez spécifier une liste d'arguments de fonction à l'intérieur des parenthèses, mais dans l'intérêt de ce défi, ignorons-le et utilisons-le simplement
()
(ce qui signifie techniquement que "la fonction peut prendre n'importe quel type d'argument").
- Vous pouvez spécifier une liste d'arguments de fonction à l'intérieur des parenthèses, mais dans l'intérêt de ce défi, ignorons-le et utilisons-le simplement
Et une façon de lire les notations est la suivante:
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
Le problème, c'est que nous pouvons combiner tous ces éléments pour former un type plus complexe, tel qu'un tableau de tableaux ou un tableau de pointeurs de fonction ou un pointeur sur un tableau de pointeurs :
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
Comment ai-je lu ces déclarations compliquées?
- Commencez par le nom de la variable.
(name) is ...
- Sélectionnez le modificateur avec la priorité la plus élevée.
- Lis le:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- Répétez les étapes 2 et 3 jusqu'à ce que les modificateurs soient épuisés.
- Enfin, lisez le type de base.
... (base type).
En C, les opérateurs postfixés ont priorité sur les opérateurs préfixés et les modificateurs de type ne font pas exception. Par conséquent, []
et ()
lier en premier, alors *
. Quelque chose dans une paire de parens(...)
(à ne pas confondre avec l'opérateur de la fonction) est d'abord lié à tout ce qui se trouve à l'extérieur.
Exemple illustré:
int (*fptrs[10])();
fptrs fptrs is ...
[10] array of 10 ... // [] takes precedence over *
(* ) pointer to ...
() function returning ...
int int
Tâche
Avec une ligne d'instruction de déclaration de variable écrite en C, indiquez l'expression anglaise décrivant la ligne, à l'aide de la méthode présentée ci-dessus.
Contribution
L'entrée est une instruction C unique comprenant un seul type de base, un nom de variable unique, zéro modificateur de type ou plus, ainsi que le point-virgule de fin. Vous devez implémenter tous les éléments de syntaxe décrits ci-dessus, plus:
- Le type de base et le nom de la variable correspondent à l'expression régulière
[A-Za-z_][A-Za-z0-9_]*
. - Théoriquement, votre programme devrait supporter un nombre illimité de modificateurs de type.
Vous pouvez simplifier les autres éléments de la syntaxe C des manières suivantes (une implémentation complète est également la bienvenue):
- Le type de base est toujours un seul mot, par exemple
int
,float
,uint32_t
,myStruct
. Quelque chose commeunsigned long long
ne sera pas testé. - Pour la notation de tableau
[N]
, le nombreN
sera toujours un entier positif écrit en base 10. Des choses commeint a[5+5]
,int a[SIZE]
ouint a[0x0f]
ne seront pas testées. - Pour la notation de fonction
()
, aucun paramètre ne sera spécifié, comme indiqué ci-dessus. - Pour les espaces, seul le caractère d'espace
0x20
sera utilisé. Vous pouvez limiter votre programme à une utilisation spécifique des espaces, par exemple- Utilisez un seul espace après le type de base
- Utilisez un espace partout entre les jetons
- Cependant, vous ne pouvez pas utiliser deux espaces consécutifs ou plus pour transmettre plus d'informations qu'un séparateur de jetons.
Selon la syntaxe C, les trois combinaisons suivantes ne sont pas valides et ne seront donc pas testées:
f()()
Fonction de retourf()[]
Fonction retournant un tableaua[]()
Tableau de N fonctions
Les développeurs C utilisent ces formulaires équivalents à la place (et tous sont couverts dans les cas de test):
(*f())()
Fonction retournant le pointeur à la fonction*f()
Fonction renvoyant le pointeur sur le premier élément du tableau(*a[])()
Tableau de N pointeurs pour fonctionner
Sortie
La sortie est une phrase anglaise unique. Vous n’avez pas besoin (mais vous pouvez si vous le souhaitez) de respecter la grammaire anglaise, par exemple l’utilisation dea, an, the
formes singulières / plurielles et le point de fin (point). Chaque mot doit être séparé par un ou plusieurs espaces (espaces, tabulations, nouvelles lignes) pour que le résultat soit lisible par l'homme.
Encore une fois, voici le processus de conversion:
- Commencez par le nom de la variable.
(name) is ...
- Sélectionnez le modificateur avec la priorité la plus élevée.
- Lis le:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- Répétez les étapes 2 et 3 jusqu'à ce que les modificateurs soient épuisés.
- Enfin, lisez le type de base.
... (base type).
Cas de test
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 */
Critère de notation et de gain
Ceci est un défi de code-golf . Le programme avec le plus petit nombre d'octets gagne.
int arr[3][4];
est an array of 3 arrays of 4 ints
(comme vous dites), ou an array of 4 arrays of 3 ints
?
sizeof(arr[0]) == sizeof(int[4])
, donc un élément de arr
contient quatre int
s.
;
à la fin de la ligne?