Coderbyte ist eine Online-Codierungs-Challenge-Site (ich habe sie erst vor 2 Minuten gefunden).
Die erste C ++ - Herausforderung, mit der Sie begrüßt werden, enthält ein C ++ - Skelett, das Sie ändern müssen:
#include <iostream> #include <string> using namespace std; int FirstFactorial(int num) { // Code goes here return num; } int main() { // Keep this function call here cout << FirstFactorial(gets(stdin)); return 0; }
Wenn Sie wenig vertraut mit C ++ dem ersten , was sind * , das erscheint in Ihren Augen ist:
int FirstFactorial(int num);
cout << FirstFactorial(gets(stdin));
Also, ok, der Code ruft auf, gets
der seit C ++ 11 veraltet und seit C ++ 14 entfernt ist, was an sich schlecht ist.
Aber dann merke ich: gets
ist vom Typ char*(char*)
. Es sollte also keinen FILE*
Parameter akzeptieren und das Ergebnis sollte nicht anstelle eines int
Parameters verwendet werden können, sondern ... es wird nicht nur ohne Warnungen oder Fehler kompiliert, sondern es wird ausgeführt und übergibt tatsächlich den richtigen Eingabewert an FirstFactorial
.
Außerhalb dieser speziellen Site wird der Code nicht (wie erwartet) kompiliert. Was ist hier also los?
* Eigentlich ist der erste, using namespace std
aber das ist für mein Problem hier irrelevant.
quelle
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.gets(stdin )
(mit einem zusätzlichen Leerzeichen) den erwarteten C ++ - Fehler erzeugt.Antworten:
Ich bin der Gründer von Coderbyte und auch der Typ, der diesen
gets(stdin)
Hack erstellt hat.Die Kommentare zu diesem Beitrag sind richtig, dass es sich um eine Form des Findens und Ersetzens handelt. Lassen Sie mich daher erklären, warum ich dies sehr schnell getan habe.
Damals, als ich die Site zum ersten Mal erstellte (um 2012), unterstützte sie nur JavaScript. Es gab keine Möglichkeit, Eingaben in JavaScript, das im Browser ausgeführt wird, "einzulesen", und daher würde es eine Funktion geben
foo(input)
und ich habe diereadline()
Funktion von Node.js verwendet, um sie wie folgt aufzurufenfoo(readline())
. Außer ich war ein Kind und wusste es nicht besser, also habe ich esreadline()
zur Laufzeit buchstäblich nur durch die Eingabe ersetzt . Sofoo(readline())
wurdefoo(2)
oderfoo("hello")
was für JavaScript gut funktionierte.Um 2013/2014 habe ich weitere Sprachen hinzugefügt und Dienste von Drittanbietern verwendet, um Code online auszuwerten. Es war jedoch sehr schwierig, mit den von mir verwendeten Diensten stdin / stdout durchzuführen. Daher habe ich mich an das gleiche dumme Suchen und Ersetzen für Sprachen gehalten wie Python, Ruby und schließlich C ++, C # usw.
Schneller Vorlauf bis heute, ich führe den Code in meinen eigenen Containern aus, habe aber nie die Funktionsweise von stdin / stdout aktualisiert, weil sich die Leute an den seltsamen Hack gewöhnt haben (einige Leute haben sogar in Foren gepostet, in denen erklärt wird, wie man ihn umgeht).
Ich weiß, dass es keine bewährte Methode ist und es für jemanden, der eine neue Sprache lernt, nicht hilfreich ist, solche Hacks zu sehen, aber die Idee war, dass neue Programmierer sich überhaupt keine Gedanken über das Lesen von Eingaben machen und sich nur darauf konzentrieren, den Algorithmus zu schreiben, um das Problem zu lösen Problem. Eine häufige Beschwerde über Coding-Challenge-Sites vor Jahren war, dass neue Programmierer viel Zeit damit verbringen würden, nur herauszufinden, wie
stdin
man aus einer Datei liest oder Zeilen aus einer Datei liest. Deshalb wollte ich, dass neue Codierer dieses Problem auf Coderbyte vermeiden.Ich werde in Kürze die gesamte Editorseite zusammen mit dem Standardcode aktualisieren und
stdin
für Sprachen lesen. Hoffentlich werden dann C ++ - Programmierer Coderbyte mehr genießen :)quelle
TAKE_INPUT
ersetzen und dann Ihren Find-Replace verwenden, um ihn#define TAKE_INPUT whatever_here
oben einzufügen .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:Und das sieht ... normal aus:
gets
ist als veraltet markiert und hat die Unterschriftchar *(char *)
. Aber wie ist es dann?FirstFactorial(gets(stdin));
Kompilieren?Versuchen wir etwas anderes:
Was uns gibt:
Endlich bekommen wir etwas:
decltype(8)
. Also wurde das Ganzegets(stdin)
textuell durch die Eingabe ersetzt (8
) ersetzt.Und die Dinge werden seltsamer. Der Compilerfehler wird fortgesetzt:
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
Es kompiliert.
Aber
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 anmain
werden einen Fehler ausspucken. Verwenden Sie außerhalb dieser Site normale Lesemethoden für Eingaben.quelle
std::cout << "gets(stdin)";
und die Ausgabe ist8
(oder was auch immer Sie in das 'Eingabe'-Feld"gets(stdin)"
. Das ist ein String-Literal, das selbst der Präprozessor nicht berühren würdeIch habe
main
im Coderbyte-Editor folgende Ergänzung ausprobiert:Wo das mysteriöse und rätselhafte Snippet
gets(stdin)
in einem String-Literal erscheint. Dies sollte möglicherweise von nichts transformiert werden, nicht einmal vom Präprozessor, und jeder C ++ - Programmierer sollte erwarten, dass dieser Code die genaue Zeichenfolgegets(stdin)
in die Standardausgabe druckt . Und doch sehen wir die folgende Ausgabe, wenn sie kompiliert und auf Coderbyte ausgeführt wird:Wobei der Wert
8
direkt aus dem praktischen Eingabefeld unter dem Editor übernommen wird.Daraus ergibt sich, dass dieser Online-Editor blinde Such- und Ersetzungsvorgänge für den Quellcode ausführt, wobei das Erscheinungsbild
gets(stdin)
durch die 'Eingabe' des Benutzers ersetzt wird. Ich persönlich würde dies einen Missbrauch der Sprache nennen, der schlimmer ist als unachtsame Präprozessor-Makros.Im Zusammenhang mit einer Online-Codierungs-Challenge-Website mache ich mir darüber Sorgen, weil sie unkonventionelle, nicht standardmäßige, bedeutungslose und zumindest unsichere Praktiken wie
gets(stdin)
und auf eine Weise lehrt, die auf anderen Plattformen nicht wiederholt werden kann.Ich bin sicher , es kann nicht sein die schwer , nur zu verwenden
std::cin
und nur Strom Eingabe in ein Programm.quelle
gets(stdin)
, das ersetzt wird? Ich meinte "blind" in dem Sinne, dass es die Syntax oder Grammatik der Sprache nicht zu kennen scheint.System.out.print(FirstFactorial(s.nextLine()9));
gedruckt89
, wenn sie nichts
definiert ist.