What is going on with 'gets(stdin)' on the site coderbyte? - c++

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'm the founder of Coderbyte and also the guy who created this gets(stdin) hack.
The comments on this post are correct that it is a form of find-and-replace, so let me explain why I did this really quickly.
Back in the day when I first created the site (around 2012), it only supported JavaScript. There was no way to "read in input" in JavaScript running in the browser, and so there would be a function foo(input) and I used the readline() function from Node.js to call it like foo(readline()). Except I was a kid and didn't know better, so I literally just replaced readline() with the input at run-time. So foo(readline()) became foo(2) or foo("hello") which worked fine for JavaScript.
Around 2013/2014 I added more languages and used third-party service to evaluate code online, but it was very difficult to do stdin/stdout with the services I was using, so I stuck with the same silly find-and-replace for languages like Python, Ruby, and eventually C++, C#, etc.
Fast forward to today, I run the code in my own containers, but never updated the way stdin/stdout works because people have gotten used to the weird hack (some people have even posted in forums explaining how to get around it).
I know it is not best practice and it isn't helpful for someone learning a new language to see hacks like this, but the idea was for new programmers to not worry about reading input at all and just focus on writing the algorithm to solve the problem. One common complaint about coding challenge sites years ago was that new programmers would spend a lot of time just figuring out how to read from stdin or read lines from a file, so I wanted new coders to avoid this problem on Coderbyte.
I'll be updating the entire editor page soon along with the default code and stdin reading for languages. Hopefully then C++ programmers will enjoy using Coderbyte more :)

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.

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.
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.

Related

How to output identification of template arg T at design-time compilation?

always had this question and never asked, and running into a internal compilation error with hundreds of types. I just want to output the name of T, while its actually designing the functions, design-time compilation.
seems utterly the easiest thing to implement in a compiler? pragma message, pragma type. these things call when its generating them, so i see the message print over and over.
with msvc, an xmacro to get the name didnt work. i didnt want to add that to this question but it should be known i tried that too..
template <typename T>
void abc(T v) {
/// not allowed (and i see no other pragmas?)
#pragma message(T) // i need to output something identifying int. doesnt have to be int but anything special even a hash or a size at the compilation stage here
}
int main(int argc, char *argv[]) {
abc(int(1));
return 0;
}
pragma is definitely outputting multiple times, its not like its some run-once thing. i see lots and lots of logs so its evaling with potential type name resolution. nothing at all available?
#pragma message(__PRETTY_FUNCTION__)
this prints what i need.. i tried __FUNCTION__ and that was just class::method, but this beauty gives:
struct ident *__cdecl ident::for_type<struct array<enum VkFormat>::adata,false>(void)
things like that.. and thats very valuable.. much more valuable than bifurcating through a million types.

What is the right way to parse large amount of input for main function in C++

