sfondo
L'istruzione di dichiarazione delle variabili in C è composta da tre parti: il nome della variabile, il suo tipo di base e i modificatori del tipo .
Esistono tre tipi di modificatori di tipo:
- Puntatore
*
(prefisso) - Array
[N]
(postfix) - Funzione
()
(postfisso)- Puoi specificare un elenco di argomenti di funzione all'interno delle parentesi, ma per il bene di questa sfida, ignoriamolo e usiamolo
()
(che tecnicamente significa "la funzione può accettare qualsiasi tipo di argomento").
- Puoi specificare un elenco di argomenti di funzione all'interno delle parentesi, ma per il bene di questa sfida, ignoriamolo e usiamolo
E un modo per leggere le notazioni è il seguente:
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
Il problema è che possiamo mescolare tutti questi per formare un tipo più complicato, come un array di array o un array di puntatori a funzione o un puntatore a un array di puntatori :
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
Come ho letto queste dichiarazioni complicate?
- Inizia dal nome della variabile.
(name) is ...
- Seleziona il modificatore con la precedenza più alta.
- Leggilo:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- Ripeti 2 e 3 fino ad esaurimento dei modificatori.
- Infine, leggi il tipo di base.
... (base type).
In C, gli operatori postfix hanno la precedenza sugli operatori prefissi e i modificatori di tipo non fanno eccezione. Pertanto, []
e ()
associare prima, quindi *
. Qualsiasi cosa all'interno di una coppia di parentesi (...)
(da non confondere con l'operatore di funzione) si lega prima di tutto a qualsiasi cosa all'esterno.
Esempio illustrato:
int (*fptrs[10])();
fptrs fptrs is ...
[10] array of 10 ... // [] takes precedence over *
(* ) pointer to ...
() function returning ...
int int
Compito
Data una riga di dichiarazione di dichiarazione variabile scritta in C, genera l'espressione inglese che descrive la riga, usando il metodo mostrato sopra.
Ingresso
L'input è una singola istruzione C che include un singolo tipo di base, un singolo nome di variabile, zero o più modificatori di tipo e il punto e virgola finale. Devi implementare tutti gli elementi di sintassi descritti sopra, oltre a:
- Sia il tipo di base che il nome della variabile corrispondono all'espressione regolare
[A-Za-z_][A-Za-z0-9_]*
. - Teoricamente, il tuo programma dovrebbe supportare un numero illimitato di modificatori di tipo.
È possibile semplificare altri elementi della sintassi C nei modi seguenti (è gradita anche l'implementazione completa):
- Il tipo base è sempre una sola parola, per esempio
int
,float
,uint32_t
,myStruct
. Qualcosa del genereunsigned long long
non verrà testato. - Per la notazione di matrice
[N]
, il numeroN
sarà sempre un unico numero intero positivo scritto in base 10. I cose similiint a[5+5]
,int a[SIZE]
oint a[0x0f]
non sarà testato. - Per la notazione della funzione
()
, nessun parametro verrà specificato affatto, come indicato sopra. - Per gli spazi bianchi,
0x20
verrà utilizzato solo il carattere spazio . È possibile limitare il programma all'utilizzo specifico di spazi bianchi, ad es- Utilizzare solo uno spazio dopo il tipo di base
- Usa uno spazio ovunque tra i token
- Tuttavia, non è possibile utilizzare due o più spazi consecutivi per trasmettere più informazioni che essere un separatore di token.
Secondo la sintassi C, le seguenti tre combinazioni non sono valide e quindi non verranno testate:
f()()
Funzione di ritorno alla funzionef()[]
Array di ritorno funzionia[]()
Matrice di N funzioni
Gli sviluppatori C usano invece questi moduli equivalenti (e tutti questi sono trattati nei casi di test):
(*f())()
Funzione che restituisce il puntatore alla funzione*f()
Funzione che restituisce il puntatore al primo elemento dell'array(*a[])()
Matrice di N puntatori per funzionare
Produzione
L'output è una singola frase inglese. Non è necessario (ma è possibile se lo si desidera) rispettare la grammatica inglese, ad esempio l'uso di a, an, the
forme singolari / plurali e il punto finale (punto). Ogni parola deve essere separata da uno o più spazi bianchi (spazio, tabulazione, nuova riga) in modo che il risultato sia leggibile dall'uomo.
Ancora una volta, ecco il processo di conversione:
- Inizia dal nome della variabile.
(name) is ...
- Seleziona il modificatore con la precedenza più alta.
- Leggilo:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- Ripeti 2 e 3 fino ad esaurimento dei modificatori.
- Infine, leggi il tipo di base.
... (base type).
Casi 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 */
Punteggio e criterio di vincita
Questa è una sfida di code-golf . Vince il programma con il minor numero di byte.
int arr[3][4];
è an array of 3 arrays of 4 ints
(come dici tu), oppure an array of 4 arrays of 3 ints
?
sizeof(arr[0]) == sizeof(int[4])
, quindi un elemento di arr
contiene quattro int
s.
;
alla fine della riga?