站点编码字节上的“ gets(stdin)”怎么回事? [英] What is going on with 'gets(stdin)' on the site coderbyte?

查看:95
本文介绍了站点编码字节上的“ gets(stdin)”怎么回事?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Coderbyte是一个在线编码挑战网站(我在2分钟前找到了它)。



遇到的第一个C ++挑战具有需要修改的C ++框架:



< blockquote>

  #include< iostream> 
#include< string>
使用命名空间std;

int FirstFactorial(int num){

//代码在这里
返回编号;

}

int main(){

//在此处保留此函数调用
cout<< FirstFactorial(gets(stdin));
返回0;

}


如果你很小熟悉C ++的第一件事 * 出现在您眼中的是:

  int FirstFactorial(int num ); 
cout<< FirstFactorial(gets(stdin));

好吧,代码调用得到自C ++ 11起已弃用,自C ++ 14起已删除,这本身是不好的。



但是后来我意识到:获取的类型是 char *(char *)。因此,它不应该接受 FILE * 参数,并且结果不能代替 int 使用参数,但...不仅可以编译,没有任何警告或错误,而且可以运行并实际上将正确的输入值传递给 FirstFactorial



在此特定站点之外,代码未按预期进行编译,所以这里发生了什么?






*实际上第一个是使用命名空间std ,但这与我在这里的问题无关。

解决方案

我很感兴趣。因此,请抽出时间来研究调查镜,由于我无权使用编译器或编译标志,因此需要发挥创造力。另外,因为与此代码无关,所以对每个假设都提出一个好主意。


首先,让我们检查获取的实际类型。我为此有一个小技巧:

  template< class>结构名称; 

int main(){

Name< decltype(gets)> n;

//将此函数保留在此处
cout<< FirstFactorial(gets(stdin));
返回0;

}

这看起来...正常:


  /tmp/613814454/Main.cpp:16:19:警告:不建议使用'gets'[-Wdeprecated-declarations] 
Name< ; decltype(gets)> n;
^
/usr/include/stdio.h:638:37:注意: gets已在此处明确标记为已弃用。
extern char * gets(char * __ s)__wur __attribute_deprecated__;
^
/usr/include/x86_64-linux-gnu/sys/cdefs.h:254:51:注意:从宏'__attribute_deprecated__'扩展
#定义__attribute_deprecated__ __attribute__((__deprecated__) )
^
/tmp/613814454/Main.cpp:16:26:错误:未定义模板'Name< char *(char *)>'的隐式实例化
Name< decltype(得到)> n;
^
/tmp/613814454/Main.cpp:12:25:注意:此处声明了模板
template< class>结构名称;
^
产生1条警告和1条错误。


gets 被标记为已弃用,并且签名为 char *(char *)。但是 FirstFactorial(gets(stdin)); 怎么编译?


让我们尝试一下其他事情:

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

//将此函数保留在此处
cout<< FirstFactorial(gets(stdin));
返回0;

}

哪个给了我们:


  /tmp/286775780/Main.cpp:15:21:错误:未定义模板'Name< int>'的隐式实例化
Name< decltype(8 )> n;
^


最后我们得到了一些东西: decltype(8)。因此,整个 gets(stdin)被文本替换为输入( 8 )。


事情变得奇怪了。编译器错误继续:


  /tmp/596773533/Main.cpp:18:26:错误:无匹配功能呼叫获取 
cout<< FirstFactorial(gets(stdin));
^ ~~~
/usr/include/stdio.h:638:14:注意:候选函数不可行:第一个参数$从'struct _IO_FILE *'到'char *'的未知转换b $ b extern char * gets(char * __ s)__wur __attribute_deprecated__;


现在,我们得到了 cout< < FirstFactorial(gets(stdin));


我检查了一个宏,因为 #undef得到似乎


但是

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

它会编译。


但是

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

n2 行没有预期的错误。


再一次,几乎对 main 进行的任何修改都会使行 cout<< FirstFactorial(gets(stdin)); 吐出预期的错误。


此外, stdin 实际上似乎


所以我只能得出结论,并推测他们有一个小程序可以解析源并尝试(较差地)替换 gets(stdin)包含测试用例的输入值,然后才将其实际输入到编译器中。如果有人有更好的理论或实际上知道他们在做什么,请分享!


这显然是非常糟糕的做法。经过研究,我发现这里至少存在一个问题(示例),因为人们不知道那里有一个这样做的网站,他们的答案是不要使用获取使用...代替这确实是一个很好的建议,但只会使操作程序更加混乱,因为任何从stdin进行有效读取的尝试都将在此站点上失败。




TLDR


gets(stdin)是无效的C ++。这个特定网站使用的gi头(出于什么原因我无法弄清楚)。如果您想继续在网站上提交(我既不认可也不不认可),则必须使用这种结构,否则该结构将毫无意义,但请注意它很脆弱。对 main 的几乎所有修改都会吐出一个错误。在此站点之外,请使用常规的输入法阅读。


Coderbyte is an online coding challenge site (I found it just 2 minutes ago).

The first C++ challenge you are greeted with has a C++ skeleton you need to modify:

#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;

}

If you are little familiar with C++ the first thing* that pops in your eyes is:

int FirstFactorial(int num);
cout << FirstFactorial(gets(stdin));

So, ok, the code calls gets which is deprecated since C++11 and removed since C++14 which is bad in itself.

But then I realize: gets is of type char*(char*). So it shouldn't accept a FILE* parameter and the result shouldn't be usable in the place of an int parameter, but ... not only it compiles without any warnings or errors, but it runs and actually passes the correct input value to FirstFactorial.

Outside of this particular site, the code doesn't compile (as expected), so what is going on here?


*Actually the first one is using namespace std but that is irrelevant to my issue here.

解决方案

I am intrigued. So, time to put the investigation goggles on and since I don't have access to the compiler or compilation flags I need to get inventive. Also because nothing about this code makes sense it's not a bad idea question every assumption.

First let's check the actual type of gets. I have a little trick for that:

template <class> struct Name;

int main() { 
    
    Name<decltype(gets)> n;
  
  // keep this function call here
  cout << FirstFactorial(gets(stdin));
  return 0;
    
}

And that looks ... 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 is marked as deprecated and has the signature char *(char *). But then how is FirstFactorial(gets(stdin)); compiling?

Let's try something else:

int main() { 
  Name<decltype(gets(stdin))> n;
  
  // keep this function call here
  cout << FirstFactorial(gets(stdin));
  return 0;
    
} 

Which gives us:

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

Finally we are getting something: decltype(8). So the entire gets(stdin) was textually replaced with the input (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.

这篇关于站点编码字节上的“ gets(stdin)”怎么回事?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