Arka fon
C'deki değişken bildirim ifadesi üç bölümden oluşur: değişkenin adı , temel türü ve tür değiştirici (ler) .
Üç tür tip değiştirici vardır:
- İşaretçi
*
(önek) - Dizi
[N]
(postfix) - İşlev
()
(postfix)- Parenler içindeki işlev argümanlarının bir listesini belirleyebilirsiniz, ancak bu zorluğun uğruna, onu görmezden gelelim ve kullanalım
()
(teknik olarak "işlevin herhangi bir argümanı alabileceği" anlamına gelir).
- Parenler içindeki işlev argümanlarının bir listesini belirleyebilirsiniz, ancak bu zorluğun uğruna, onu görmezden gelelim ve kullanalım
Ve notasyonları okumanın bir yolu şöyledir:
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
Catch, dizilerin dizisi veya işlev işaretçiler dizisi veya işaretçi dizisine işaretçi dizisi gibi daha karmaşık bir tür oluşturmak için bunların hepsini karıştırabiliriz :
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
Bu karmaşık ifadeleri nasıl okudum?
- Değişken isminden başlayın.
(name) is ...
- En yüksek önceliğe sahip değiştiriciyi seçin.
- Oku onu:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- Değiştiriciler tükenene kadar 2 ve 3'ü tekrarlayın.
- Son olarak, baz türünü okuyun.
... (base type).
C'de, postfix operatörleri prefix operatörlerine göre önceliklidir ve type değiştiricileri istisna değildir. Bu nedenle, []
ve ()
bağlama, sonra *
. Bir çift ebeveynin içindeki herhangi bir şey (...)
(işlev operatörü ile karıştırılmaması gereken) ilk önce dışarıdaki herhangi bir şeyin üzerine bağlanır.
Resimli örnek:
int (*fptrs[10])();
fptrs fptrs is ...
[10] array of 10 ... // [] takes precedence over *
(* ) pointer to ...
() function returning ...
int int
Görev
C ile yazılmış bir değişken bildirim ifadesi satırı göz önüne alındığında, yukarıda gösterilen yöntemi kullanarak satırı tanımlayan İngilizce ifadeyi çıktı alın.
Giriş
Giriş, tek bir temel tip, tek bir değişken adı, sıfır veya daha fazla tip değiştirici ve bitiş noktalı virgül içeren tek bir C ifadesidir. Yukarıda belirtilen tüm sözdizimi öğelerini uygulamalısınız, artı:
- Hem temel tür hem de değişken adı normal ifadeyle eşleşir
[A-Za-z_][A-Za-z0-9_]*
. - Teorik olarak, programınız sınırsız sayıda tür değiştiriciyi desteklemelidir.
Diğer C sözdizimi öğelerini aşağıdaki şekillerde basitleştirebilirsiniz (tam uygulama da açığız):
- Baz türü her zaman tek bir kelime, örneğin
int
,float
,uint32_t
,myStruct
. Gibi bir şeyunsigned long long
test edilmeyecek. - Dizi açıklamasında için
[N]
, sayıN
her zaman tek pozitif tamsayı 10. şeyler gibi baz yazılmış olacakint a[5+5]
,int a[SIZE]
ya daint a[0x0f]
test edilmeyecektir. - İşlev gösterimi için
()
, yukarıda belirtildiği gibi hiçbir parametre belirtilmeyecektir. - Beyaz alanlar için, yalnızca boşluk karakteri
0x20
kullanılacaktır. Programınızı beyaz boşlukların belirli kullanımlarıyla sınırlayabilirsiniz; örneğin,- Temel türden sonra yalnızca bir boşluk kullanın
- Jetonlar arasında her yerde bir boşluk kullanın
- Bununla birlikte, bir simge ayırıcı olmaktan daha fazla bilgi iletmek için iki veya daha fazla ardışık boşluk kullanamazsınız.
C sözdizimine göre, aşağıdaki üç kombinasyon geçersizdir ve bu nedenle test edilmeyecektir:
f()()
İşlev döndürme işlevif()[]
İşlev dönen dizia[]()
N fonksiyonlarının dizisi
C geliştiricileri bunun yerine bu eşdeğer formları kullanır (ve bunların tümü test durumlarında ele alınmıştır):
(*f())()
İşlev gösteren gösterici işlevi döndürüyor*f()
İşlev , ilk göstericiye dönen gösterici(*a[])()
Çalışacak N işaretçi dizisi
Çıktı
Çıktı, tek bir İngilizce cümledir. İngilizce gramerine (örneğin a, an, the
, tekil / çoğul formlar ve bitiş noktası (dönem) kullanımı gibi) ingilizce dilbilgisine saygı göstermeniz gerekmez (ancak dilerseniz ). Her kelime bir veya daha fazla boşlukla (boşluk, sekme, yeni satır) ayrılmalıdır, böylece sonuç insan tarafından okunabilir.
Yine, işte dönüşüm süreci:
- Değişken isminden başlayın.
(name) is ...
- En yüksek önceliğe sahip değiştiriciyi seçin.
- Oku onu:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- Değiştiriciler tükenene kadar 2 ve 3'ü tekrarlayın.
- Son olarak, baz türünü okuyun.
... (base type).
Test durumları
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 */
Puanlama ve Kazanma kriteri
Bu bir kod golf mücadelesi. En küçük bayt sayısına sahip olan program kazanır.
int arr[3][4];
olduğu an array of 3 arrays of 4 ints
(dediğin gibi) veya an array of 4 arrays of 3 ints
?
;
satırın sonunda mı içeriyor ?