I may call my program like this:
1. ./main solved.txt
2. cat unsolved.txt | ./main
3. cat unsolved.txt | ./main solved.txt
I am using this to know whether I need to read data from the pipe line or not on C POSIX Standard:
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <unistd.h>
int main( int argumentsCount, char* argumentsStringList[] )
{
std::stringstream inputedPipeLineString;
if( argumentsCount > 1 )
{
printf( "argumentsStringList[1]: %s", argumentsStringList[ 1 ] );
}
// If it is passed input through the terminal pipe line, get it.
if( !isatty( fileno( stdin ) ) )
{
// Converts the std::fstream "std::cin" to std::stringstream which natively
// supports conversion to string.
inputedPipeLineString << std::cin.rdbuf();
printf( "inputedPipeLineString: %s", inputedPipeLineString.str().c_str() );
}
}
But now I want to use the C++ 11 Standard, and my loved fileno
and isatty
are out of it. So there is an alternative to them on the C++ 11?
Related threads:
The problem is that when compiling with the -std=C++11
, the fileno
and isatty
are undefined on the stdio.h/cstdlib
because they are POSIX stuff. So, one solution would be to use -std=GNU++11
instead of -std=C++11
. But is it possible to write something else to compile using the -std=C++11
?
C++ POSIX Standard
As far as I know, there is no such thing. There is a C POSIX library, which is part of POSIX standard.
So there is an alternative to them on the C++ 11?
There is no alternative in standard C++ (not before C++11, so far not after either).
You will need to depend on POSIX to get the functionality that you need.
Even in POSIX, it is the unistd.h
which defines isatty
. You've neglected to include it in your program.
I'm not aware of a completely portable way to do this. As far as I know, standard C++ knows no information of where it's input comes from so you should just use isatty
if you are working on a posix system.
In C++17, you have the <filesystem>
header which has a std::filesystem::status()
function that returns a file_status
object. You can access its type through the type()
function, via the result for instance, and use a quick comparison to see if it's a type of your intended target.
One really naïve approach to this would be something like:
auto result {std::filesystem::status(fd)};
if (result.type() == std::filesystem::file_type::character)
{
// do some stuff in here
}
where fd is the file descriptor to check. The above isn't full proof since there's no additional checks, but if it's a character type, it can almost certainly be equated to a terminal.
If you have a compiler that supports C++17, <filesystem>
can be really handy
https://en.cppreference.com/w/cpp/filesystem/file_type
NOTE: I am just starting out with working with <filesystem>
so there may be some nuances I'm missing here and welcome any updates to the answer
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With