Ich bin fasziniert. Also, Zeit, die Untersuchungsbrille aufzusetzen, und da ich keinen Zugriff auf den Compiler oder die Kompilierungsflags habe, muss ich erfinderisch werden. Auch weil nichts an diesem Code Sinn macht, ist es keine schlechte Idee, jede Annahme in Frage zu stellen.
Lassen Sie uns zuerst den tatsächlichen Typ von überprüfen gets
. Ich habe einen kleinen Trick dafür:
template <class> struct Name;
int main() {
Name<decltype(gets)> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
Und das sieht ... normal aus:
/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
ist als veraltet markiert und hat die Unterschrift char *(char *)
. Aber wie ist es dann?FirstFactorial(gets(stdin));
Kompilieren?
Versuchen wir etwas anderes:
int main() {
Name<decltype(gets(stdin))> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
Was uns gibt:
/tmp/286775780/Main.cpp:15:21: error: implicit instantiation of undefined template 'Name<int>'
Name<decltype(8)> n;
^
Endlich bekommen wir etwas: decltype(8)
. Also wurde das Ganze gets(stdin)
textuell durch die Eingabe ersetzt (8
) ersetzt.
Und die Dinge werden seltsamer. Der Compilerfehler wird fortgesetzt:
/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__;
Jetzt erhalten wir den erwarteten Fehler für cout << FirstFactorial(gets(stdin));
Ich habe nach einem Makro gesucht und seitdem #undef gets
es nichts zu tun scheint, sieht es so aus, als wäre es kein Makro.
Aber
std::integral_constant<int, gets(stdin)> n;
Es kompiliert.
Aber
std::integral_constant<int, gets(stdin)> n; // OK
std::integral_constant<int, gets(stdin)> n2; // ERROR wtf??
Geht nicht mit dem erwarteten Fehler am n2
Leitung.
Und wieder fast jede Modifikation main
macht die Liniecout << FirstFactorial(gets(stdin));
den erwarteten Fehler ausspucken zu lassen.
Darüber hinaus die stdin
scheint eigentlich leer zu sein.
Ich kann also nur schließen und spekulieren, dass sie ein kleines Programm haben, das die Quelle analysiert und (schlecht) versucht, sie zu ersetzen gets(stdin)
den Testfall-Eingabewert bevor sie tatsächlich in den Compiler eingespeist werden. Wenn jemand eine bessere Theorie hat oder tatsächlich weiß, was er tut, teilen Sie dies bitte mit!
Dies ist offensichtlich eine sehr schlechte Praxis. Während ich dies recherchierte, stellte ich fest, dass es hier zumindest eine Frage gibt ( Beispiel ), und da die Leute keine Ahnung haben, dass es da draußen eine Site gibt, die dies tut, lautet ihre Antwort "benutze nicht gets
benutze ... stattdessen", was in der Tat der Fall ist Ein guter Rat, der das OP jedoch nur mehr verwirrt, da jeder Versuch eines gültigen Lesens von stdin auf dieser Site fehlschlägt.
TLDR
gets(stdin)
ist ungültig C ++. Es ist eine Spielerei, die diese spezielle Site verwendet (aus welchen Gründen ich es nicht herausfinden kann). Wenn Sie weiterhin auf der Website einreichen möchten (ich unterstütze es weder noch unterstütze ich es), müssen Sie dieses Konstrukt verwenden, das sonst keinen Sinn ergibt, aber sich bewusst ist, dass es spröde ist. Fast alle Änderungen an main
werden einen Fehler ausspucken. Verwenden Sie außerhalb dieser Site normale Lesemethoden für Eingaben.
stdin
in der Standardbibliothek einFILE*
und ein Zeiger auf einen beliebigen Typ konvertiert wirdchar*
, der der Typ des Arguments von istgets()
. Sie sollten diese Art von Code jedoch niemals außerhalb eines verschleierten C-Wettbewerbs schreiben. Wenn Ihr Compiler dies überhaupt akzeptiert, fügen Sie weitere Warnflags hinzu. Wenn Sie versuchen, eine Codebasis zu reparieren, in der dieses Konstrukt enthalten ist, verwandeln Sie Warnungen in Fehler.