Suppose there are 30 numbers I had to input into an executable, because of the large amount of input, it is not reasonable to input them via command line. One standard way is to save them into a single XML file and use XML parser like tinyxml2 to parse them. The problem is if I use tinyxml2 to parse the input directly I will have a very bloated main function, which seems to contradict the common good practice.
For example:
int main(int argc, char **argv){
int a[30];
tinyxml2::XMLDocument doc_xml;
if (doc_xml.LoadFile(argv[1])){
std::cerr << "failed to load input file";
}
else {
tinyxml2::XMLHandle xml(&doc_xml);
tinyxml2::XMLHandle a0_xml =
xml.FirstChildElement("INPUT").FirstChildElement("A0");
if (a0_xml.ToElement()) {
a0_xml.ToElement()->QueryIntText(&a[0]);
}
else {
std::cerr << "A0 missing";
}
tinyxml2::XMLHandle a1_xml =
xml.FirstChildElement("INPUT").FirstChildElement("A1");
if (a1_xml.ToElement()) {
a1_xml.ToElement()->QueryIntText(&a[1]);
}
else {
std::cerr << "A1 missing";
}
// parsing all the way to A29 ...
}
// do something with a
return 0;
}
But on the other hand, if I write an extra class just to parse these specific type of input in order to shorten the main function, it doesn't seem to be right either, because this extra class will be useless unless it's used in conjunction with this main function since it can't be reused elsewhere.
int main(int argc, char **argv){
int a[30];
ParseXMLJustForThisExeClass ParseXMLJustForThisExeClass_obj;
ParseXMLJustForThisExeClass_obj.Run(argv[1], a);
// do something with a
return 0;
}
What is the best way to deal with it?
Note, besides reading XML files you can also pass lots of data through stdin. It's pretty common practice to use e.g. mycomplexcmd | hexdump -C, where hexdump is reading from stdin through the pipe.
Now up to the rest of the question: there's a reason to go with the your multiple-functions example (here it's not very important whether they're constructors or usual functions). It's pretty much the same as why would you want any function to be smaller — readability. That said, I don't know about the "common good practice", and I've seen many terminal utilities with very big main().
Imagine someone new is reading 1-st variant of main(). They'd be going through the hoops of figuring out all these handles, queries, children, parents — when all they wanted is to just look at the part after // do something with a. It's because they don't know if it's relevant to their problem or not. But in the 2-nd variant they'll quickly figure it out "Aha, it's the parsing logic, it's not what I am looking for".
That said, of course you can break the logic with detailed comments. But now imagine something went wrong, someone is debugging the code, and they pinned down the problem to this function (alright, it's funny given the function is main(), maybe they just started debugging). The bug turned out to be very subtle, unclear, and one is checking everything in the function. Now, because you're dealing with mutable language, you'd often find yourself in situation where you think "oh, may be it's something with this variable, where it's being changed?"; and you first look up every use of the variable through this large function, then conditions that could lead to blocks where it's changed; then you figuring out what does this another big block, relevant to the condition, that could've been extracted to a separate function, what variables are used in there; and to the moment you figured out what it's doing you already forgot half of what you were looking before!
Of course sometimes big functions are unavoidable. But if you asked the question, it's probably not your case.
Rule of thumb: you see a function doing two different things having little in common, you want to break it to 2 separate functions. In your case it's parsing XML and "doing something with a". Though if that 2-nd part is a few lines, probably not worth extracting — speculate a bit. Don't worry about the overhead, compilers are good at optimizing. You can either use LTO, or you can declare a function in .cpp file only as static (non-class static), and depending on optimization options a compiler may inline the code.
P.S.: you seem to be in the state where it's very useful to learn'n'play with some Haskell. You don't have to use it for real serious projects, but insights you'd get can be applied anywhere. It forces you into better design, in particular you'd quickly start feeling when it's necessary to break a function (aside of many other things).

Ignoring Syntax Errors

I have a file that contains an arbitrary number of lines of c++ code, each line of which is self-contained (meaning it is valid by itself in the main function). However, I do not know how many, if any, of the lines will have valid c++ syntax. An example file might be
int length, width; // This one is fine
template <class T className {}; // Throws a syntax error
What I want to do is write to a second file all the lines that have valid syntax. Currently, I've written a program in python that reads each line, places it into the following form
int main() {
// Line goes here
return 0;
}
and attempts to compile it, returning True if the compilation succeeds and False if it doesn't, which I then use to determine which lines to write to the output file. For example, the first line would generate a file containing
int main() {
int length, width;
return 0;
}
which would compile fine and return True to the python program. However, I'm curious if there is any sort of try-catch syntax that works with the compiler so I could put each line of the file in a try-catch block and write it to the output if no exception is thrown, or if there's a way I can tell the compiler to ignore syntax errors.
Edit: I've been asked for details about why I would need to do this, and I'll be the first to admit it's a strange question. The reason I'm doing this is because I have another program (of which I don't know all the implementation details) that writes a large number of lines to a file, each of which should be able to stand alone. I also know that this program will almost certainly write lines that have syntax errors. What I'm trying to do is write a program that will remove any invalid lines so that the resulting file can compile without error. What I have in my python program right now works, but I'm trying to figure out if there is a simpler way to do it.
Edit 2: Though I think I've got my answer - that I can't really play try-catch with the compiler, and that's good enough. Thanks everyone!
Individual lines of code that are syntactically correct in the context of a C++ source file are not necessarily syntactically correct by themselves.
For example this:
int length, width;
happens to be valid either as part of a main function or by itself -- but it has a different meaning (by itself it defines length and width as static objects).
This:
}
is valid in context, but not by itself.
There is typically no way for a compiler to ignore syntax errors. Once a syntax error has been encountered, the compiler has no way to interpret the rest of the code.
When you're reading English text, adfasff iyufoyur; ^^$(( -- but you can usually recover and recognize valid syntax after an error. Compilers for programming languages aren't designed to perform that kind of recovery; probably the nature of C++'s syntax would make it more difficult, and there's just not enough demand to make it worth doing.
I'm not sure what your criterion for a single line of code being "correct" is. One possibility might be to write the line of code to a file, contained in a definition of main:
int main() {
// insert arbitrary line here
}
and then compile the resulting source file. I'm not sure that I can see how that would be particularly useful, but it's about the closest I can come to what you're asking for.
What do you mean by "each line is self-contained"? If the syntax of a line of C++ code is valid may depend largely on the code before or after that line. A given line of code might be valid within a function, but not outside a function body. So, as long as you can't define what you mean by "self-contained" it is hard to solve your problem.

Cannot understand a C++ line

I am reading a C++ code and came across a function:
double Nm_poissons_ratio(double /*Temp*/)
{
double PR(0.0);
PR = 0.31;
return PR;
}
I don't understand what is the effect of /* */ characters which surround the Temp variable.
Thanks
If you write
double Nm_poissons_ratio(double Temp)
the compiler will warning. about an unused variable.
In this case, the coder wanted to retain the signature for some reason, but to avoid the warning. He/she therefore put a comment to show what it originally was.
Why is this the signature? It's hard to know.
Perhaps this is an intermediate version of the code, and he/she plans to use this parameter in the future (this is actually an excellent case to retain the warning).
Perhaps it's passed as a callback to some function that expects a specific signature.
It means that the function takes a double argument, but they are commenting out the name (hence the /* */) because the argument to be named.
Likely because the compiler will warn them about an unused formal argument, since they do not use Temp anywhere in the function.
All that is happening is the developer is commenting out a piece of code. Basically a comment tells the computer to ignore this piece of code. So, if you were developing a programming you would:
/* This is hidden to everyone BUT the programmer. */

Simple c++ program gets compilation errors

When I'm trying to compile this code, it shows error:
main.cpp:19:3: error: invalid operands of types 'void' and 'int' to binary 'operator!='
This is the file:
#include <iostream>
#include <cstdio>
using namespace std;
#define $ DEBUG
#define DEBUG 1
#define _(out) do{ std::cout << __FILE__ << ":" << __LINE__ \
<< " " << out << '\n';}while(0)
#define _(out) printf(out);
int main(){
#ifdef LOCAL_PROJECT
#define DEBUG 0
#endif
$ && ({
_("eeeeewe");
});//line 19
return 0;
}
$ is simple name of DEBUG, in runtime it's 0 or 1.
The compilation error is for this source file.
how to get rid of this and compile?
There are some things you're doing here that are inadvisable, and some that are illegal. But I gave you an upvote for at least alerting me to a gcc extension I hadn't seen:
#include <iostream>
int main() {
int x = ({std::cout << "I'm surprised this prints "; 10 + 20;});
std::cout << x << "\n";
}
That does indeed output on IDEone I'm surprised this prints 30, even under C++14 settings. On coliru, though you get:
main.cpp:4:17: warning: ISO C++ forbids braced-groups within expressions [-Wpedantic]
Yet now that we've had our learning moment together, avoid non-standard extensions. Partly because people on StackOverflow will yell at you. But mostly for the reasons that life is hard enough trying to find terra firma in language development, education and usage when you stick to the subset that has been agreed upon and vetted by a large number of people who thought through the issues.
(The "language feature that one guy added that time for that project" is probably a bad idea--for any definition of "that one guy" or "that project".)
Also, something like that--being rarely used--probably has all kinds of lack of attention in the optimizer about getting that expression out. Which means at best it's slower than other ways, and at worst it has random bugs.
Moving on:
The use of $ in identifier names is apparently "implementation-defined behavior". Meaning there's nothing in the spec disallowing it...but nothing saying that a compiler has to implement it either. It's probably not something you want to be inventing new creative uses of, and only using if you're stuck in a situation bridging with old code on a VAX or something.
On the other hand, you simply you can't name any global variables or macros starting with an underscore. They are reserved for compiler implementations to use themselves. (If you read all that you'll see other unusual nuances, such as that you can't have identifiers beginning with an underscore and followed by a capital letter in ANY scope, although if the letter is lowercase you can define them locally. Often people use this for member variables but have to be careful to follow the rule.)
It's possible to use printf for purposes of compatibility...because of the explicit design to enable taking old C programs and slowly upgrade them to C++. But you shouldn't be writing new constructs or code using it, and if you want some basic philosophy on why then read the short paper Learning Standard C++ as a New Language. It's an old paper in its own right, but it's from Bjarne Stroustrup and works through that particular point pretty well.
Yet the "biggest" issue of why the approach is generally wrong is that there are much more reliable ways of doing this than trying to grab textual swaths of code into a macro. Many topics to study on that, such as the use of lambdas in C++11. But more generally you should focus on what appears to be your desire here, which is the subject area of logging. A quick search into a tag intersection could get you good advice on that:
Search Query for [c++] [logging] __FILE__
how to get rid of this and compile?
Introduce intermediate steps into the process.
Get rid of this...(code!)
Read through the links I've provided.
Look at approaches used to achieve this goal and assess what you like or don't like about them.
Write new code that uses better practices, or borrow from others.
...and compile. :-)
Remove the semicolon after the call to the macro, or just change the macro to remove the semicolon after printf(out).
Macros are especially inconvenient when they cause bugs like this. Because macros are directly substituted like a find+copy+paste, it can sometimes cause results that don't make sense.
#include <iostream>
#include <cstdio>
using namespace std;
#define $ DEBUG
#define DEBUG 1
#define _(out) do{ std::cout << __FILE__ << ":" << __LINE__ \
<< " " << out << '\n';}while(0)
#define _(out) printf(out);
int main(){
#ifdef LOCAL_PROJECT
#define DEBUG 0
#endif
$ && ({
_("eeeeewe")
});//line 19
return 0;
}