Read out what somebody wrote in cmd!

Pages: 12
Hi, i want to code a program which i start over the cmd.
For example if i type in the cmd "file.exe -b example hello" .Ialready added the debugging arguments. But how do i check with the code if somebody typed the last "hello" for example and how do i add actions then if it was put in? please help
Not clear what your asking. The number of arguments passed to the program (including the name of the program) itself is argc, and argv contains the actual data. So "hello" in your example would be argv[argc - 1]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Example program
#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
    if (argc > 1)
    {
        std::string arg = argv[argc - 1];
        if (arg == "hello")
        {
            std::cout << "Hello, world!\n";   
        }
        else
        {
            std::cout << "Goodbye, world!\n";   
        }
    }
}


This will print every argument back out:
1
2
3
4
5
6
7
8
// Example program
#include <iostream>

int main(int argc, char* argv[])
{
    for (int i = 0; i < argc; i++)
        std::cout << argv[i] << '\n';
}


A common 'gotcha' is trying to do something like:
1
2
3
4
if (argv[i] == "hello")
{
    // ...
}

This won't work, because argv[i] is a C-style string (this will only compare pointers).
Easiest workaround is to convert it to a C++ string
1
2
3
4
if (std::string(argv[i]) == "hello")
{

}
Last edited on
Thanks but i dont know how to implement that...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>



using namespace std;



    int main(int argc, char* argv[])
    {
        for (int i = 0; i < argc; i++) {
            std::cout << argv[i] << '\n';


            if (argv[i] == "test") {

                cout << "test";
            }
        }
    }






here is mycode. So i want to reach that if any of the arguments which are input in the cmd are "test" it should give aout test
@NMI21,

@Ganado was editing his post while you were responding. The end of his edited post (starting with "A common 'gotcha'") deals with your most recent problem.

A program's command-line argument list is an array of C strings. To compare any of the argument strings with a desired C string you can use the C library strcmp() function. With a command-line of
test_app.exe -b test hello


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <cstring>

int main(int argc, char* argv[])
{
   if (argc > 1)
   {
      char arg[] = "test";

      for (int i { 1 }; i < argc; ++i)
      {
         if (strcmp(argv[i], arg) == 0) // http://www.cplusplus.com/reference/cstring/strcmp/
         {
            std::cout << '"' << argv[i] << "\" is a TEST!\n";
         }
         else
         {
            std::cout << '"' << argv[i] << "\" is NOT a test.\n";
         }
      }
   }
}

"-b" is NOT a test.
"test" is a TEST!
"hello" is NOT a test.

The case of the strings, C or C++, must match exactly. TEST, Test or another variation will NOT match test.
Last edited on
Ah thanks! now i understand it. One last question. i want to add a filepath. Is there any way i can exclude / and :. Because the program notices them as 1 argument but i want to write a file path like C:/user/example/example and it should be noticed as one argument all together.
Thank for my bad english i hope you understand my problem..
Last edited on
C++17 introduced <filesystem>, the library makes it a lot easier to deal with the file system:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <filesystem>

int main()
{
   std::filesystem::path file_path { "C:/Dummy/Blank/Project1/Project1/Project.exe" };

   std::cout << file_path << "\n\n";

   std::cout << file_path.parent_path() << "\n\n";

   std::cout << file_path.filename() << '\n';
}

"C:/Dummy/Blank/Project1/Project1/Project.exe"

"C:/Dummy/Blank/Project1/Project1"

"Project.exe"

https://en.cppreference.com/w/cpp/filesystem
Thank you but thats not exactly what im searching for. The user of my program is able to start the programm with programm.exe filepath over the cmc. But if i put in a filepath the / are detected as more arguments. For example C:/Users/Desktop --> 4 Arguments
but i only want it to be one argument
What happens if you put that in double quotes:
file.exe "C:/Users/Desktop....."
Executing the code I posted previously using a command prompt at the C drive root:
C:\>"C:\Programming\My Projects\Project1\Release\project1.exe" -b test hello
"-b" is NOT a test.
"test" is a TEST!
"hello" is NOT a test.

C:\>

Is THIS what you are looking for? I enclosed the entire path in quotes because of the space in the path. I would recommend using quotes even if there are no spaces.

Notice I started parsing through the command-line argument array at argv[1], to exclude the program's entry in the argument list.
So what i want to do is to write a programm which will be executed from cmd.
With example.exe test filepath

the filepath is of a txt file. So my main program starts and does something if i start it with test and it starts different if i dont write test like only example.exe filepath. I got this with the test already but i want to save the filepath which is input by the user. The main program should read the txt file afterwards. I want to safe the filepath in a string. And i dont know how to check if the user put in a filepath.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>



