'Continuous' C++ output of one executable as Input to another program - c++

I am trying to pass the output generated by one executable as input into another. I have been able to send in one line at a time.
The problem is when I try to send in a 'sequence of lines generated in a while loop' from Program1 to be read as input by Program2. I tried piping the executables in terminal (as given below), but it fails to work.
./Program1 | ./Program2
./Program1 |xargs ./Program2
./Program1 > ./Program2
I want to avoid File I/O.
Note:
Platform : Linux
==================
Something along the lines of the following example
Program1 (Writing to Terminal)
int main(int argc, char *argv[])
{
int i = 2200;
while(1){
printf("%d \n", i);
i++;
}
}
Program2 (Reading from Terminal, the output of Program1)
int main(int argc, char *argv[])
{
while(1){
// Read 'i' values
cout << "There are " << argc << " arguments:" << endl;
// Loop through each argument and print its number and value
for (int nArg=0; nArg < argc; nArg++)
cout << nArg << " " << argv[nArg] << endl;
}
return 0;
}

The problem is that you are trying to read the program arguments. But when you pipe from one program to the next the output from the first program becomes the standard input (std::cin) of the second program.
Try this for program 2:
#include <string>
#include <iostream>
int main()
{
std::string line;
while(std::getline(std::cin, line)) // read from std::cin
{
// show that it arrived
std::cout << "Line Received: " << line << '\n';
}
}

Related

Trying to make something write to a file in c++

