0

I have a string which is coming from command line:

–m –d Tue –t 4 20 –u userid

I save it to a string by this:

string command;
for(int i=1; i<argc;i++){
    string tmp = argv[i];
    command += " "+ tmp + " ";
}

Now I want to manipulate this string to find if there is -u and if there is -u I want to see if the next value is starting with - or is a name. (it can be only -u or -u and a user name. In this example there is a user name)

if(command.find("-u",0)){  
    std::size_t found = command.find_first_of("-u");
    cout<<found<<endl;
}

The output is 14 which is not the right place. My job is to find if there is a -u and if after -u is a user name or nothing or another command starting with -. I appreciate any idea or efficient code.

Edit: I must run this code on another server which I can not take any library instead of built-in g++ libraries.

Bernard
  • 4,240
  • 18
  • 55
  • 88
  • use getopt_long for this. Here's an example: http://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Option-Example.html – zoska Mar 27 '14 at 18:15
  • why not use a dedicated command line parsing library, i.e. [cpp-optparse](https://github.com/weisslj/cpp-optparse)? – Dmitry Ledentsov Mar 27 '14 at 18:15
  • 1
    Seriously, you should consider getting code that handles this already, such as boost::program_options. http://www.boost.org/doc/libs/1_55_0/doc/html/program_options.html – PaulMcKenzie Mar 27 '14 at 18:16
  • Have a look at http://stackoverflow.com/questions/637371/option-parsers-for-c-c –  Mar 27 '14 at 18:17
  • @Bernard: The reason why you're getting the comments to "get a library or code that does this already" is because you really don't want to get yourself involved in the command-line parsing business if you don't have to. There are corner cases that can come up that your home-made code will fail to consider or even handle correctly. – PaulMcKenzie Mar 27 '14 at 18:17
  • Isn't `getopt` part of the built-in g++ libraries? – Fred Larson Mar 27 '14 at 18:18
  • I must run this code on another server which I can not take any library instead of built-in g++ libraries. – Bernard Mar 27 '14 at 18:19
  • getopt is part of g++: http://www.gnu.org/software/libc/manual/html_node/Getopt.html – PaulMcKenzie Mar 27 '14 at 18:20
  • If you really have to do it yourself and you're able to use C++11, you can try to solve this with regular expressions and capture groups - see http://en.cppreference.com/w/cpp/regex for reference. This is probably better than writing a bunch of if / then / else constructs. But as others have said, a specialized library will be best. – Excelcius Mar 27 '14 at 18:26

3 Answers3

2

While there certainly exist many libraries that do the things you want to achieve (see the comments under the question), althought if you want to stick with your code, you have to use string.find instead of string.find_first_of.

find_first_of searches for the first occurence of any character from the first argument (so "-u"). When it finds it, it returns the position, thus in the provided example, it'll return "0" (since –m –d Tue –t 4 20 –u userid starts with -).

If you want to search the string from a given position, you can give find a parameter describing the position it should start from:

size_t find (const string& str, size_t pos = 0) const;

so, if you want to find the first "-" after "-u", you'll do:

// Check if the first thing after "-u" starts with "-":
if(command.find("-u")!=string::npos                                         // if there's an "-u" in the command,
&& (command.find("-",command.find("-u"))                                    // and there's a "-" with a position        
< command.find_first_of("abcdefghijklmnoqprstuwvxys",command.find("-u")))   // less than the position of the first letter after "-u", then:
   cout << "it's a different command";
Paweł Stawarz
  • 3,952
  • 2
  • 17
  • 26
0

std::string::find_first_of() doesn't work as you expect it to:

Searches the string for the first character that matches any of the characters specified in its arguments.

What you want is std::string::find(), which:

Searches the string for the first occurrence of the sequence specified by its arguments.

But so you wouldn't invent the circle, you should use one of already implemented library of command line options parsing or use included in standard library getopt_long functionality.

zoska
  • 1,684
  • 11
  • 23
-1

Less words more code!:)

#include <iostream>
#include <sstream>
#include <iterator>
#include <algorithm>
#include <string>

int main()
{
    const char *user = "–u";
    std::string s( "–m –d Tue –t 4 20 –u userid" );
    std::string userID;

    std::istringstream is( s );

    auto it = std::find( std::istream_iterator<std::string>( is ),
                         std::istream_iterator<std::string>(),
                         user );

    if ( it != std::istream_iterator<std::string>() )
    {
        ++it;
        if ( it != std::istream_iterator<std::string>() && ( *it )[0] != '-' )
        {
            userID = *it;
        }
    }

    std::cout << "userID = " << userID << std::endl;
}

The output is

userID = userid
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335