0

I am trying to use input redirection to scan a file for regular expressions and output those regular expressions with the line number of the file to a new output text file. The output text file is to be the name of the file that was used for the input redirection with ".txt" appended to it. For instance if the program was run as follows:

./scanRegex < scanThisFile.log

Then the output file should be called

scanThisFile.log.txt

I created a simple program as follows ( minus the regex scanning to isolate the issue ).

main.cpp

    #include <iostream>
    #include <ios>
    #include <fstream>
    #include <string>
    #include <vector>

    int main( int argc, char* argv[] )
    {
       std::string fileName = argv[1]; //<---===== ??????
       std::string txt = ".txt\n";
       char outputFile[100];

       for( int i = 0; i < fileName.length(); ++i ){
         outputFile[i] = fileName[i];
       }
       for( int i = fileName.length(); i < fileName.length() + 4; ++i ){
         outputFile[i] = txt[i - fileName.length()];
       }

       std::ofstream outfile;
       outfile.open(outputFile);

       outfile << "It works!!";

       outfile.close();
    }

When I use

argv[ 0 ]

the program runs but the filename is wrong for what my intention is but is understandable because the program name is the first argument for argv: a.txt

When I use

argv[ 1 ]

I get the following runtime error:

osboxes@osboxes:~/Desktop/ps7$ ./a < device1_intouch.log terminate called after throwing an instance of 'std::logic_error' what(): basic_string::_M_construct null not valid Aborted (core dumped)

When I use

argv[2]

the program runs but the filename is wrong and full of gibberish (overflow?):

Maybe this is only part of where my problem is. Any help would be greatly appreciated. Thank you.

user9477548
  • 87
  • 11
  • 1
    There is a big difference between _command line arguments_ and the _standard input_. `argv` is for command line arguments, while `std::cin` is for standard input. Also note that you should always check `argc`, which is the number of elements in `argv` before you read from `argv`, to avoid undefined behavior (aka "bugs"). – alter_igel Apr 27 '19 at 17:09
  • 1
    When you _invoke_ your program as in `$ ./myProgram arg1 arg2 .. argn`, that translates to `argv == {"/path/to/myProgram", "arg1", "arg2", ..., "argn"}` and `argc == n` when your `main` function is called. This has nothing to do with the standard input, which you read via `std::cin`, and which may be supplied during, not just before, the call to `main` – alter_igel Apr 27 '19 at 17:13
  • I understand.. for some reason I thought that anything inputted on the command line got assigned to argv ( including standard input ). I guess I will just have to change my program to accept the file as a command line argument rather than use input redirection. Thank you for your help. – user9477548 Apr 27 '19 at 17:27

1 Answers1

1

You're confusing the standard input with your program's command line arguments. Command line arguments are the list of strings that you include on the command line when you invoke your program. For example:

$ ./myProgram arg1 arg2 ... argn

These are read via argv and argc, which respectively represent the "argument vector" and "argument count." By convention, the first argument is the working directory of your program. In this example, you would have:

argv == {"/path/to/myProgram", "arg1", "arg2", ..., "argn"}
argc == n

at the start of main. You must be careful not to read from argv out of bounds by checking argc, as with any raw array.

The standard input, on the other hand, is a stream of data that is supplied to your program throughout the call to main. This is read using std::cin.

int main(int argc, char** argv){
    std::string s;
    std::cin >> s; // read from standard input
}

When you run this program, it will block at the indicated line until it recieves data from the standard input. This data can be supplied by typing manually while the program is running from the command line:

$ ./myProgram

hello

or by input redirection:

$ echo "hello" | ./myProgram

$ ./myProgram < hello.txt

In the three examples above, s will contain the first word of text from the input, and you can use it for whatever you want on the following line.

Note that std::cin >> s will read text until it reaches the first white-space character. Fortunately, there are easy ways to read an entire line from stdin and to read everything from stdin

Community
  • 1
  • 1
alter_igel
  • 6,899
  • 3
  • 21
  • 40