0

I've been having trouble with comparison in my c++ program. This is the boiled down version.

#include "stdafx.h"
#include <iostream>
#include <windows.h>
using namespace std;
int main(int argc, char *argv[])
{
    if(argc>2){cout<<"3+Args"<<endl;}else//???
    if(argc==2){
        cout<<"2args"<<endl;
        if(argv[1]=="/hide-icons"){}
        if(argv[1]=="/show-icons"){}
        if(argv[1]=="/reinstall"){setAsDefault();}
        if(argv[1]=="/?"){showPossibleCommands();}
        if(argv[1]=="/1"){cout<<"go"<<endl;FirstRun();}
    }else{showPossibleCommands();cout<<argv[0]<<endl;}
    return 0;
}

When I run "programname.exe /1", my program writes "2args" but not "go". Am I missing something obvious?

ThatGuyYouKnow
  • 450
  • 5
  • 10

3 Answers3

18

argv[1] is a char*, so by testing with == you're checking if the pointer points to the same spot as the start of the various string constants you're using... which is not going to be the case. To compare contents instead, use strcmp.

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 3
    Or stricmp if you want the arguments to be case insensitive – Stephen Nutt Aug 16 '09 at 00:16
  • 1
    Or strncmp if you want to test only the first n characters. – Will Bickford Aug 16 '09 at 00:18
  • 2
    `stricmp()` isn't standard. Chere's no real standard C (or C++ as far as I can tell - ask a real C++ programmer) way to do a case-insensitive string comparison. GCC provides strcasecmp, VC++ provides stricmp... – Chris Lutz Aug 16 '09 at 00:20
  • Good point Stephen, and of course he might want to accept abbreviations too (strncmp, strnicmp) &c. Depending on the level of standard compliance required, not all of these may be accessible with `#include ` (or the C++-namespaced equivalent). – Alex Martelli Aug 16 '09 at 00:23
  • 1
    strcasecmp is what the Open Group / IEEE specify in their standards, see http://www.opengroup.org/onlinepubs/9699919799/functions/strcasecmp.html . – Alex Martelli Aug 16 '09 at 00:25
5

The problem is, that your code compares the pointers to the strings, not the stings itself.

You have to replace the compares with calls to the string-compare function.

E.g.

if(argv[1]=="/1"){cout<<"go"<<endl;FirstRun();}

becomes

if(strcmp(argv[1],"/1") == 0) {cout<<"go"<<endl;FirstRun();}

You may have to include string.h to get the strcmp prototype into your code.

Nils Pipenbrinck
  • 83,631
  • 31
  • 151
  • 221
1

Another option is to convert the C-style arguments into a much more friendly vector of strings and process them instead:

#include <string>
#include <vector>

typedef std::vector<std::string> parameter_list;

int
cpp_main(std::string const& program_name, parameter_list const& params) {
    for (parameter_list::const_iterator arg=params.begin(); arg!=params.end(); ++arg) {
        if (*arg == "/hide-icons") {
        } else if (*arg == "/show-icons") {
        } else if (*arg == "/reinstall") {
            set_as_default();
        } else if (*arg == "/?") {
            show_help(program_name);
        } else if (*arg == "/1") {
            first_run();
        } else {
            show_help(program_name);
        }
    }
    return 0;
}

int
main(int argc, char **argv) {
    return cpp_main(argv[0], parameter_list(&argv[1], &argv[argc]));
}
D.Shawley
  • 58,213
  • 10
  • 98
  • 113
  • Nice idea. However you should not access an array outside its bounds, the result is undefined although it usually works as long as the array is not at the end of a page of memory. try parameter_list(&argv[0] + 1, &argv[0] +argc) – iain Aug 16 '09 at 13:38
  • The constructor is never dereferencing `argv` outside of its range. This is an STL open range so it copies starting at `argv[1]` and ending at the element before `argv[argc]`. Remember that `end()` is STL is actually the _"past-the-end value for the container"_. If the container is an array, then this is the element following the last element of the array. However, there may be a small possibility that the address of `argv[argc]` (which is calculated) overflows the address range but I think the standard actually provides protection against this happening too. – D.Shawley Aug 20 '09 at 21:27