开发者

Checking argv[] against a string? (C++)

开发者 https://www.devze.com 2023-02-14 10:17 出处:网络
So I\'m attempting to check the arguments that I\'m inputting into my program, and one of them is either the word \"yes\" 开发者_Go百科or \"no\", entered without the quotes.

So I'm attempting to check the arguments that I'm inputting into my program, and one of them is either the word "yes" 开发者_Go百科or "no", entered without the quotes.

I'm trying to test equivalency ( if (argv[n] == "yes") ) but that seems to be returning false every time when the input is, in fact, yes(When I output it it confirms this). What am I missing here that I'm doing improperly? If I understand properly argv[n] returns a cstring that is null-terminated, so it should allow me to do this.


You're comparing pointers. Use strcmp, or std::string.

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

  if (argv[1] == "yes"); // Wrong, compares two pointers
  if (strcmp(argv[1], "yes") == 0); // This compares what the pointers point to
  if (std::string(argv[1]) == "yes"); // Works fine
  if (argv[1] == std::string("yes")); // Works fine

  // Easy-mode    
  std::vector<std::string> args(argv, argv+argc);
  for (size_t i = 1; i < args.size(); ++i) {
      if (args[i] == "yes") {
          // do something
      }
  }

}


Here's a better alternative to std::string, and when efficiency is important - in C++17 you now have the very useful std::string_view. This lets you work with the arguments similarly to a std::string, without incurring the cost of copying.

Currently available in std::experimental in GCC:

#include <experimental/string_view>
...
if(std::experimental::string_view(argv[1]) == "yes") {
  // do things
}


if(strcmp(argv[0],"yes")==0) { // equal to "yes"

strcmp is zero if the 2 strings are the same.


You could also take a look into boost::program_options, though this seems a little off topic and overkill, but once you get used to it it's easy, convenient and safe to use. Some advantages are auto-generated --help for your program, plus things like string evaluation can be done safe using lexical_cast.


If you don't know exactly where the argument will appear, you might consider using find_if (C++17):

#include <algorithm>
#include <string>

int main(int argc, char * argv[])
{
    auto const begin = argv;
    auto const end = argv + argc;

    auto is_yes = [](std::string const & s) { return s == "yes"; };
    auto const it = std::find_if(begin, end, is_yes);

    // do stuff with `it`
    // ....
}


Modern C++, with a bit of const correctness...

/*BINFMTCXX: -Wall -Werror -std=c++17
*/

   #include <iostream>
   #include <string>
   #include <vector>
   using std::string; using std::vector; using std::cerr;

int main( int argc, char * const argv[] )
   {
   assert( argc >= 1 ); // exploratory -- could fail in principle, but not really
   const vector<string> args(argv+1,argv+argc); // convert C-style to modern C++
   for ( auto a : args ) cerr<<(a=="yes")<<"\n"; // operator '==' works as expected
   }

Note: The standard doesn't guarantee that you can use const in the signature of main, nor does it forbid it.

As used here, const ensures that we won't change things we don't intend to change -- which is the purpose of const in the C++ language.

See also...

  • Passing argv as const
  • What is the proper declaration of main?
  • int getopt(int argc, char * const argv[], const char *optstring) -- notice signature
  • What does int argc, char *argv[] mean? -- min value of argc
0

精彩评论

暂无评论...
验证码 换一张
取 消