C++ command line args (file) not found? - c++

I have the following main method:
int main(string argf)
{
ifstream exprFile(argf);
string inExpr;
if (exprFile.is_open())
{
while ( getline(exprFile,inExpr) )
{
//do stuff
}
exprFile.close();
}
else cout << "Unable to open file";
system("pause"); // to wait for user input; allows the user to see what was printed before the window closes
return 0;
}
I have run this program from the command line using the following:
"C:\Complete Filepath\Project2.exe" "C:\Differnt Filepath\args.txt"
C:\Complete Filepath\Project2.exe C:\Differnt Filepath\args.txt
"C:\Complete Filepath\Project2.exe" "args.txt"
C:\Complete Filepath\Project2.exe args.txt
The last two with args.txt being in the same directory as the executable. All four gave the "Unable to open file" result. Attemping to print the argf value before doing anything with it yielded nothing at all. A completely blank print statement.
I then went into the Visual Studio 2010 options and added all variations of the args.txt file under the arguments section there with the file in different locations as well and nothing works.
What am I doing wrong?
How are you supposed to open a file passed as an argument on the command line?

int main ( int argc, char *argv[] )
This is correct way to get argument from main.
argc is number of arguments. argv is argument list.
Actual argument will start with index = 1. Value at index 0 will be always program name.
In your example,
"C:\Complete Filepath\Project2.exe" "C:\Differnt Filepath\args.txt"
argc = 2
argv[0] = "Project2.exe"
argv[1] = "C:\Differnt Filepath\args.txt"

Yay, code!
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char* argv[])
{
ifstream exprFile;
string inExpr;
for( int i = 1; i < argc; i++) { // 0 is the program name
exprFile.open(argv[i]);
if (exprFile.is_open()) {
while ( getline(exprFile,inExpr) ) {
cout << "Doing stuff on line: " << inExpr << "\n";
}
exprFile.close();
}
else cout << "Unable to open file " << argv[i];
}
}

Related

Recieve 3 files by terminal and concatenate the content of file2 and file3 to file1 using fstream

