I am new at C/C++,
So basically I want to call an .exe file that displays 2 numbers and be able to grab those two numbers to use them in my code.
To call the .exe file I've used the system command, but I am still not able to grab those two numbers that are displayed by the .exe file
char *files = "MyPath\file.exe";
system (files);
I think this is better aproach:
Here you just create new process, and you read data that process gives you. I tested this on OS X 10.11 with .sh file and works like a charm. I think that this would probably work on Windows also.
FILE *fp = popen("path to exe","r");
if (fp == NULL)
{
std::cout << "Popen is null" << std::endl;
}else
{
char buff[100];
while ( fgets( buff, sizeof(buff), fp ) != NULL )
{
std::cout << buff;
}
}
You need to escapr back slashes in C++ string literals so:
// note the double "\\"
char* files = "MyPath\\file.exe";
Or just use forward slashes:
char* files = "MyPath/file.exe";
Its not very efficient but one thing you can to with std::system is redirect the output to a file and then read the file:
#include <cstdlib>
#include <fstream>
#include <iostream>
int main()
{
// redirect > the output to a file called output.txt
if(std::system("MyPath\\file.exe > output.txt") != 0)
{
std::cerr << "ERROR: calling system\n";
return 1; // error code
}
// open a file to the output data
std::ifstream ifs("output.txt");
if(!ifs.is_open())
{
std::cerr << "ERROR: opening output file\n";
return 1; // error code
}
int num1, num2;
if(!(ifs >> num1 >> num2))
{
std::cerr << "ERROR: reading numbers\n";
return 1; // error code
}
// do something with the numbers here
std::cout << "num1: " << num1 << '\n';
std::cout << "num2: " << num2 << '\n';
}
NOTE: (thnx #VermillionAzure)
Note that system doesn't always work everywhere because unicorn
environments. Also, shells can differ from each other, like cmd.exe
and bash. – VermillionAzure
When using std::system the results are platform dependant and not all shells will have redirection or use the same syntax or even exist!
Related
I'm trying to make a program that moves a file (like file.txt) specified by the user to a directory that he also specifies. I tried using the move() function, however I don't quite understand it yet, so I tried with the rename() function and used this site's code as help.
I've worked with the rename() function and moved a file like this:
char oldDir[] = "C:\\Users\\MyName\\file.txt";
char newDir[] = "C:\\Users\\MyName\\New folder\\file.txt";
if (rename(oldDir, newDir) != 0)
perror("Error moving file");
else
cout << "File moved successfully";
And that worked perfectly, if I typed in the directory correctly. The thing is that I would like to tell the user to type in the directory of a file to move to another directory, so I tried this:
char oldDir[] = " ";
char newDir[] = " ";
cout << "Type file directory: "; cin >> oldDir;
cout << "Type file directory to move to: "; cin >> newDir;
if (rename(oldDir, newDir) != 0)
perror("Error moving file");
else
cout << "File moved successfully";
But, when typing in the console the oldDir path like: C:\\Users\\MyName\\file.txt, I always get the error:
Error moving file no such file or directory
It returns before I can even type the newDir path. Of course the file.txt is in C:\Users\MyName.
What could be the problem? I tried to remove the " " from the oldDir and newDir variables, but then I get another error:
incomplete type is not allowed
What am I doing wrong?
First off, don't double up on the slashes when typing them in at the command prompt at runtime, if that is what you are doing. Escaping slashes only applies to string literals in code, not runtime data.
That said, you are not allocating enough memory to hold the user's input. When initialized with " ", your oldDir[] and newDir[] arrays are each only 2 chars in size. When you drop the " ", the compiler no longer knows how large to make the array, since you are not telling it which size to use.
You need to handle the arrays more like this instead:
char oldDir[MAX_PATH] = "";
char newDir[MAX_PATH] = "";
std::cout << "Type file directory: ";
cin.getline(oldDir, MAX_PATH); // paths can contain spaces!
std::cout << "Type file directory to move to: ";
cin.getline(newDir, MAX_PATH); // paths can contain spaces!
if (rename(oldDir, newDir) != 0)
perror("Error moving file");
else
std::cout << "File moved successfully" << std::endl;
However, you really should be using std::string instead:
std::string oldDir, newDir;
std::cout << "Type file directory: ";
std::getline(cin, oldDir); // paths can contain spaces!
std::cout << "Type file directory to move to: ";
std::getline(cin, newDir); // paths can contain spaces!
if (rename(oldDir.c_str(), newDir.c_str()) != 0)
perror("Error moving file");
else
std::cout << "File moved successfully" << std::endl;
If you are using C++17 or later, consider using std::filesystem::rename() instead of ::rename():
#include <filesystem>
std::string oldDir, newDir;
std::cout << "Type file directory: ";
std::getline(cin, oldDir); // paths can contain spaces!
std::cout << "Type file directory to move to: ";
getline(cin, newDir); // paths can contain spaces!
std::error_code err;
std::filesystem::rename(oldDir, newDir, err);
if (err)
std::cerr << "Error moving file: " << err.message() << endl;
else
std::cout << "File moved successfully" << std::endl;
My program use a small SQLite3 database. To make sure it actually exist when the program is launched, I have a database creation script in a file, that is executed.
The script work without problem.
However, when using C++ I/O functions to read from that file, I am getting really often invalid characters at the end of my file, which result in the script containing errors and not being properly executed by the SQLite library. Here is an example when displaying the buffer content:
// Proper content from the file, then a random character is there
1
Error executing request: near "1": syntax error
Other characters also appear, whitespaces, numbers, letters...
Here is the code where I load my script :
std::cerr << "Creating database if needed...\n";
char sql_script[] = "/path/to/script.sql";
int script_length;
bool result = false;
std::ifstream script_fs(sql_script, std::fstream::binary | std::fstream::in);
if (script_fs) {
char* buffer;
char** err_msg = NULL;
script_fs.seekg(0, script_fs.end);
script_length = script_fs.tellg();
script_fs.seekg(0, script_fs.beg);
buffer = new char[script_length];
script_fs.read(buffer, script_length);
std::cout << "sql:\n" << buffer << "\n";
if (sqlite3_exec(m_db, buffer, NULL, NULL, err_msg) == SQLITE_OK){
result = true;
} else {
std::cerr << "Error executing: " << sqlite3_errmsg(m_db) << "\n" << err_msg << "\n";
}
delete buffer;
script_fs.close();
} else {
std::cerr << "Error opening script: " << strerror(errno) << "\n";
}
return result;
}
Why is this happening and how can I fix this ?
You need to make sure that you have a null-terminated string.
Allocate memory for one more character.
Assign the null character to the last element of buffer.
buffer = new char[script_length+1];
script_fs.read(buffer, script_length);
buffer[script_length] = '\0';
Also, use the array form of delete.
delete [] buffer;
Don't mix C and C++, If you want to read sql query file in C++ using ifstream then below code in C++ can be one approach in which you don't need to manage memory, take care of things like allocating one extra char of '\0' etc. :
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int main() {
ifstream fin("test.sql", std::fstream::binary | std::fstream::in);
std::string sqlquery = std::string(std::istreambuf_iterator<char>(fin), std::istreambuf_iterator<char>());
std::cout<<sqlquery<<std::endl;
return 0;
}
So, quick question:
I am tasked with making a program that reads in a file, does some fancy things, and writes out to an html file with the re-purposed text, all simple stuff.
Furthermore the program must be able to accept up to four command line arguments (but a minumum of two). The executable of course, the file it is reading in, the file name it will be reading out to, and finally a "-r" argument for more information on the file (the amount of paragraphs, etc).
So the question I have is as follows:
the "-r" argument can be anywhere in the arguments (as long as it comes after argv[0] of course), or it can be completely non-existent (as can the output file name).
This is still simple to do, a little tedious writing a bunch of if's or even a switch or two, but I can't help but think that there may be an easier way to accomplish this, rather than having a plethora of if statements.
Any help would be greatly appreciated. (I also suppose you don't need any code considering I don't exactly have a problem.)
Here is roughly how one might do it without a library:
GCC 4.8.2: g++ -Wall -Wextra -std=c++0x main.cpp
#include <iostream>
#include <string>
int main(int argc, char* argv[]) {
char* input = nullptr;
char* output = nullptr;
char* r_arg = nullptr;
--argc; ++argv; // Skip the program name.
const char* def_in = "default in";
const char* def_out = "default out";
const char* def_r = "default r";
while (0 < argc) {
if (std::string(argv[0]) == "-r") {
// This code requires a space after the "-r", which is unusual.
++argv;
--argc;
r_arg = argv[0]; }
else if (input == nullptr) {
input = argv[0]; }
else if (output == nullptr) {
output = argv[0]; }
else {
std::cerr << "error: unexpected arg '" << argv[0] << "'\n"; }
++argv;
--argc; }
if (input == nullptr) {
input = const_cast<char*>(def_in); }
if (output == nullptr) {
output = const_cast<char*>(def_out); }
if (r_arg == nullptr) {
r_arg = const_cast<char*>(def_r); }
std::cout << "input: " << input << "\n"
<< "output: " << output << "\n"
<< "r arg: " << r_arg << "\n";
return 0; }
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.
Actually, I'm working on a minishell. My functions work, but when I want to log the whole cin stuff (commands, parameters, output) into a file, nothing appears in the file. Nowhere can I find something to handle with full input and output with parameters.
I hope someone can help me.
My code:
using namespace std;
ofstream outputFile;
void read_command(char *com, char **par){
fprintf(stdout, "$");
cin >> com;
outputFile.open("logging.txt"); // file opened but nothing APPEARS IN IT????
if(strcmp(com,"date")== 0){ // DATE
time_t rawtime;
time ( &rawtime );
printf ( "%s", ctime (&rawtime) );
}
else if(strcmp(com,"echo")== 0) // ECHO
{
string echo_part;
cin >> echo_part;
cout << echo_part << endl;
}
else if(strcmp(com,"sleep")== 0){ // SLEEP
int howlong = 0;
cin >> howlong;
cout << "seconds: " << howlong << "....zZZzzZzz" << endl;
sleep(howlong);
}
else if(strcmp(com,"ps")== 0) // PROCESS
{
execlp("/bin/ps","ps","-A",NULL); // ps - command
}
}
void handler(int p) { // CTR-C handler
cout << endl;
cout << "Bye !" << endl;
outputFile.close();
alarm(1); // 2 seconds alarm ends process with kill
}
int main(){
int childPid;
int status;
char command[20];
char *parameters[60];
signal(SIGINT,&handler); // CTR-C exit disabled
while (1) {
read_command(command, parameters);
if ((childPid = fork()) == -1) {
fprintf(stderr,"can't fork\n");
exit(1);
}
else if (childPid == 0) { //child
execv(command, parameters);
exit(0);
}
else { // parent process
wait(&status);
}
}
}
You re-open the output stream outputFile for every line, overwriting the file with each new command.
Edit: As the other posters noted, not actually writing something to outputFile might be a second reason.
You open outputFile, but never write anything to it. What should appear there?
To output something to the file, try
outputFile << something
there are no
outputFile << ...;
so you are not writing to the file
Your code contains a lot of potential memory access violations.
There are libraries to help you in what you are trying to do (reading and interpreting user input), for instance the GNU Readline library, which is coded in C (but can be used by C++ code, as is the case for all the C-written libraries).
There are some nice C++ wrappers, such as for instance SReadlineWrapper.