Search code examples
c++pipecout

Passing the standard output of function A as the argument of function B in C++


I'm starting C++ and I'd like to code a linker

I first did a tokenizer executable that takes as an input a file and print in the standard output the list of its tokens

%./tokenizer input_file
Token 1 : 3
Token 2 : X
token 3 : 10
etc
...

Then, I programmed a linker executable that takes as an input a token file and print in the standard output the symbol table and memory map.

%./tokenizer input_file > temp
%./linker temp
Symbol Table :
X=10
etc
...

Memory Map :
000: 1002
etc
...

Now, my goal is to have a single executable that takes the input file "INPUT" and prints in the standard output the symbol table and memory map. It is important for me to respect this format.

I want :

%./linker input_file
Symbol Table :
X=10
etc
...

Memory Map :
000: 1002
etc
...

For now, I've copied the main() of the tokenizer inside the .cc of the linker (under a different name of course) but I don't know what to do next.

For example I'd like my code to basically look like : (i precise ifstream because that's how I wrote my code so it would help me to keep it that way)

int getTokens(char* file[]) {
   string token;
   ifstream _file (file);
   doStuff(_file);
   ....
   cout << token << endl;
   ....
}
int main(int argc, char argv*[]) {
   char* input_file[] = argv[1];
   ifstream tokenFile = convertCoutToIFSTREAM(getTokens(input_file))
   doOtherStuff(tokenFile);
   ...
   cout << linkResults << endl; 

I could make a shell script where I first run the tokenizer, saves its output in a file then run the linker on it but I'd like to find a way where I do not have to create a file in between.

Thank you very much for your help


Solution

  • A simple way would be to use streams

    You have to change

    void getTokens(char* file[]) {
       string token;
       ifstream _file (file);
       doStuff(_file);
       // ....
       cout << token << endl;
       // ....
    }
    

    into

    void getTokens(std::istream& in, std::ostream& out) {
       doStuff(in);
       // ....
       out << token << endl;
       // ....
    }
    

    And then you can chain the call. (not a real pipe, as whole function has to be finished before the other begins).

    void tokenizer(std::istream& in, std::ostream& out);
    void linker(std::istream& in, std::ostream& out);
    
    int main(int argc, char* argv[])
    {
        assert(argc > 1);
        std::ifstream in(argv[1]);
        std::stringstream ss;
        tokenizer(in, ss);
        linker(ss, std::cout);
    }
    

    Demo