I tried programming a file writer, but when i try to write to a file with something that has multiple words it will suddenly create files.
My code
#include <fstream>
#include <iostream>
#include <unistd.h>
int main(int argc, char *argv[]) {
char cwd[256];
while (true) {
getcwd(cwd, 256);
std::string cwd_s = (std::string)cwd;
std::string Input;
std::cout << cwd_s << "> ";
std::cin >> Input;
std::ofstream file(Input);
std::cout << "cmd /";
std::cin >> Input;
file << Input;
};
for (int i; i < argc; i++) {
std::cout << argv[i] << '\n';
};
return 0;
}
I expected to get this:
C:\Users\code> File.txt
cmd /hello world!
File.txt
hello world!
But it only had "hello", it created another file named world!
I have tried changing the code, but to no avail.
So I have wrote this code that I think does what you expect. The behavior you were seing is because you used the same string to store the filename and the user input. Also you redefined a new file every loop (without closing the previous one). I added a signal handler since if you press Ctrl+C the program would quit without saving/closing the file.
I added comments about how you can make a better CLI interface (if you're interested)
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
std::ofstream outfile;
void signalHandler(int signum) {
outfile.close();
exit(signum);
}
int main() {
char cwd[256];
if (getcwd(cwd, sizeof(cwd)) != NULL) {
std::cout << cwd << "> ";
} else {
std::cerr << "Error: Could not get current working directory." << std::endl;
return 1;
}
std::string filename;
std::getline(std::cin, filename);
outfile.open(filename);
// We intercept the Ctrl+C signal to close the file before exiting. Else nothing will be written to it.
// You can also use Ctrl+D (EOF: End Of File) to exit the program.
// The best praticte would be to implement a command line interface with a "quit" command. (like a map<string, function> for example)
signal(SIGINT, signalHandler);
// Another good practice is to check if the file did open correctly.
if (!outfile.is_open()) {
std::cerr << "Error: Could not open file for writing." << std::endl;
return 1;
}
std::cout << "cmd / ";
char ch;
while (std::cin.get(ch)) {
outfile.put(ch);
if (ch == '\n') {
std::cout << "cmd / ";
}
}
outfile.close();
return 0;
}
Hope it will help you ! And if you have any question about the code feel free to ask I'll explain !

How do I handle empty files when dumping ifstream to cout?

I'm trying to dump the contents of a file to cout.
#include <iostream>
#include <fstream>
int main(int argc, char** argv)
{
if (argc > 1) {
std::ifstream fin(argv[1]);
if (fin) {
std::cout << "---file contents---\n";
std::cout << fin.rdbuf();
std::cout << "---end contents---\n";
} else {
std::cout << "The file does not exist\n";
}
}
else {
std::cout << "Usage: " << argv[0] << " FILE\n";
}
if (std::cout.good()) {
return 0;
}
else if (std::cout.fail()) {
return 1;
}
else {
return 2;
}
}
This code does not work as intended when the input file is empty. It prints the initial "---file contents---", but never prints the trailing "---end contents---". After debugging, I found the application is not crashing, but instead is putting std::cout in an error state (the return code is 1).
How can I print the contents of an empty file without putting cout in an error state?
This operator<< reference (overload number 10 in the list) explains it all:
If no characters were inserted, executes setstate(failbit).
Since the input file is empty, there's no characters to insert into the output stream. And the failbit is set.
You need to add a specific check for failbit after
std::cout << fin.rdbuf();
to see if the input file was empty or not.

unexpected getline behavior

Originally was trying to read data using char* but switched to string cause was getting behavior as if there was a missing null terminator. made the problem minimal below but still getting very weird output
int main(int argc, char * argv[]){
// file one: flightData
std::ifstream inFile1(argv[1]);
if (!inFile1.is_open())
{
std::cout << "Could not open the file 1." << std::endl;
return -1;
}
// file two: flightPlans
std::ifstream inFile2(argv[2]);
if (!inFile2.is_open())
{
std::cout << "Could not open the file 2." << std::endl;
return -1;
}
//File three: output
std::ofstream outputfile(argv[3]);
if (!outputfile.is_open())
{
std::cout << "Could not open the output file" << std::endl;
return -1;
}
std::string buffer;
getline(inFile1, buffer);
std::cout<<buffer<<std::endl;
while (getline(inFile1, buffer)) {
std::cout<<buffer;
std::cout<<"help";
}
// flightPlanner system(inFile1);
// system.printF();
// system.planFlights(inFile2,outputfile);
return 0;
}
output is
4
helpDallas|Austin|50|50help
which i'm pretty sure is incorrect, interestingly when i add endl to cout buffer it gives me output i would expect not really sure whats going on
inFile1
4
Dallas|Austin|50|50
Dallas|Austin|50|50
Dallas|Austin|50|50
Dallas|Austin|50|50
When i run in debugger i get the output i expect:
4
Dallas|Houston|50|50
helpDallas|Houston|50|50
helpDallas|Houston|50|50
helpDallas|Houston|50|50help
any idea what could be going on?
Do you need flushing your stdout?
std::cout << std::flush;
Any chance your shell ate your outputs?
Try pipping the output to "cat -A":
./a.out | cat -A
(Drive by comment - I may not know what I'm talking about ^_^)

Taking a filename as an input while running a program I compiled in cpp

In cpp, I need to run a program like this
g++ *.cpp -o out
./out <input.txt> <somenumber>
where input.txt is a text file containing lines of information I need to proccess, and somenumber is an integer value I need to use.
I am searching for hours and couldn't find the answer I was looking for,
I found solutions that work like
./out < input.txt
reads the input.txt line as a string which then in the code I can process,
but the assignment says that the code will be run only and specifically as
./out <input.txt> <somenumber>
can anyone help ?
I have wrote some code, in which I wrote my main as
int main(int argc, char* argv[] ){
but when I run
./out <input.txt>
the terminal gives an error saying
" -bash: syntax error near unexpected token `newline' "
edit: typo
You are correct in wanting to accomplish this using argc and argv. Something like this should work
#include <iostream>
#include <string>
int main(int argc, char* argv[]) {
std::string file_name;
std::string number;
if(argc == 3) {
file_name = argv[1];
number = argv[2];
}
std::cout << "Filename: " << file_name << " number: " << number << "\n";
}
By convention, the use of < > to enclose an input parameter signifies that the parameter is mandatory for the command.
Therefore, the command
./out <input.txt> <some_number>
signifies that the two parameters - input.txt and some_number are mandatory.
The command can be run as:
./out input.txt 101
Here is an example of working code:
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
string inputFile;
string someNumber;
if(argc != 3) {
cout << "Sorry! Wrong input \n";
cout << "Usage: ./out <input_file_name> <some_number> \n";
return -1;
}
inputFile = argv[1];
someNumber = argv[2];
cout << "Processing ...\n";
cout << "File = " << inputFile << ", Number = " << someNumber << "\n";
return 0;
}
Output:
$ ./out input.txt 101
Processing ...
File = input.txt, Number = 101

Passing contents of file as argument into C++ program

Using C++, need to pass the contents of a file to the program as an argument à la $ ./main <filename.txt or $ echo the contents of the file | ./main
I want to be able to access the contents of the file as a variable or something so I can manipulate further.
I have this basic listing including some of the stuff I've been trying. The data doesn't seem to be in argv (my runs always tell me I have one argument). What is the way to access a command line argument passed in this way?
#include <fstream>
#include <iostream>
int main(int argc, char **argv)
{
std::cout << "Have " << argc << " arguments:" << std::endl;
for (int i = 0; i < argc; ++i) {
std::cout << argv[i] << std::endl;
}
std::istream* input = &std::cin;
if(argc > 1) {
std::cout << input;
std::cout << "more than argument found\n";
}
std::string inputs;
std::cout<< "1:\n";
std::cout<< argv[0];
std::cout<< "\n2:\n";
std::cout<< argv[1];
std::cout<< "\n3:\n";
std::cout<< input;
std::cout<< "\nEnd\n";
return 0;
}
EDIT
I perhaps wasn't entirely clear, given it was a fairly fundamental question I was asking but didn't realize. Essentially, passing using $ ./main <filename.txt is non-negotiable. User RPGillespie's comment pointed me in the right direction. The pipe sends it to stdin (which I didn't realize). Thus I wanted to handle the data using cin. A minimal working example would be
int main() {
// read input
for (std::string line; std::getline(std::cin, line);) {
std::cout << line << std::endl;
}
return 0;
}
cat file | ./main will pipe the file content to the input of the ./main, not the argument.
If you want to pipe arguments in this way, use xargs:
cat file | xargs ./main
While #liliscent has a great solution, the following also works (I am mentioning it for the sake of completeness and since I feel it is more readable):
./main $(cat file)
This takes the contents of the file called file (since it interprets the command inside the $( and )), and passes them as arguments to ./main.