I'm begginer in C++, so may be parts of my code doesn't have sense, sorry.
What I have to do is (C++, Linux, by fstream):
· Receive 3 or more files passed by terminal by:
./executable file1.txt file2.txt file3.txt
· programm a function that read the files file2.txt and file3.txt and copy it to file1.txt (concatenate, don't overwrite)
I don't know how to do it, I don't know anything about fstream, I'm just learning now by myself, so I really need help. Maybe there are similar questions solved in SO, but I don't know how to solve my problem by them.
I attach the code I have. I don't know how to code the function, so it's empty.
Thank you so much.
I try doing:
void concat(char *argv[], int numberoffilesreceived){
char c;
towritethefiles.open(argv[0], ios::app);
for(int i=1; i<numberoffilesreceived; i++){
toreadthefiles.open(argv[i], ios::in);
while(!toreadthefiles.eof()){
toreadthefiles >> c;
towritethefiles<< c;
}
}
}
It compiles but doesn't work, the program freezes when you run it.
and I also try using std::copy by I don't understand how it works.
ifstream toreadthefiles;
ofstream towritethefiles;
void concat(char *argv[], int numberoffilesreceived);
int main(int argc, char *argv[]){
/* 1/2 The code from below to 2/2 it's only to prevent path errors when receiving the files (it works fine) */
const char directory[SIZE]="./";
int count_files=0;
char files[SIZE][SIZE];
for(int i=1; i<argc; i++){
strcpy(files[i], directory);
strcat(files[i], argv[i]);
count_files++;
}
/*2/2 to add ./ to the name files when passed by terminal: ./executable ./file1.txt ./file2.txt ./file3.txt */
/*check if received almost 3 files like required */
if(argc<3){
cout<< "Error, to few files entered" << endl;
getchar();
exit(1);
}
/*pass the files to the concat function*/
for(int i=1; i<argc; i++){
concat(&argv[i], count_files);
}
toreadthefiles.close();
towritethefiles.close();
return 0;
}
void concat(char *argv[], int count_files){
}
I think I see an issue with your concat() function. You are calling concat() for each of the files passed in. Then in the function, you are using count_files to run that loop again for the number of files passed in.
I would consider rewriting concat() function so that it looks like this:
void concat(std::ofstream& outputStream, char* fileToAppend)
{
std::ifstream in(fileToAppend);
if (!in) {
cout << "Error, cannot open file: " << fileToAppend;
return;
}
// Use std::getline to read each line in the input stream,
// then write it to the output stream!
string line;
while (std::getline(in, line)) {
outputStream << line;
}
}
The benefit being that you can reuse the function for appending a single input file to an existing output stream, and you wrap up the check to ensure the file exists (you may want something more sophisticated like returning true/false on the file being appended, or throwing an error, etc.).
In main(), you would replace the code after the check for at least three files with something like:
// Create an output stream with the first file
// ios::out- output flag
// ios::app- append flag
std::ofstream out(argv[1], ios::out | ios::app);
// Make sure the file exists!
if (!out) {
cout << "Error, cannot open file: " << argv[1];
exit(1);
}
// For all other arguments, concat with the first.
for (int i = 2; i < argc; i++) {
concat(out, argv[i]);
}
You can use std::copy with stream iterators, and I've revised my previous suspicion that it would be slow, so here's one way using doing just that with comments in the code.
#include <iostream>
#include <fstream>
#include <vector>
#include <ios>
#include <stdexcept>
void concat(const std::string& destination, const std::vector<std::string>& sources) {
// open the destination file and keep it open until all is done
std::ofstream dest_fs(destination, std::ios_base::binary);
if(!dest_fs)
throw std::runtime_error("Could not write to \"" + destination + "\".");
// loop over the source files
for(const auto& source_file : sources) {
// open the current source file
std::ifstream source_fs(source_file, std::ios_base::binary);
if(!source_fs)
throw std::runtime_error("Could not read from \"" + source_file + "\".");
// copy from source to destination
std::copy(std::istreambuf_iterator<char>(source_fs),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(dest_fs));
}
}
int cppmain(std::string program, std::vector<std::string> args) {
if(args.size() < 2) {
std::cout << "USAGE: " << program << " destination_file input_file(s)\n";
return 1;
}
// extract the first argument which is the destination file
std::string destination_file = std::move(args.front());
args.erase(args.begin()); // erase first argument from the vector
try {
// do the concatenation
concat(destination_file, args);
return 0;
} catch(const std::exception& ex) {
std::cerr << program << ": ERROR: " << ex.what() << "\n";
return 1;
}
}
int main(int argc, char* argv[]) {
return cppmain(argv[0], {argv + 1, argv + argc});
}

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

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';
}
}

Where do I put the filename for the program to read?

I have a C++ file that I would like to learn from but I am facing difficulty trying to open my text file which contains data to read. I am trying to figure out where do I put my text file.
My code is:
#include <fstream>
#include <cstdlib>
using namespace std;
void rFile(string argvFile);
void Init(int i, Chord& newChord);
int main(int argc, char* argv[]) {
if (argc != 2) {
cout << "INCORRECT SYNTAX!" << endl;
} else {
**//I changed the this to rFile("text.txt"); but error too.**
rFile(argv[1]);
}
}
void rFile(string argvFile) {
Chord newChord;
string inLine;
ifstream inFile;
**// I got an error trying to put the text file name after argvFile.c_str("text.txt"));**
inFile.open(argvFile.c_str());
if (inFile.is_open())
while (inFile.good()) {
getline(inFile, inLine);
}
} else {
cout << "ERROR! FOUND NOT FOUND!" << endl;
}
}
Can someone please kindly enlighten me?
This code reads filename from the program parameters,
rFile(argv[1]);
argv is an array of parameters passed to the program during its execution, so for example running
./prog a b c
assigns
argv[1] = "a"
argv[2] = "b"
argv[3] = "c"
the 0'th element (argv[0]) contains the program name, so in this case
argv[0] = "prog"
so in case of your program - once you compile it to the prog, you run it through (unix)
./prog PATH_TO_FILE
or (windows)
prog.exe PATH_TO_FILE

