Programing

사이트 코더 바이트에서 'gets (stdin)'은 어떻게됩니까?

lottogame 2020. 6. 21. 19:38
반응형

사이트 코더 바이트에서 'gets (stdin)'은 어떻게됩니까?


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이지만 여기의 내 문제와 관련이 없습니다.


저는 Coderbyte의 창립자이며이 gets(stdin)을 만든 사람입니다 .

이 게시물에 대한 의견은 그것이 찾기 및 바꾸기의 형태라는 것이 정확하므로 내가 왜 그렇게 빨리했는지 설명하겠습니다.

2012 년 경에 처음 사이트를 만든 당시에는 JavaScript 만 지원했습니다. 브라우저에서 실행되는 JavaScript에서 "입력을 읽는"방법이 없었으므로 함수가 있고 Node.js foo(input)readline()함수를 사용하여 처럼 호출했습니다 foo(readline()). 내가 어 렸고 더 잘 몰랐기 때문에 문자 그대로 readline()런타임에 입력으로 바꿨습니다. 그래서이 foo(readline())되었다 foo(2)또는 foo("hello")자바 스크립트 벌금을 근무한다.

2013/2014 년경에 더 많은 언어를 추가하고 타사 서비스를 사용하여 코드를 온라인으로 평가했지만 사용중인 서비스로 stdin / stdout을 수행하는 것은 매우 어려웠으므로 언어에 대해 동일한 어리석은 찾기 및 바꾸기를 고수했습니다. Python, Ruby 및 C ++, C # 등

오늘 빨리, 나는 내 컨테이너에서 코드를 실행하지만 사람들이 이상한 해킹에 익숙해 져서 stdin / stdout 작동 방식을 업데이트하지 않았습니다 (일부 사람들은 포럼에 게시하는 방법을 설명했습니다).

모범 사례가 아니며 새로운 언어를 배우는 사람이 이와 같은 해킹을 보는 데 도움이되지 않는다는 것을 알고 있지만 새로운 프로그래머는 입력을 전혀 걱정하지 않고 알고리즘을 작성하여 문제를 해결하는 데 집중했습니다. 문제. 몇 년 전 사이트 코딩 문제에 대한 일반적인 불만 중 하나는 새로운 프로그래머가 stdin파일에서 줄 을 읽 거나 읽는 방법을 알아내는 데 많은 시간을 할애한다는 점입니다 . 따라서 새로운 코더가 Coderbyte에서이 문제를 피하기를 원했습니다.

기본 코드와 함께 전체 편집기 페이지를 곧 업데이트하고 stdin언어를 읽을 것입니다. 희망적으로 C ++ 프로그래머는 Coderbyte를 더 많이 사용하게 될 것입니다 :)


나는 흥미 롭다. 그래서 조사 고글을 착용 할 시간이며 컴파일러 또는 컴파일 플래그에 액세스 할 수 없으므로 독창적이어야합니다. 또한이 코드에 대한 의미가 없기 때문에 모든 가정에 나쁜 아이디어 질문은 아닙니다.

먼저 실제 유형을 확인합시다 gets. 나는 약간의 트릭을 가지고있다 :

template <class> struct Name;

int main() { 

    Name<decltype(gets)> n;

  // keep this function call here
  cout << FirstFactorial(gets(stdin));
  return 0;

}

그리고 그것은 ... 보통 보입니다.

/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더 이상 사용되지 않는 것으로 표시되고 서명이 char *(char *)있습니다. 그러나 어떻게 FirstFactorial(gets(stdin));컴파일되고 있습니까?

다른 것을 시도해 보자.

int main() { 
  Name<decltype(gets(stdin))> n;

  // keep this function call here
  cout << FirstFactorial(gets(stdin));
  return 0;

} 

우리에게주는 것 :

/tmp/286775780/Main.cpp:15:21: error: implicit instantiation of undefined template 'Name<int>'
  Name<decltype(8)> n;
                    ^

마침내 우리는 무언가를 얻고 있습니다 : decltype(8). 따라서 전체 gets(stdin)가 텍스트로 입력 ( 8)으로 대체되었습니다 .

And the things get weirder. The compiler error continues:

/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__;

So now we get the expected error for cout << FirstFactorial(gets(stdin));

I checked for a macro and since #undef gets seems to do nothing it looks like it isn't a macro.

But

std::integral_constant<int, gets(stdin)> n;

It compiles.

But

std::integral_constant<int, gets(stdin)> n;    // OK
std::integral_constant<int, gets(stdin)> n2;   // ERROR                                          wtf??

Doesn't with the expected error at the n2 line.

And again, almost any modification to main makes the line cout << FirstFactorial(gets(stdin)); spit out the expected error.

Moreover the stdin actually seems to be empty.

So I can only conclude and speculate they have a little program that parses the source and tries (poorly) to replace gets(stdin) with the test case input value before actually feeding it into the compiler. If anybody has a better theory or actually knows what they are doing please share!

This is obviously a very bad practice. While researching this I found there is at least a question here (example) about this and because people have no idea that there is a site out there who does this their answer is "don't use gets use ... instead" which is indeed a good advice but only confuses the OP more since any attempt at a valid read from stdin will fail on this site.


TLDR

gets(stdin) is invalid C++. It's a gimmick this particular site uses (for what reasons I cannot figure out). If you want to continue to submit on the site (I am neither endorsing it neither not endorsing it) you have to use this construct that otherwise would not make sense, but be aware that it is brittle. Almost any modifications to main will spit out an error. Outside of this site use normal input reading methods.


I tried the following addition to main in the Coderbyte editor:

std::cout << "gets(stdin)";

Where the mysterious and enigmatic snippet gets(stdin) appears inside a string literal. This shouldn't possibly be transformed by anything, not even the preprocessor, and any C++ programmer should expect this code to print the exact string gets(stdin) to the standard output. And yet we see the following output, when compiled and run on coderbyte:

8

Where the value 8 is taken straight from the convenient 'input' field under the editor.

Magic code

From this, it's clear that this online editor is performing blind find-and-replace operations on the source code, substitution appearances of gets(stdin) with the user's 'input'. I would personally call this a misuse of the language that's worse than careless preprocessor macros.

In the context of an online coding challenge website, I'm worried by this because it teaches unconventional, non-standard, meaningless, and at least unsafe practices like gets(stdin), and in a manner that can't be repeated on other platforms.

I'm sure it can't be this hard to just use std::cin and just stream input to a program.

참고URL : https://stackoverflow.com/questions/55269252/what-is-going-on-with-getsstdin-on-the-site-coderbyte

반응형