I'm building a commandline in C and for some reason, comparisons between strings aren't working.
int main(int argc, char *argv[])
{
bool sufficient_args = argc > 1;
if (sufficient_args)
{
if (argv[1] == "--version" || argv[1] == "--v")
{
xsh::console_write("version", xsh::versionID);
} else if (argv[1] == "--repo" || argv[1] == "--r")
{
xsh::console_write("repository", xsh::repo_url);
} else if (argv[1] == "--docs" || argv[1] == "--d" || argv[1] == "--help" || argv[1] == "--h")
{
xsh::console_write("documentation", xsh::docs_url);
} else if (argv[1] == "--credit" || argv[1] == "--c")
{
xsh::console_write("credit", xsh::credit);
} else
{
xsh::throw_error(412, "invalid argument(s) found");
}
} else
{
xsh::throw_error(212, "insufficient arguments");
}
std::cout << " " << std::endl;
return 0;
}
Im not getting any syntax errors, but when I run the .exe file with an argument such as --help or --credit, it runs the following code;
xsh::throw_error(412, "invalid argument(s) found");
which means that argv[1] was not interpreted as the same data type as "--help".
what do I do?
CodePudding user response:
Thats not how you compare char *
'strings' in c
either use strcmp
if(strcmp (argv[1] ,"--version") == 0)
or convert to c std::string
std::string arg1(argv[1]);
if (argv1 == "--version")
CodePudding user response:
Perfectly normal. You're comparing char*
, meaning that you're comparing POINTERS to char
arrays... And these are NOT strings!
Also, using char*
in C is, globally, a very bad idea. You must use real strings, like std::string
which is part of C standard.
EDIT (see comments): Conversion of C array to C structure:
#include <vector>
#include <string>
....
std::vector<std::string> args ;
for (int i=0;i<argc;i )
args.push_back(std::string(argv[i]) ;
Usage: use args[X]
instead of argv[X]
, and operator "==" will work normally. Not tested against constant literal strings, if it doesn't work, try something like if (args[1].compare("--version")==0)
if the compiler whines about not finding a suitable function.
CodePudding user response:
The argv[]
is an array of char*
and the string literals you compare them against are const char *
. What you are comparing are pointers and the argv[] will never contain pointers to the string constants in your code and all compares will be false. What you want to compare is what the pointers point at and you can do that using strcmp()
in the good old C style.
Converting argv[]
into a std::vector<std::string>
is a possibility to pull this into C land and you can do that by emplacing argv[i]
into a vector in a loop.
But since you probably never use the strings again after parsing the command line it would be easier to implicitly convert the command line arguments to std::string (or string_view) by comparing them with std::string
(string_view) literals:
using namespace std::literals;
...
if (argv[1] == "--version"s || argv[1] == "--v"s)
or
using namespace std::literals;
...
if (argv[1] == "--version"sv || argv[1] == "--v"sv)
The s
and sv
after the "" makes them std::string
and std::string_view
literals respectively. And then the overloaded operator==()
is used and implicitly converts the first argument to the same type.