Je suis intrigué. Donc, il est temps de mettre les lunettes d'enquête et comme je n'ai pas accès au compilateur ou aux indicateurs de compilation, je dois devenir inventif. Aussi parce que rien dans ce code n'a de sens, ce n'est pas une mauvaise idée de remettre en question chaque hypothèse.
Commençons par vérifier le type réel de gets
. J'ai un petit truc pour ça:
template <class> struct Name;
int main() {
Name<decltype(gets)> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
Et cela semble ... 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
est marqué comme obsolète et possède la signature char *(char *)
. Mais alors comment est la FirstFactorial(gets(stdin));
compilation?
Essayons autre chose:
int main() {
Name<decltype(gets(stdin))> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
Ce qui nous donne:
/tmp/286775780/Main.cpp:15:21: error: implicit instantiation of undefined template 'Name<int>'
Name<decltype(8)> n;
^
Enfin , nous obtenons quelque chose: decltype(8)
. Donc, le tout a gets(stdin)
été remplacé textuellement par l'entrée ( 8
).
Et les choses deviennent plus étranges. L'erreur du compilateur continue:
/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__;
Alors maintenant, nous obtenons l'erreur attendue pour cout << FirstFactorial(gets(stdin));
J'ai vérifié une macro et depuis #undef gets
semble ne rien faire, il semble que ce ne soit pas une macro.
Mais
std::integral_constant<int, gets(stdin)> n;
Il compile.
Mais
std::integral_constant<int, gets(stdin)> n; // OK
std::integral_constant<int, gets(stdin)> n2; // ERROR wtf??
Pas avec l'erreur attendue à la n2
ligne.
Et encore une fois, presque toutes les modifications apportées à main
la ligne cout << FirstFactorial(gets(stdin));
crachent l'erreur attendue.
De plus, le stdin
semble être vide.
Je ne peux donc que conclure et spéculer qu'ils ont un petit programme qui analyse la source et essaie (mal) de remplacer gets(stdin)
par la valeur d'entrée du cas de test avant de l'introduire dans le compilateur. Si quelqu'un a une meilleure théorie ou sait ce qu'il fait, partagez-le!
C'est évidemment une très mauvaise pratique. En recherchant cela, j'ai trouvé qu'il y avait au moins une question ici ( exemple ) à ce sujet et parce que les gens n'ont aucune idée qu'il existe un site qui le fait, leur réponse est "n'utilisez pas, gets
utilisez ... à la place", ce qui est en effet un bon conseil mais ne fait que confondre davantage l'OP puisque toute tentative de lecture valide depuis stdin échouera sur ce site.
TLDR
gets(stdin)
n'est pas valide en C ++. C'est un gadget que ce site utilise en particulier (pour quelles raisons je ne peux pas comprendre). Si vous souhaitez continuer à soumettre sur le site (je ne l'approuve ni ne l'approuve), vous devez utiliser cette construction qui autrement n'aurait pas de sens, mais sachez qu'elle est fragile. Presque toutes les modifications apportées à main
vont cracher une erreur. En dehors de ce site, utilisez des méthodes de lecture d'entrée normales.
stdin
dans la bibliothèque standard se trouve unFILE*
, et un pointeur vers n'importe quel type est converti enchar*
, qui est le type de l'argument degets()
. Cependant, vous ne devriez jamais, jamais, jamais écrire ce genre de code en dehors d'un concours C obscurci. Si votre compilateur l'accepte même, ajoutez plus d'indicateurs d'avertissement, et si vous essayez de corriger une base de code contenant cette construction, transformez les avertissements en erreurs.