Fondo
La declaración de declaración de variables en C consta de tres partes: el nombre de la variable, su tipo base y los modificadores de tipo .
Hay tres tipos de modificadores de tipo:
- Puntero
*
(prefijo) - Matriz
[N]
(postfix) - Función
()
(postfix)- Puede especificar una lista de argumentos de función dentro de los elementos parentales, pero en aras de este desafío, ignorémoslo y solo usemos
()
(lo que técnicamente significa "la función puede tomar cualquier tipo de argumento").
- Puede especificar una lista de argumentos de función dentro de los elementos parentales, pero en aras de este desafío, ignorémoslo y solo usemos
Y una forma de leer las anotaciones es la siguiente:
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
El problema es que podemos mezclar todo esto para formar un tipo más complicado, como una matriz de matrices o una matriz de punteros de función o un puntero a una matriz de punteros :
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
¿Cómo leí estas complicadas declaraciones?
- Comience desde el nombre de la variable.
(name) is ...
- Seleccione el modificador con la mayor precedencia.
- Léelo:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- Repita 2 y 3 hasta que los modificadores estén agotados.
- Finalmente, lea el tipo base.
... (base type).
En C, los operadores de postfix tienen prioridad sobre los operadores de prefijo, y los modificadores de tipo no son una excepción. Por lo tanto, []
y ()
atar primero, luego *
. Cualquier cosa dentro de un par de parens (...)
(que no debe confundirse con el operador de función) se une primero sobre cualquier cosa fuera.
Ejemplo ilustrado:
int (*fptrs[10])();
fptrs fptrs is ...
[10] array of 10 ... // [] takes precedence over *
(* ) pointer to ...
() function returning ...
int int
Tarea
Dada una línea de declaración de declaración de variables escrita en C, genera la expresión en inglés que describe la línea, utilizando el método que se muestra arriba.
Entrada
La entrada es una declaración C única que incluye un tipo base único, un nombre de variable único, cero o más modificadores de tipo y el punto y coma final. Tiene que implementar todos los elementos de sintaxis cubiertos anteriormente, además de:
- Tanto el tipo base como el nombre de la variable coinciden con la expresión regular
[A-Za-z_][A-Za-z0-9_]*
. - Teóricamente, su programa debería admitir un número ilimitado de modificadores de tipo.
Puede simplificar otros elementos de sintaxis de C de las siguientes maneras (la implementación completa también es bienvenida):
- El tipo de base es siempre una única palabra, por ejemplo
int
,float
,uint32_t
,myStruct
. Algo asíunsigned long long
no será probado. - Para la notación de matriz
[N]
, el númeroN
será siempre un solo número entero positivo escrito en base 10. cosas comoint a[5+5]
,int a[SIZE]
oint a[0x0f]
no se ensayó. - Para la notación de función
()
, no se especificarán parámetros, como se señaló anteriormente. - Para espacios en blanco, solo se
0x20
usará el carácter de espacio . Puede restringir su programa al uso específico de espacios en blanco, p. Ej.- Use solo un espacio después del tipo base
- Usa un espacio en todas partes entre fichas
- Sin embargo, no puede usar dos o más espacios consecutivos para transmitir más información que ser un separador de tokens.
Según la sintaxis de C, las siguientes tres combinaciones no son válidas y, por lo tanto, no se probarán:
f()()
Función función de retornof()[]
Función que devuelve la matriza[]()
Matriz de funciones N
Los desarrolladores de C utilizan estos formularios equivalentes (y todos estos están cubiertos en los casos de prueba):
(*f())()
Función que devuelve el puntero a la función*f()
Función que devuelve el puntero al primer elemento de la matriz(*a[])()
Matriz de N punteros para funcionar
Salida
El resultado es una sola oración en inglés. No es necesario (pero puede hacerlo si lo desea) respetar la gramática inglesa, por ejemplo, el uso de a, an, the
formas singulares / plurales y el punto final (punto). Cada palabra debe estar separada por uno o más espacios en blanco (espacio, tabulación, nueva línea) para que el resultado sea legible para los humanos.
Nuevamente, aquí está el proceso de conversión:
- Comience desde el nombre de la variable.
(name) is ...
- Seleccione el modificador con la mayor precedencia.
- Léelo:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- Repita 2 y 3 hasta que los modificadores estén agotados.
- Finalmente, lea el tipo base.
... (base type).
Casos de prueba
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 */
Criterio de puntuación y ganador
Este es un desafío de código de golf . El programa con el menor número de bytes gana.
int arr[3][4];
es an array of 3 arrays of 4 ints
(como dices) o an array of 4 arrays of 3 ints
?
sizeof(arr[0]) == sizeof(int[4])
, por lo que un elemento de arr
contiene cuatro int
s.
;
al final de la línea?