Coderbyte - это онлайновый сайт, посвященный проблемам кодирования (я нашел его всего 2 минуты назад).
Первый вызов C ++, с которым вас встретят, имеет скелет C ++, который нужно изменить:
#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; }
Если вы мало знакомы с C ++ первым делом * что выскакивает в ваших глазах:
int FirstFactorial(int num);
cout << FirstFactorial(gets(stdin));
Итак, хорошо, код вызывает, gets
который устарел с C ++ 11 и удален с C ++ 14, что само по себе плохо.
Но потом я понимаю: gets
это тип char*(char*)
. Таким образом, он не должен принимать FILE*
параметр, и результат не должен использоваться вместо int
параметра, но ... он не только компилируется без каких-либо предупреждений или ошибок, но и работает и фактически передает правильное входное значение FirstFactorial
.
За пределами этого конкретного сайта код не компилируется (как и ожидалось), так что здесь происходит?
* На самом деле первое, using namespace std
но это не имеет отношения к моей проблеме здесь.
источник
stdin
в стандартной библиотеке естьFILE*
, и указатель на любой тип преобразуется вchar*
, который является типом аргументаgets()
. Тем не менее, вы никогда не должны писать такого рода код вне запутанного конкурса Си. Если ваш компилятор даже принимает его, добавьте больше флагов предупреждений, и, если вы пытаетесь исправить кодовую базу с этой конструкцией, превратите предупреждения в ошибки.gets(stdin )
(с дополнительным пробелом) выдает ожидаемую ошибку C ++.Ответы:
Я основатель Coderbyte, а также парень, который создал этот
gets(stdin)
хак.Комментарии к этому сообщению верны, так как это форма поиска и замены, поэтому позвольте мне объяснить, почему я сделал это очень быстро.
Когда я впервые создал сайт (около 2012 года), он поддерживал только JavaScript. В JavaScript не было возможности «читать входные данные», работающие в браузере, и поэтому была бы функция,
foo(input)
и я использовалreadline()
функцию из Node.js для ее вызова какfoo(readline())
. За исключением того, что я был ребенком и не знал лучше, поэтому я буквально заменилreadline()
ввод во время выполнения. Такfoo(readline())
сталоfoo(2)
илиfoo("hello")
работало нормально для JavaScript.Примерно в 2013/2014 году я добавил больше языков и использовал сторонние сервисы для оценки кода в сети, но было очень сложно использовать stdin / stdout с сервисами, которые я использовал, поэтому я остался с тем же глупым поиском и заменой языков как Python, Ruby и, в конечном итоге, C ++, C # и т. д.
Забегая вперед, сегодня я запускаю код в своих собственных контейнерах, но никогда не обновляю способ работы stdin / stdout, потому что люди привыкли к странному хаку (некоторые люди даже публиковались на форумах, объясняющих, как его обойти).
Я знаю, что это не лучшая практика, и для кого-то, изучающего новый язык, бесполезно видеть подобные хаки, но идея в том, чтобы новые программисты вообще не беспокоились о чтении ввода и просто сосредоточились на написании алгоритма для решения проблема. Еще одна распространенная жалоба на проблемы с кодированием сайтов много лет назад заключалась в том, что новые программисты тратят много времени
stdin
на изучение того, как читать или читать строки из файла, поэтому я хотел, чтобы новые кодеры избежали этой проблемы на кодербайте.Скоро я обновлю всю страницу редактора вместе с кодом по умолчанию и
stdin
чтением для языков. Надеемся, что тогда программисты на C ++ получат больше удовольствия от использования Coderbyte :)источник
TAKE_INPUT
, а затем используйте ваш find-replace для вставки#define TAKE_INPUT whatever_here
вверху.Я заинтригован. Итак, время надеть защитные очки, и, поскольку у меня нет доступа к компилятору или флагам компиляции, мне нужно проявить изобретательность. Кроме того, потому что ничто в этом коде не имеет смысла, это не плохая идея, ставящая под сомнение каждое предположение.
Сначала давайте проверим фактический тип
gets
. У меня есть небольшая хитрость для этого:И это выглядит ... нормально:
gets
помечен как устаревший и имеет подписьchar *(char *)
. Но тогда какFirstFactorial(gets(stdin));
компилируется?Давайте попробуем что-то еще:
Что дает нам:
Наконец-то мы получаем что-то
decltype(8)
. Таким образом, весьgets(stdin)
текст был заменен на input (8
).И все становится страннее. Ошибка компилятора продолжается:
Итак, теперь мы получаем ожидаемую ошибку для
cout << FirstFactorial(gets(stdin));
Я проверил макрос и,
#undef gets
похоже, ничего не делает, похоже, что это не макрос.Но
Это компилируется.
Но
Не с ожидаемой ошибкой в
n2
строке.И снова, почти любая модификация
main
заставляет линиюcout << FirstFactorial(gets(stdin));
выплевывать ожидаемую ошибку.Кроме того, на
stdin
самом деле, кажется, пусто.Поэтому я могу только заключить и предположить, что у них есть небольшая программа, которая анализирует исходный код и пытается (плохо) заменить
gets(stdin)
его входным значением тестового примера перед тем, как фактически передать его в компилятор. Если кто-то имеет лучшую теорию или действительно знает, что он делает, пожалуйста, поделитесь!Это явно очень плохая практика. Исследуя это, я обнаружил, что здесь есть, по крайней мере, вопрос ( пример ) об этом, и потому что люди понятия не имеют, что существует сайт, который делает это, их ответом является «не используйте
gets
use вместо этого», что действительно Хороший совет, но он еще больше сбивает с толку OP, так как любая попытка корректного чтения из stdin на этом сайте потерпит неудачу.TLDR
gets(stdin)
является недействительным C ++. Это трюк, который использует этот конкретный сайт (по каким причинам я не могу понять). Если вы хотите продолжить отправку на сайт (я не одобряю и не одобряю его), вы должны использовать эту конструкцию, которая в противном случае не имела бы смысла, но помните, что она хрупкая. Практически любые модификацииmain
выложат ошибку. За пределами этого сайта используйте обычные методы чтения ввода.источник
std::cout << "gets(stdin)";
и вывод будет8
(или все, что вы вводите в поле ввода). Это позорное злоупотребление языком."gets(stdin)"
. Это строковый литерал, который не коснется даже препроцессорЯ попробовал следующее дополнение
main
в редакторе Coderbyte:Где таинственный и загадочный фрагмент
gets(stdin)
появляется внутри строкового литерала. Это не должно быть преобразовано ничем, даже препроцессором, и любой программист C ++ должен ожидать, что этот код выведет точную строкуgets(stdin)
в стандартный вывод. И все же мы видим следующий вывод при компиляции и запуске на кодербайте:Где значение
8
берется прямо из удобного поля ввода под редактором.Из этого ясно, что этот онлайн-редактор выполняет слепые операции поиска и замены над исходным кодом, заменив их
gets(stdin)
на «ввод» пользователя. Я бы лично назвал это неправильным использованием языка, который хуже небрежного макроса препроцессора.В контексте веб-сайта, посвященного проблемам онлайн-кодирования, меня это беспокоит, потому что он учит нетрадиционным, нестандартным, бессмысленным и, по крайней мере, небезопасным практикам, таким образом
gets(stdin)
, и таким образом, который не может быть повторен на других платформах.Я уверен, что не может быть так сложно просто использовать
std::cin
и просто передавать данные в программу.источник
gets(stdin)
что заменено? Я имел в виду «слепой» в том смысле, что он, кажется, не знает синтаксиса или грамматики языка.System.out.print(FirstFactorial(s.nextLine()9));
печатается,89
даже еслиs
она не определена.