Фон
Заява змінної декларації в C складається з трьох частин: назва змінної, її базовий тип та модифікатор (и) типу .
Існує три види модифікаторів типу:
- Вказівник
*(префікс) - Масив
[N](постфікс) - Функція
()(постфікс)- Ви можете вказати список аргументів функції всередині паролів, але заради цього виклику давайте ігноруємо його та просто використовуємо
()(що технічно означає "функція може приймати будь-які аргументи").
- Ви можете вказати список аргументів функції всередині паролів, але заради цього виклику давайте ігноруємо його та просто використовуємо
А спосіб прочитати нотації такий:
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
Проблема полягає в тому, що ми можемо змішати все це для формування більш складного типу, такого як масив масивів або масив функціональних покажчиків або вказівник на масив покажчиків :
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
Як я прочитав ці складні заяви?
- Почніть з назви змінної.
(name) is ... - Виберіть модифікатор з найвищим пріоритетом.
- Читати:
* -> pointer to ...[N] -> array of N ...() -> function returning ...
- Повторюйте 2 і 3, поки модифікатори не вичерпані.
- Нарешті, прочитайте базовий тип.
... (base type).
У C оператори Postfix мають перевагу над префіксними операторами, і модифікатори типу не є винятком. Тому []і ()зв’яжіть спочатку, потім *. Все, що знаходиться всередині пари паронів (...)(не плутати з оператором функції), пов'язує спочатку над чим-небудь зовнішнім.
Ілюстрований приклад:
int (*fptrs[10])();
fptrs fptrs is ...
[10] array of 10 ... // [] takes precedence over *
(* ) pointer to ...
() function returning ...
int int
Завдання
З огляду на рядок заяви заяви про змінну, записану на C, виведіть англійський вираз, який описує рядок, використовуючи метод, показаний вище.
Вхідні дані
Вхід - це єдине твердження C, яке включає єдиний базовий тип, одне ім'я змінної, модифікатори нуля або більше типів і кінцеву крапку з комою. Ви повинні реалізувати всі елементи синтаксису, описані вище, плюс:
- І базовий тип, і назва змінної відповідають регулярному виразу
[A-Za-z_][A-Za-z0-9_]*. - Теоретично ваша програма повинна підтримувати необмежену кількість модифікаторів типів.
Ви можете спростити інші елементи синтаксису С наступними способами (також можлива повна реалізація):
- Базовий тип завжди одне слово, наприклад
int,float,uint32_t,myStruct. Щось подібнеunsigned long longне буде перевірено. - Для позначення масиву
[N], числоNзавжди буде одне ціле позитивне число записується в базі 10. Такі речі , якint a[5+5],int a[SIZE]абоint a[0x0f]НЕ будуть перевірені. - Для позначення функції
(), параметри взагалі не будуть вказані, як зазначено вище. - Для пробілів
0x20буде використовуватися лише пробіл . Ви можете обмежити свою програму конкретним використанням пробілів, наприклад- Використовуйте лише один пробіл після базового типу
- Використовуйте пробіл скрізь між маркерами
- Однак ви не можете використовувати два чи більше послідовних пробілів, щоб передати більше інформації, ніж бути роздільником токенів.
Відповідно до синтаксису C, наступні три комбінації є недійсними, тому вони не будуть перевірені:
f()()Функція повернення функціїf()[]Функція повертає масивa[]()Масив N функцій
Розробники C натомість використовують ці еквівалентні форми (і всі вони охоплені у тестових випадках):
(*f())()Функція повертає вказівник на функцію*f()Функція, що повертає вказівник на перший елемент масиву(*a[])()Для функціонування масив N покажчиків
Вихідні дані
Вихід - єдине англійське речення. Вам не потрібно (але ви можете, якщо хочете) поважати граматику англійської мови, наприклад, використання форм a, an, theоднини / множини та закінчувальну крапку (період). Кожне слово має бути розділене одним або декількома пробілами (пробіл, вкладка, новий рядок), щоб результат був зрозумілий людині.
Знову ось процес перетворення:
- Почніть з назви змінної.
(name) is ... - Виберіть модифікатор з найвищим пріоритетом.
- Читати:
* -> pointer to ...[N] -> array of N ...() -> function returning ...
- Повторюйте 2 і 3, поки модифікатори не вичерпані.
- Нарешті, прочитайте базовий тип.
... (base type).
Тестові справи
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 */
Критерій оцінювання та виграшу
Це проблема з кодовим гольфом . Виграє програма з найменшою кількістю байтів.
int arr[3][4];є an array of 3 arrays of 4 ints(як ви кажете), або an array of 4 arrays of 3 ints?
sizeof(arr[0]) == sizeof(int[4]), тому елемент arrмістить чотири intс.
;в кінці рядка?