Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know when there is input through the terminal pipe line on C++ 11?

Tags:

c++

posix

c++11

How to know when there is input through the terminal pipe line on C++ 11?

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:

  1. checking data availability before calling std::getline
  2. Why does in_avail() output zero even if the stream has some char?
  3. Error "'fdopen' was not declared" found with g++ 4 that compiled with g++3
  4. stdio.h not standard in C++?
  5. error: ‘fileno’ was not declared in this scope
  6. GoogleTest 1.6 with Cygwin 1.7 compile error: 'fileno' was not declared in this scope

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?

like image 612
user Avatar asked Oct 29 '16 21:10

user


3 Answers

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.

like image 57
eerorika Avatar answered Oct 14 '22 04:10

eerorika


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.

like image 33
gowrath Avatar answered Oct 14 '22 02:10

gowrath


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

like image 26
Ryan McCullough Avatar answered Oct 14 '22 02:10

Ryan McCullough