C++ fstream multiple input files

I am writing a simple program to take in two files. The terminal command line looks like this.
./fileIO foo.code foo.encode
When it runs, the second file is not read in. When I enter
./fileIO foo.code foo.code
it works. I can't seem to figure out why the second one is not opening. Any ideas? Thanks!
#include <fstream>
#include <iostream>
#include <queue>
#include <iomanip>
#include <map>
#include <string>
#include <cassert>
using namespace std;
int main( int argc, char *argv[] )
{
// convert the C-style command line parameter to a C++-style string,
// so that we can do concatenation on it
assert( argc == 3 );
const string code = argv[1];
const string encode = argv[2];
string firstTextFile = code;
string secondTextFile = encode;
//manipulate the first infile
ifstream firstFile( firstTextFile.c_str(), ios::in );
if( !firstFile )
{
cerr << "Cannot open text file for input" << endl;
return 1;
}
string lineIn;
string codeSubstring;
string hexSubstring;
while( getline( firstFile, lineIn ) )
{
hexSubstring = lineIn.substr(0, 2);
codeSubstring = lineIn.substr(4, lineIn.length() );
cout << hexSubstring << ", " << codeSubstring << endl;
}
//manipulate the second infile
ifstream secondFile( secondTextFile.c_str(), ios::in );
if( !secondFile )
{
cerr << "Cannot open text file for input" << endl;
return 1;
}
char characterIn;
while( secondFile.get( characterIn ) )
{
cout << characterIn << endl;
}
return 0;
}
One thing you might want to try is adding the close() call as is standard procedure after you're done using files. Sometimes issues arise with re-opening files if they were not closed properly in a previous run.
firstFile.close();
secondFile.close();
Also, you may try restarting the computer if there is some lingering file handle that hasn't been released.

Enter File Name When Executing Program In C++

I'm learning C++, then i was searching for some codes for learn something in the area that i love: File I/O, but i want to know how i can tweak my code for the user type the file that he wants to see, like in wget, but with my program like this:
C:\> FileSize test.txt
The code of my program is here:
// obtaining file size
#include <iostream>
#include <fstream>
using namespace std;
int main () {
long begin,end;
ifstream myfile ("example.txt");
begin = myfile.tellg();
myfile.seekg (0, ios::end);
end = myfile.tellg();
myfile.close();
cout << "size is: " << (end-begin) << " bytes.\n";
return 0;
}
Thanks!
In the example below argv contains command line arguments as null terminated string array and argc contains an integer telling you how many arguments where passed.
#include <iostream>
#include <fstream>
using namespace std;
int main ( int argc, char** argv )
{
long begin,end;
if( argc < 2 )
{
cout << "No file was passed. Usage: myprog.exe filetotest.txt";
return 1;
}
ifstream myfile ( argv[1] );
begin = myfile.tellg();
myfile.seekg (0, ios::end);
end = myfile.tellg();
myfile.close();
cout << "size is: " << (end-begin) << " bytes.\n";
return 0;
}
main() takes parameters:
int main(int argc, char** argv) {
...
ifstream myfile (argv[1]);
...
}
You could also get clever, and loop for each file specified on the command line:
int main(int argc, char** argv) {
for (int file = 1; file < argc; file++) {
...
ifstream myfile (argv[file]);
...
}
}
Note that argv[0] is a string pointing to the name of your own program.
Main takes two arguments, which you can use to do this. See this:
Uni ref
MSDN reference (has VC specific commands