using namespace std;



    int main(int argc, char* argv[])
    {
        fstream myfile();
       

        for (int i = 0; i < argc; i++) {
           
            if (string(argv[i]) == "test") {

                cout << "test";
            }
            
            
            else{
                

            
            
            
            }
        }

    }



so I want to add a function here to check if the user put in a filepath and if yes save it


Last edited on
If you are trying to read a file, then you can check if the file was successfully opened.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

int main(int argc, char* argv[])
{
    if (argc <= 1)
    {
        std::cout << "Specify filepath\n";
        return 1;
    }
    
    ifstream infile(argv[1]);
    
    if (!infile)
    {
        cout << "Error opening " << argv[1] << '\n';
        return 1;
    }

    // read infile ...

    return 0;
}

Last edited on
commandline args are GIGO.
you can have them put in path and file name as one argument, or as two, you decide.
when the user uses the program if the file name OR the file path Or the combination if you do them together have spaces in them, c++ sees that as MULTIPLE command line args UNLESS the user puts quotes on it. It is fairly casual: it seems to work in windows at least if you put a leading quote of either type an don't bother to close them. I have not experimented but it is friendly enough that I have not had to dig deeply into it.
be aware that command line args ALSO support drag and drop, eg you can drop a file onto the .exe and it is as if called with that as an argument, and that has the path and filename as ONE big string not split up, so I recommend you expect it as a combined argument. (again, windows behavior).

you could be smart and mush all the args back together with spaces between if you want to assume that multiple args were really one. however it will very likely choke on multi space items; it will work for like program files\file name.txt but not for some special folder with word, 5 spaces, word type format. IMHO fixing that issue would be enabling idiots more than fixing your code. If they want to make folders and files like that, they can learn to use quotes.

to detect if it has a path, just look for the slashes. you can do it with strstr in C since the darn things are char array style strings and copying them to use find() is rather silly for a 5 line program.
it is usually considered a friendly gesture to check argc and if its not right, throw a message rather than crash trying to access argv[invalid index].

if they leave off the path, its assumed to be in the current folder. you can use argv[0] to steal that info and save it anyway, if you wanted to. (at least on windows its the fully qualified path to the program itself)
Last edited on
to detect if it has a path, just look for the slashes.
"file.txt" is a valid path :)
Guys thanks for helping me out but I think im just dumb. Its so hard to explain for me what im searching for. Im trying one last time im so sorry for my bad english skills. I want to write a program which can be executed from the cmd with example.exe function1 example filepath.

From a reply earlier i understood the code which helps me if any of the args have a specific word or letter in it. That works fine for function1 then. But afterwords i really dont know how to read or check what is in the example and the filkepath arg. And i cant do it with arg[number] because the user should be able to start the program with and without function1. I hope its a little bit clearer now.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>



using namespace std;



    int main(int argc, char* argv[])
    {
        fstream myfile();
       

        for (int i = 0; i < argc; i++) {
           
            fstream myfile(argv[i]);

            if (string(argv[i]) == "test") {

                cout << "test was input";

            }
            
            
            else{
                

                cout << "started üprogram without function1";
            
            
            }
        }

    }


That is my code at the moment and i dont understand how i can read the other arguments.
the filepath is of a txt file. So my main program starts and does something if i start it with test and it starts different if i dont write test like only example.exe filepath.


any of the args have a specific word or letter in it


You are not being consistent. These two requirements are contradictory.

The first mentions only 2 arguments - other of your posts mention 3 arguments.

What, exactly, are the allowed command arguments.
Give some examples of actual command lines.
Last edited on
Ok one example is
program.exe - function1 filepath word


program.exe - - > program shoulf start
-function1 - - > optional function(program starts without it aswell but does soemthing different)
filepath-->reads the input filepath of the user and opens the txt with fstream
word--> reads out the word and saves it
- function1
or
-function1
?
-function1
1
2
3
4
5
6
7
int main( int argc, char* argv[] )
{
  // What we know at this point is that the 'argc' is 1, 2, 3, 4, ....
  IF it is 1 THEN user wrote no arguments
  IF it is 2 THEN user wrote one argument. We can use arg[1]
  IF it is 3 THEN user wrote two argument. We can use arg[1] and arg[2]
  ...


If there were at least 2 arguments, is the second argument path to a file?
1
2
3
4
5
6
7
8
9
  namespace fs = std::filesystem;
  std::string name = argv[2];
  fs::path file_path {name};
  auto s = fs::status( file_path );
  if ( fs::exists(s) && fs::is_regular_file(s) ) {
    // yes, 'name' is a path to regular file that does exists
    std::ifstream in( name );
    // ...
  }

Disclaimer: I've never used <filesystem>
Pages: 12