1

I am building a CLI app that should do something similar to this:

./app

Welcome to the app, Type -h or --help to learn more.

./app -h

list of commands:...

Here is the code i am trying to build:

#include <iostream>

using namespace std;

int main(int argc, char** argv)  {

   cout << "Welcome to the app. Type -h or --help to learn more\n";

   if(argv == "-h" || argv == "--help") {
      cout << "List of commands:...";
   }
  return 0;
}

But when i try to compile gcc gives following erros:

error: comparison between distinct pointer types ‘char**’ and ‘const char*’ lacks a cast [-fpermissive]
    if(argv == "-h" || argv == "--help") {
               ^~~~
error: comparison between distinct pointer types ‘char**’ and ‘const char*’ lacks a cast [-fpermissive]
    if(argv == "-h" || argv == "--help") {
                               ^~~~~~~~

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    With e.g. `argv == "-h"` you compare two *pointers* that will never be equal. And the pointers are of different types as well, as mentioned in the error message. I suggest you [get a couple of good books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282) to read, as they should have information about what you want. There's also plenty of tutorials and examples on how to do it, if you just search a little. – Some programmer dude Apr 03 '19 at 08:42
  • 1
    Have a look at [`getopt()`](https://linux.die.net/man/3/getopt). – Sourav Ghosh Apr 03 '19 at 08:53
  • Assuming `-h` is the first command line argument - and you have checked `argc` to ensure such an argument is supplied - you need to do `strcmp(argv[1], "-h")`. Better yet, instead of using C string comparison functions, work out how to use the C++ `std::string`. – Peter Apr 03 '19 at 09:11

4 Answers4

11

As of C++17, the best way of writing this code is as follows:

#include <iostream>
#include <string_view>

int main(int argc, char** argv) {
    using namespace std::literals;

    std::cout << "Welcome to the app. Type -h or --help to learn more\n";

    if (argv[0] == "-h"sv || argv[0] == "--help"sv) {
       std::cout << "List of commands:...";
    }
}

Prior to the existence of the string_view header you can use the ""s std::string literal, which yields identical code to the above, just including the string standard header and changing "…"sv to "…"s. Such code unfortunately leads to redundant allocations but in this particular example that’s irrelevant.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • How exactly can I use this without `using namespace std::literals`? – HackerDaGreat57 Jul 20 '22 at 02:14
  • 1
    @HackerDaGreat57 You could use `using std::literals::operator ""sv;`, but don’t bother: `using namespace std::literals;` is the canonical solution. And this particular use of `using namespace` is acceptable even by organisations who otherwise never accept `using namespace`. If you want to avoid pulling all standard library literals into your scope, you can use `using namespace std::literals::string_view_literals;`. – Konrad Rudolph Jul 20 '22 at 18:59
4

argv is a pointer to char*.

You have to first chose which of the argc arguments you want to access.

e.g. argv[2] for the third argument.

And you can't do stringcompare with == on a char* you have to either use strcmp, or construct a string object from the char * like so: string arg2 = argv[2];

then you can do arg2 == "--help"

A.Franzen
  • 725
  • 4
  • 10
  • 2
    `argv[2]` is the *second* argument, considering that `argv[0]` is the name of the command. And you should probably add a note to always check `argc` before indexing `argv`. – Some programmer dude Apr 03 '19 at 08:47
  • 1
    @A.Franzen argv[0] is always the name of the program/command and depending on the argc (Which contains number of parameters passed), you can access the corresponding parameters. – cpp_enthusiast Apr 03 '19 at 08:50
2

You need to loop through the array of arguments and convert the char array to strings if you want to use the == operator

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char** argv)  {

    cout << "Welcome to the app. Type -h or --help to learn more\n";

    for(int i=0;i<argc;i++)
    {
        if(string(argv[i]) == "-h" || string(argv[i]) == "--help")
        {
            cout << "List of commands:...";
        }
    }
    return 0;
}
Lord Wolfenstein
  • 261
  • 2
  • 14
-2

You cannot compare strings the way you compare integers !!! use strcmp/stricmp

cprogrammer
  • 5,503
  • 3
  • 36
  • 56
  • 4
    C++ has much more readable ways of writing this code. Your assertion that “You cannot compare strings the way you compare integers” is simply false in C++ and doesn’t become more true if you add more exclamation marks. – Konrad Rudolph Apr 03 '19 at 09:03