views:

369

answers:

6

In my programming class we currently have a project that requires us to take arguments into the program. I then need to be able to check one of the arguments to see which value was passed to the program so that I can choose the appropriate behavior for the program to follow. In a previous homework assignment I did this with the strcmp function included in the cstring library using the following code:

int main(int argc, char *argv[]) {
   if (strcmp(argv[1], "yes") == 0) {
      // do this code
   } else if (strcmp(argv[1], "no") == 0) {
      // do this code
   }
}

However, for some reason we're not allowed to use the cstring library in this project. How else can I do this?

+1  A: 

You can always compare strings using a manual for loop, comparing it character by character. Your terminating condition will be when you encounter a NULL-char (since in C strings are null-terminated) or when you encounter a character in the first string which is not equal to its counterpart in the second string.

const char* s1 = "abcdefg";
const char* s2 = "abcdefg";

const char* p1 = s1;
const char* p2 = s2;

int same = 0;
for (; (same = (*p1 == *p2)) && *p1 != '\0'; ++p1, ++p2);

if (same) printf("The strings are equal\n");
else printf("The strings are NOT equal\n");

This will give you a character-by-character comparison. But note that this is different from strcmp in the sense that strcmp does a lexicographical comparison which will also tell you if one string is "less" than other string in terms of alphabetical ordering. But it seems you only need an equality comparison, which will only tell you whether or not the strings are identical.

Charles Salvia
Wouldn't this fail for s1 = "a" and s2 = "abcdefg"? That is, wouldn't it say the strings were equal?
ChrisInEdmonton
Good point, the check for nullchar should happen after the comparison. I'll fix the code above.
Charles Salvia
+5  A: 

Try this:

if (argv[1] == std::string("yes")) { stuff }

If the intent of the exercise is to teach how string comparisons work, then implement a for loop like other answers suggest. However, in C++ you are not supposed to use strcmp - there is a string class for a reason.

hrnt
If he can't use `cstring` I doubt he can use the `std::string` class
Charles Salvia
Well, it depends on the course. I know of C++ courses where use of C functions is prohibited to force people to learn C++ facilities providing the same functionality. I edited my answer to better reflect this.
hrnt
I see; good call.
Charles Salvia
+1  A: 

write your own strcmp function

ahzz
YES! - but call it something else so your TA doesn't mark you down because they saw `strcmp()` in your solution.
Michael Burr
+2  A: 

Make your own my_string_comp function:

// return 0 on success, -1 on failure
int my_string_comp(char* a, char *b) {
  if(a && b) { // check for non null pointers
    while(*a != '\0' && *b != '\0' && *a == *b) { a++; b++; }
    if(*a == '\0' && *b == '\0') { return 0; }
  }  
  return -1;
}

Note that this function gives a boolean output whereas strcmp returns values corresponding to lexicographical order of two input strings.

Joy Dutta
Worth noting that strcmp() returns more granularity than this, i.e. it can return 0, -1, or 1.
asveikau
True. This is a simplified function to generate a boolean output.
Joy Dutta
A: 

You can hash the input string and switch based on its numerical value - for the case values use the hashed values of the symbolic constants. You could make an external script to generate a header file with the "string" to "hash" mapping.

florin
A: 

I highly, highly recommend Boost.Program options for C++ command-line argument processing. It may be overkill for something like this, but for anything even slightly more complicated, the Boost.Program options library is less code, easier to understand once written, and lets you do fancy things like taking arguments from config files or from environment variables, or passing on the command line, with almost no work.

Something roughly like the following (untested) should work for you:

namespace po = boost::program_options;

int main() {
  po::options_description desc("Allowed options");
  desc.add_options()
    ("help", "produce help message")
    ("yes",  "get down")
    ("no",   "get funky")
  ;

  po:variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);

  if (vm.count("yes")) {
    // get down
  } else if (vm.count("no")) {
    // get funky
  }
}

The tutorial page gives a number of other examples which shows that it is almost no work to add additional, substantially more complex, command-line arguments.

Note that boost is not included by default in C++, but it is not normally too hard to add it. Boost is one of those sets of libraries that all C++ programmers need to be aware of. Please be warned that this may be overkill if you are still learning C++, however.

ChrisInEdmonton