Saya tertarik. Jadi, waktu untuk mengenakan kacamata investigasi dan karena saya tidak memiliki akses ke kompiler atau bendera kompilasi saya perlu mendapatkan inventif. Juga karena tidak ada tentang kode ini masuk akal itu bukan pertanyaan ide buruk setiap asumsi.
Pertama mari kita periksa jenis sebenarnya gets
. Saya punya sedikit trik untuk itu:
template <class> struct Name;
int main() {
Name<decltype(gets)> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
Dan itu terlihat ... normal:
/tmp/613814454/Main.cpp:16:19: warning: 'gets' is deprecated [-Wdeprecated-declarations]
Name<decltype(gets)> n;
^
/usr/include/stdio.h:638:37: note: 'gets' has been explicitly marked deprecated here
extern char *gets (char *__s) __wur __attribute_deprecated__;
^
/usr/include/x86_64-linux-gnu/sys/cdefs.h:254:51: note: expanded from macro '__attribute_deprecated__'
# define __attribute_deprecated__ __attribute__ ((__deprecated__))
^
/tmp/613814454/Main.cpp:16:26: error: implicit instantiation of undefined template 'Name<char *(char *)>'
Name<decltype(gets)> n;
^
/tmp/613814454/Main.cpp:12:25: note: template is declared here
template <class> struct Name;
^
1 warning and 1 error generated.
gets
ditandai sebagai usang dan memiliki tanda tangan char *(char *)
. Tapi bagaimana cara FirstFactorial(gets(stdin));
kompilasi?
Mari kita coba yang lain:
int main() {
Name<decltype(gets(stdin))> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
Yang memberi kita:
/tmp/286775780/Main.cpp:15:21: error: implicit instantiation of undefined template 'Name<int>'
Name<decltype(8)> n;
^
Akhirnya kita mendapatkan sesuatu: decltype(8)
. Jadi semuanya gets(stdin)
diganti secara tekstual dengan input ( 8
).
Dan hal-hal semakin aneh. Kesalahan kompiler berlanjut:
/tmp/596773533/Main.cpp:18:26: error: no matching function for call to 'gets'
cout << FirstFactorial(gets(stdin));
^~~~
/usr/include/stdio.h:638:14: note: candidate function not viable: no known conversion from 'struct _IO_FILE *' to 'char *' for 1st argument
extern char *gets (char *__s) __wur __attribute_deprecated__;
Jadi sekarang kita mendapatkan kesalahan yang diharapkan untuk cout << FirstFactorial(gets(stdin));
Saya memeriksa makro dan karena #undef gets
sepertinya tidak melakukan apa-apa sepertinya itu bukan makro.
Tapi
std::integral_constant<int, gets(stdin)> n;
Itu mengkompilasi.
Tapi
std::integral_constant<int, gets(stdin)> n; // OK
std::integral_constant<int, gets(stdin)> n2; // ERROR wtf??
Tidak dengan kesalahan yang diharapkan di n2
telepon.
Dan lagi, hampir semua modifikasi untuk main
membuat garis cout << FirstFactorial(gets(stdin));
meludahkan kesalahan yang diharapkan.
Apalagi yang stdin
tampak kosong.
Jadi saya hanya bisa menyimpulkan dan berspekulasi mereka memiliki program kecil yang mem-parsing sumber dan mencoba (buruk) untuk mengganti gets(stdin)
dengan nilai input test case sebelum benar-benar memasukkannya ke dalam kompiler. Jika ada yang punya teori yang lebih baik atau benar-benar tahu apa yang mereka lakukan, silakan bagikan!
Ini jelas merupakan praktik yang sangat buruk. Saat meneliti ini saya menemukan setidaknya ada pertanyaan di sini ( contoh ) tentang ini dan karena orang tidak tahu bahwa ada situs di luar sana yang melakukan ini, jawaban mereka adalah "jangan gunakan gets
gunakan ... sebagai gantinya" yang memang saran yang bagus tetapi lebih membingungkan OP karena usaha membaca yang valid dari stdin akan gagal di situs ini.
TLDR
gets(stdin)
tidak valid C ++. Ini tipuan yang digunakan situs ini (untuk alasan apa saya tidak tahu). Jika Anda ingin terus mengirimkan di situs (saya tidak mendukungnya atau tidak mendukungnya) Anda harus menggunakan konstruksi ini yang jika tidak tidak masuk akal, tetapi perlu diketahui bahwa itu rapuh. Hampir semua modifikasi untuk main
memuntahkan kesalahan. Di luar situs ini menggunakan metode membaca input normal.
stdin
di perpustakaan standar adalah aFILE*
, dan penunjuk ke tipe apa pun dikonversi menjadichar*
, yang merupakan tipe argumen darigets()
. Namun, Anda tidak boleh, pernah, pernah menulis kode seperti itu di luar kontes C yang membingungkan. Jika kompiler Anda bahkan menerimanya, tambahkan lebih banyak bendera peringatan, dan jika Anda mencoba untuk memperbaiki basis kode yang memiliki konstruksi di dalamnya, ubah peringatan menjadi kesalahan.