Reputation: 183
I'm trying to figure out how to be able to read in a .txt file as a command prompt argument instead user input. If I have the program
#include <iostream>
#include "cmdline.h"
using namespace std;
int main (int cnt, char * args[]) {
int a = cmdline_int(args, 1);
int b = cmdline_int(args, 2);
cout << "sum = " << a << " + " << b << " = " << a + b << endl;
return 0;
}
where the file "cmdline.h" contains
#include <cstdlib>
#include <string>
using namespace std;
int cmdline_int( char* cmdline_a[], int n ) {
return atoi( cmdline_a[ n ] );
}
char cmdline_char( char* cmdline_a[], int n ) {
char c = cmdline_a[ n ][0];
return c;
}
I can run the program as
./program 3 5
and the output will be
sum = 3 + 5 = 8
however if I have a file (textfile.txt) that simply contains those same numbers in list form, i.e.
3
5
and try to run it as
./program < textfile.txt
I get
Segmentation fault
it does the same thing if textfile.txt contains "3 5", though its important that I use a text file in list form anyway. What do I need to change to make "./program textfile.txt" have the same output as "./program 3 5" ?
I'm guessing the problem lies between the int main parenthesis, I'm just not sure what specifically.
Upvotes: 5
Views: 12992
Reputation: 1
#include <stdio.h>
int main(int argc, char* argv[]) {
*//read from textfile one char at a time:*
char c;
while ((c=getchar()) != EOF){
*//Command line should look like:
//./program < textfile.txt*
printf("%c",c); //print char
}
return 0;
}
Upvotes: 0
Reputation: 15501
Run your program as:
./program myfile.txt
and use the argv[1]
command line parameter to accept the file name instead. Parse accordingly:
#include <iostream>
#include <fstream>
#include <string>
int main(int argc, char* argv[]) {
if (argc > 1) {
std::ifstream fs(argv[1]);
int a, b;
while (fs >> a >> b) {
std::cout << a << ' ' << b << '\n';
}
} else {
std::cout << "No arguments." << '\n';
}
}
Upvotes: 2
Reputation: 8491
Test program
When you want to check such things, I would recommend first understanding how the application receives them. I would start with the following minimal program:
int main (int argc, char * argv[]) {
for (int i = 0; i < argc; i++)
cout << argv[i] << endl;
return 0;
}
And execute it
./program 3 5
outputs:
./program
3
5
./program < textfile.txt
outputs:
./program
So now you can see that the issue is with how the txt
file is passed to the application. And the reason your application crashes is because you use the arguments without validating that they actually exist!
Explanation
The symbol (<) means opening the file up and attaching it to the standard input (cin) of your application.
./program < textfile.txt
is not related to the arguments, instead you have to read it from cin
.
Solution using arguments
Use
./program `cat textfile.txt`
The cat
command will "replace itself" with the contents of the file and it will work as if you manually wrote it.
Solution using < and cin
When running with ./program < textfile.txt
the following will print the numbers:
int a, b;
cin >> a >> b;
cout << a << endl;
cout << b << endl;
Combined solution
This will work for both:
int main (int argc, char * argv[]) {
int a, b;
if (argc == 1) { // No extra arguments, read from cin
cin >> a >> b;
} else { // Use args
a = cmdline_int(argv, 1);
b = cmdline_int(argv, 2);
}
// Do something with a,b
return 0;
}
Upvotes: 6
Reputation: 1279
You redirect the textfile.txt into your program, so you couldn't read it from the parameter directly.
You could read the file content from the redirect by using cin
char c;
while (std::cin.get(c))
{
// process char
}
Or, you could pass the filename as paramter like ./program textfile.txt, and read from the file
char* filename = args[1];
std::ifstream infile(filename);
int a = 0, b = 0;
infile >> a >> b;
Upvotes: 0