This question already has answers here:
launch an exe/process with stdin stdout and stderr?
(3 answers)
Closed 8 years ago.
I need some help on this subject.
I have a C++ .exe that I want to open with C++ and then write some arguments in the console.
Here is an example of what I want to do:
Lets assume an executable whatsyourage.exe with this code (in reallity, I don't have the corresponding code):
#include <iostream>
using namespace std;
int main()
{
int age = 0;
cout << "What's your age ?" << endl;
cin >> age;
cout << "You are " << age << " year !" << endl;
return 0;
}
and I want to do something like:
int main()
{std::string invit="21";
std::string chemin ="whatsyourage.exe";// in the same library
std::string const command = chemin+" "+ invit;
system(command.c_str());
}
I want to write the age (21).
Can someone please help me?
Here is the answer:
int main()
{std::string invit="21";
std::string chemin ="whatsyourage.exe";
FILE* pipe = _popen(chemin.c_str(), "w");
if (pipe == NULL) {
perror("popen");
exit(1);
}
fputs("30", pipe);// write the age into the pipeline
pclose(pipe); // close the pipe
}
The popen() function from POSIX does what you are looking for. It allows you to execute a program (like system) while getting a file handle on its input/output streams.
For Windows, if popen() is not available, you can use the CreatePipe() & co functions to do the same thing; check out this question for some pointers.
The second snippet you added is good, and the problem is with the first code. In order to handle the command line from a program, you have to define the main as int main(int numberOfArguments, char* arguments[]) (often people use the shorter version - main(int argc, char* argv[]), but you can name the arguments as you wish). Then, if you pass an argument to the function, it will be in argv[1], since argv[0] is always the path to the executable. So the first program should look like this:
int main(int numberOfArguments, char* arguments[])
{
if(numberOfArguments>=2)
cout << "You are " << arguments[1] << " year !" << endl;
else
cout << "Too few arguments passed!" << endl;
return 0;
}
Related
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.
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';
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am new to C++ and visual studio, can anyone please help me in creating an UI for below requirements?
Requirement: There is a .txt file which consists of 10 test cases. In the UI, I(tester) should be able to select his/her choice of test cases to run.
Try using a MFC project. You can find drop-down menus in GUI toolbox.
Learn further in MFC.
refer this - https://www.youtube.com/watch?v=6hSYZdvQ3s4&index=1&list=WL
Consider the possibility to use command line interface as the following template shows:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
// check that parameter is given in command line when program is run
if(argc != 2) // if number of parameters is insufficient
{ // explaine and stop
cout << "Please, run a program with parameter: name of file with testcases" << endl;
cout << "For example:" << endl << " " << argv[0] << " tests.txt" << endl;
return 1;
}
// try to open file with test cases
ifstream testfile;
testfile.open(argv[1], ifstream::in);
if( !testfile.is_open() )
{
cout << "ERROR: File " << argv[1] << " cannot be open!" << endl;
return 2;
}
// read test cases from file
string testCaseName;
char answer;
while( getline(testfile, testCaseName).good() )
{
if(testfile.eof())
{
break;
}
if(testCaseName.length() == 0)
{
continue;
}
cout << "Would you like to execute testcase " << testCaseName << " ? (Y/N): ";
cin >> answer;
if( answer == 'Y' || answer == 'y')
{
cout << "Test execution... " << endl;
// run test case
// . . .
// report test results
// . . .
}
}
return 0;
}
To run your test with such program you should type in the command line:
programname test_file.txt
I'm doing a C++ assingment for a class and I haven't used C++ in a decade so this might be something I'm missing that is simple; however ,I can't seem to figure it out.
I have a class I defined with a function that is producing no output; it looks like it's not even running and I don't have a clue why. Could someone point out my problem to me?
Issue: cout from the function getwords of the class readwords doesn't display any results.
Here is my class:
class readwords {
private:
char c;
//string aword;
public:
void getwords(std::istream& file) {
cout << "I got here" << std::flush;
/*while(file.good()) {
cout << "I got here\n";
c = file.get();
if(isspace(c)) cout << "\n"; //continue;
if(isalnum(c)) {
cout << c; //aword.insert(aword.end(),c);
}
}
*/
}
};
Which is being called from my main:
#include <fstream>
#include <stdlib.h>
#include "lab1.h"
using namespace std;
readwords wordsinfile;
words wordslist;
int main ( int argc, char *argv[] )
{
if ( argc != 2 ) {
// Looks like we have no arguments and need do something about it
// Lets tell the user
cout << "Usage: " << argv[0] <<" <filename>\n";
} else {
// Yeah we have arguements so lets make sure the file exists and it is readable
ifstream ourfile(argv[1]);
if (!ourfile.is_open()) {
// Then we have a problem opening the file
// Lets tell the user and exit
cout << "Error: " << argv[0] << " could not open the file. Exiting\n";
exit (1);
}
// Do we have a ASCII file?
if (isasciifile(ourfile)) {
cout << "Error: " << argv[0] << " only can handle ASCII or non empty files. Exiting\n";
exit(1);
}
// Let ensure we are at the start of the file
ourfile.seekg (0, ios::beg);
// Now lets close it up
ourfile.close();
}
// Ok looks like we have past our tests
// Time to go to work on the file
ifstream ourfile2(argv[1]);
wordsinfile.getwords(ourfile2);
}
Thank you for any help you can provide.
Try to use a debugger. Most IDEs (NetBeans, Code::Blocks, etc) provide an interactive interface with gdb.
I just compiled and ran your code, but nothing wrong with the code itself,
except that I needed to include to use the 'cout' method.
"I got here" has been successfully displayed in my ubuntu machine.
What is your execution environment? You should check it first.
The problem appears to be redefining my own class. When actually coding the function I needed to use:
in readwords::countwords(std::istream& file) {
....
}
Once doing this output produced fine.
Problematic code:
#include <array>
#include <iostream>
#include <cstring>
int main(int argc, char *argv[])
{
using namespace std;
cout << "Read from file:" << endl;
while (!cin.eof())
{
array<char, 16> l_array;
cin.read(l_array.data(), l_array.size());
cout.write(l_array.data(), cin.gcount());
}
cout << endl;
cout << "Read from keyboard:" << endl;
cin.rdbuf(cout.rdbuf());
while (!cin.eof())
{
array<char, 64> l_array;
memset(l_array.data(), 0, l_array.size());
cin.read(l_array.data(), l_array.size());
cout << "===== DATA =====" << endl;
cout << l_array.data() << endl;
cout << "================" << endl;
}
}
This is how i run my program:
./application < file.txt
I can read data from pipe without problems but when i want to read it again it is still asociated with pipe. I have no idea how to switch it back. I have found 'rdbuf' function which can change it, but I have no idea how to use it.
I only found examples when you stard with keyboard switch to file and back to keyboard.
Like here: http://www.cplusplus.com/reference/iostream/ios/rdbuf/
But i don't have streambuf remembered so I can't do it like they did. I want to write program which can read most of data from file, and ask only when something is missing or just to ask user in runtime about permision or something. All inside console under linux.
#EDIT
Thank you for help, I post solution
class RedirectCinToConsole
{
protected:
std::ifstream m_console;
std::streambuf *m_oldCin;
bool m_success;
public:
RedirectCinToConsole() :
m_oldCin(0),
m_success(false)
{
m_console.open("/dev/tty");
if (m_console.is_open())
{
m_success = true;
m_oldCin = std::cin.rdbuf(m_console.rdbuf());
}
}
virtual ~RedirectCinToConsole()
{
if (m_oldCin)
{
std::cin.rdbuf(m_oldCin);
}
m_console.close();
}
operator bool () const { return m_success; }
};
int main()
{
RedirectCinToConsole l_redirect;
if (l_redirect)
{
std::string l_helloWorld;
std::cin >> l_helloWorld;
std::cin.ignore();
std::cout << l_helloWorld;
}
return 0;
}
It occurs to me that, regardless of the proposed solutions, the easiest
solution (and probably the best) would be to do things the opposite:
don't redirect the input, but pass the filename to the program, and let
it open an std::ifstream to read it, keeping std::cin free for
interactive input.
Ben Voigt has suggested the standard Unix solution, but on thinking
about it, it seems the above is more natural; it is certainly easier and
more portable.
Perhaps you should use fstream to create your own stream and either ask for a file name or take the file name as a command-line parameter. This will leave cin available for other input operations.
Try opening /dev/tty. This will be your process's associated console, if there is any. If your process was started from a daemon, it could fail.