I'm fairly new to C++, I'm trying to figure out how to take in arguments from a text file and use them in my program.
So if I wanted to include a text file whatever.txt in a command, it would use specified lines as arguments.
Like if the text file looked like this:
1 2
and I wanted to use 1 and 2 from it, as arguments in my program.
So far from what I've gathered, I need something akin to this:
int main (int argc, char const *argv[]) {
to start, but not sure where to go from here.
I'm trying to mess around with certain stuff, but I'm still pretty new and outside of loops and things I can't do much with the language yet!
Short of giving you the code that will do this for you (which would ruin the fun of learning how to do these things), the steps I would follow would be:
Take one argument from the command line as the file name you want to read the information from. Think of running your script like this:
$ ./myscript whatever.txt
Then, argv[0]="./myscript" and argv[1]="whatever.txt".
Open the file (perhaps ifstream would be good for this).
Loop through each line of the file (maybe using getline to put each line into a string)
Parse each line of the file (I've seen stringstream used for filling variables from a string).
Hopefully that will help you along your way.
int main(int argc, char *argv[])
after retrieving files names in the main function you should open each file and retrieve its contents
Sample code
int main(int argc, char* argv[])
{
for(int i=1; i <= argc; i++) // i=1, assuming files arguments are right after the executable
{
string fn = argv[i]; //filename
cout << fn;
fstream f;
f.open(fn);
//your logic here
f.close();
}
return 0;
}
https://stackoverflow.com/a/30141375/3323444
argc is the number of arguments passed in to your program, argv is an array of character strings holding the names of arguments passed in.
at least there's one parameter passed in which is argv[0] which is name of program.
after building this code run it form a command prompt as:
main.exe data.txt
or simply DRAG AND DROP file "data.txt" on your main.exe
main.exe is your program, data.txt is text file containing data you want to use
#include<iostream>
#include<fstream>
int main(int argc, char* argv[])
{
char c;
if(argc < 2)
{
std::cout << "No file passed to program!" << std::endl;
return 1;
}
std::ifstream in (argv[1] , std::ios::in);
if(!in)
std::cout << "Unable to read file: " << argv[1] << std::endl;
while(in >> c)
std::cout << c << std::endl;
in.close();
std::cin.get();
std::cout << std::endl;
return 0;
}
Related
I have a txt file called test.txt that looks like this,
hi this is a test
and I have a c++ file called selection_sort.cpp that looks like this,
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
cout << argc << endl;
for (int i = 0; i < argc; i++) {
cout << argv[i] << endl;
}
return 0;
}
right now when I compile my program in my terminal with
g++ selection_sort.cpp -o selection_sort
and then try and print out all of of the arguments I am trying to pass using my code like this
./selection_sort < test.txt
but it only outputs
./selecton_sort
I would like it to output
./selection_sort
hi
this
is
a
test
What am I missing or doing wrong? I need to use the <.
What am I missing or doing wrong? I need to use the <.
This is a shell operator that sends the content of the file to the standard input of the application.
./app < text.file
Will read the file text.file and send the conent to the standard input of the application app. In C++ you can read the standard input via std::cin.
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
std::string word;
while (std::cin >> word) {
std::cout << word << "\n";
}
}
< in bash is used to redirect input. In other words, it redirects the standard input for your process to the file. However, command line arguments (e.g. argv arguments) are not read through standard input, so you cannot capture them from a file by redirecting input.
Rather, they are provided as arguments when running the command in bash to begin with. You can accomplish your goal like so:
./selection_sort $(cat test.txt)
cat is for concatenating files, but if you supply it just one file, it will just output the contents of the file through standard out. The $(x) operation will execute the x command in a subshell, capture its standard output (which in this case is the contents of the file), and then do variable substitution to replace $(x) with said contents.
Edit:
Or, you can just change the way the arguments are accepted, so that they are accepted via standard input. It depends on how you want to be able to run the program.
I want to get the input file name in advance, when my program is called, not have my program ask the user for the filename.
I've seen many examples where the program will ask the user for input like:
int main()
{
cout << "Enter file name: ";
cin.get();
//run program
return 0;
}
However, there are not many examples shown where the input is stated in the command line when the program is called:
int main(int argv, char* argc[])
{
ifstream inputfile;
inputfile.open(argc);
//run program
return 0;
}
In other words, the user would type something like this on the terminal:
$./program example.txt
Sorry if my question is like an ELI5 submission.
I think you guys might get the gist of what I am trying to do.
Use:
int main(int argc, char* argv[])
{
ifstream inputfile;
if(argc == 2)
inputfile.open(argv[1]);
else
cout<<"Please nenter filename as command line argument!\n";
//run program
return 0;
}
Here, argc and argv are called command line arguments.
The value of argc is equal to the number of command line arguments, which includes the filename of the executable file itself.
argv is an array of strings passed as command line arguments, where the name of the executable file is at argv[0] and the rest of the arguments follow that.
You need to use:
inputfile.open(argv[1]);
However, I suggest adding checks to the program.
int main(int argc, char* argv[]){
if ( argc < 2 )
{
cerr << "Not enough arguments.\n";
return EXIT_FAILURE;
}
// There is an argument. Use it.
ifstream inputfile;
inputfile.open(argv[1]);
//run program
return 0;
}
I try to understand the file reading in c++ and try to read a file that doesn't exist deliberately
//includes ommited
int main(int argc, char ** argv)
{
if(argc != 1)
throw std::exception();
std::ifstream file(argv[0]);
std::string content((std::istream_iterator<char>(file)), std::istream_iterator<char>());
std::cout << content.c_str() << std::endl;
}
DEMO
It prints the following:
ELF
Why is it supposed to mean? Do I just get UB by doing this? Since I'm a Java coder I expected that some exception will be thrown if we try to read a file that doesn't exist...
argv[0] contains path to your executable.
http://www.gnu.org/software/libc/manual/html_node/Program-Arguments.html
The file name of the program being run is also included in the vector as the first element; the value of argc counts this element.
Just try to print it's contents:
std::cout << argv[0] << std::endl;
You probably want to use argv[1].
"ELF" is the begin of file header of Executable and Linkable Format.
So I am making a program for a simple calendar app which reads in inputs from a file input.csv (its a text file with two columns which are seperated using commas and new lines for each command).
The first thing i want to do is count the number of lines from the input file, which is passed as the third argument in the command line, so I can make an array to hold each line separately but the function countLines always returns 0!
Project code:
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
//Prototypes
int countLines (ifstream& countfiles);
int countLines(ifstream& countfile)
//counts number of lines in file passed to function
{
string line;
int numberOfLines;
numberOfLines = 0;
//reads through each line until end of file
while(getline(countfile, line))
{
numberOfLines++;
}
return numberOfLines;
}
int main (int argc, char* argv[])
{
if(argc != 3) cout << "Usage: calendar.out datafile inputfile";
//Create input streams to both files
ifstream apptsfp;
ifstream inputfp;
//Open streams to both files
apptsfp.open(argv[2]);
inputfp.open(argv[3]);
int numberOfInputs=0;
numberOfInputs = countLines(inputfp)-1;
cout << "number of input commands: " << numberOfInputs << endl;
return 0;
}
Almost certainly because you are failing to open your input file.
inputfp.open(argv[3]);
if (!inputfp.is_open())
{
cerr << "failed to open input file " << argv[3] << '\n';
return 1;
}
Files can fail to open for all sorts of reasons, you should always check for this.
BTW don't use an array to hold the input lines, use std::vector<std::string>. Then you can use push_back to add the lines to the vector. This will be easier and more efficient because you won't have to read the file twice. What more could you ask for!
std::vector<std::string> lines;
std::string line;
while (getline(inputfp, line))
lines.push_back(line);
It seems you only want two arguments, not three as you say in the question (the "first" argument is the program name). This means that the input file is in argc[2] instead, and argv[3] is a NULL pointer.
This means that your open call will fail, but you do not check for that.
Your access to argv[3] is incorrect. The second file name (third arg, including the program name in arg[0]) is in slot 2 (the array is zero-based).
Try:
apptsfp.open(argv[1]);
inputfp.open(argv[2])
You are trying to access argv[3] which is null. Try this :-
int main (int argc, char* argv[])
{
if(argc != 3)
cout << "Usage: calendar.out datafile inputfile";
//Create input streams to both files
ifstream apptsfp;
ifstream inputfp;
//Open streams to both files
apptsfp.open(argv[1]);
inputfp.open(argv[2]);
int numberOfInputs=0;
numberOfInputs = countLines(inputfp)-1;
cout << "number of input commands: " << numberOfInputs << endl;
return 0;
}
I've been searching the internet for a while, but all I can find for file input in C++ is when you know the filename.
I'm trying to write a program to perform an addition of 2 numbers that are greater than 0 from a file, but without using scanf or cin. I want to load the file into memory, but all of the code I can find in regards to this situation requires knowledge of the filename. The file is formatted with 2 integers on a single line, separated by a space, and there are multiple lines of integers. The program will output the sum of the two numbers. I can easily do this with scanf, but if I were given a massive file, I would want to load it into memory (save mapping for later).
Loading the file into memory is giving me trouble, because I do not know the filename, nor how to find out, unless the user inputs the name of the file (not going to happen). I want the program to be executed like so, but using the most raw, and basic forms of C++ IO:
./myprog < boatloadofnumbers
How would I start my program to take the whole "boatloadofnumbers" as a file, so I can use more basic functions like read()? (also, what is the above method called? passing input?)
int main(){
int a,b;
while (scanf("%i,%i",&a,&b)>-1){
printf("%i\n",(a+b));
} //endwhile
return 0;
} //endmain
When the program is called as you state, then the content of boatloadofnumbers can be read from std::cin.
This method is called input redirection and is done by the shell, not your program.
Wiht input redirection the shell usually buffers the content of the file. That's a quite fast way to stream a file a single time through a computation.
It's not entirely clear how you're going to read a file when you don't know the filename. Presumably you don't know the filename at compile-time. That's okay, you can get this from the command-line at runtime, like this:
./myprog boatloadofnumbers
Then your filename is in argv[1] and you can access it using a std::ifstream.
If you're being given the input directly on stdin via redirection (such as ./myprog < boatloadofnumbers) you don't need a filename at all, you can just use std::cin.
The following main() will deal with both of these situations:
int main(int argc, char* argv[])
{
if (argc == 2)
{
std::cerr << "Reading from file" << argv[1] << std::endl;
std::ifstream ifs(argv[1]);
if (ifs)
{
sum_lines(ifs);
}
else
{
std::cerr << "Could not read from " << argv[1] << std::endl;
}
}
else
{
std::cerr << "Reading from stdin" << std::endl;
sum_lines(std::cin);
}
}
A sample sum_lines() may look a bit like this:
void sum_lines(std::istream& is)
{
int first = 0, second = 0;
std::string line = "";
while (std::getline(is, line))
{
std::istringstream iss(line);
if (is >> first >> second)
{
std::cout << first << " + " << second << " = " << first + second << std::endl;
}
else
{
std::cerr << "Could not parse [" << line << "]" << std::endl;
}
}
}
This doesn't care from where the input comes, so you can easily inject a std::istringstream for unit-testing. Also, this doesn't read the whole file into memory, just one line at a time, so it should deal with averybigboatloadofnumbers.
With shell redirection, your program can read from the standard input, which may be desirable. However, it may also be desirable to read from a file. It's easy to support both:
cat data > ./prog
./prog < data
./prog -f data
The first two are similar, and the contents of the file data are available from the program's standard input; the third line simply passes a command-line argument. Here's how we support this:
#include <cstdio>
#include <cstring>
void process_input(std::FILE * fp)
{
char buf[4];
std::fread(buf, 4, 1, fp);
// ...
}
int main(int argc, char * argv[])
{
std::FILE * fp = stdin; // already open!
if (argc >= 3 && 0 == std::strcmp(argv[1]. "-f"))
{
fp = std::fopen(argv[2], "rb");
if (!fp)
{
std::fprintf(stderr, "Could not open file %s.\n", argv[2]);
return 1;
}
}
process_input(fp);
if (fp != stdin) { std::fclose(fp); }
}
Equivalently, you can achieve something similar with iostreams, though it's a bit more roundabout to have a nice, universal reference:
#include <fstream>
int main()
{
std::ifstream ifp;
if ( /* as before */ )
{
ifp.open(argv[2], std::ios::binary);
if (!ifp) { /* error and die */ }
}
std::ifstream & infile = ifp ? ifp : std::cin;
process_input(infile);
}