Pass arguments to stuff? HOW IZ DO???

I'd like to be able to pass arguments to functions, based on user input.

For example, the user could type:
 
stuff arg1 arg2 arg3 arg4...


How does one do this?
I meant inside the program... Such as:
[code]
myname@mycomputer$ ./myprogram
prompt> command arg1 arg2 arg3...
Some stuff influenced by the arguments
prompt>
Do you mean how to write a function? If so:
1
2
3
4
return_type identifier(optional_arguments)
{
    return return_type
}
Ummm, no. I'm making a program that uses it's own commands, and I'd like to be able to pass arguments with the commands.
Something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <string>
#include <vector>

std::vector<std::string> args;

std::string arg;

while((std::cin >> arg) && std::cin.peek() == ' ')
{
        args.push_back(arg);
}

if(args[0] == "Run")
{
        if(args[1] == "-b") SetBreakPoint();
        else if(args[1] == "-s") SetStepping();
        else Run(args[1]);
}
Last edited on
Uhhh... What the hell is that!?
If you want to use what the user types, then you have to read input. megatron 0's while-loop reads words and stores them into vector.

The int main( int argc, char* argv[] ) is a result of similar process; the shell has taken what the user did write, split it into words, stored in array argv, and passed to the program it started.

Whether you have int argc, char* argv[] or std::vector<std::string> args you do have a list of words. Then your program has to decide what to do with them. Both the article that I did link to and megatron 0's show some examples, but it really is up to your actual needs.
Extending megatron 0 example (compiling code):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <functional>
#include <iostream>
#include <iterator>
#include <map>
#include <sstream>
#include <string>
#include <vector>

void loop(const std::vector<std::string>& args)
{
    //I am to lazy to use proper exception classes right now
    if (args.size() != 3) throw "invalid arguments number";
    int begin     = std::stoi(args[0]);
    int end       = std::stoi(args[1]);
    int increment = std::stoi(args[2]);
    if(begin > end || !(increment > 0) ) throw "invalid argument";
    for(int i = begin; i < end; i += increment)
        std::cout << i << ' ';
    std::cout << '\n';
}

void add(const std::vector<std::string>& args)
{
    if (args.size() != 2) throw "invalid arguments number";
    int lhs = std::stoi(args[0]);
    int rhs = std::stoi(args[1]);
    std::cout << (lhs + rhs) << '\n';
}

void echo(const std::vector<std::string>& args)
{
    for(const auto& s: args)
        std::cout << s << '\n';
}

std::vector<std::string> tokenize(std::string in)
{
    std::istringstream s(in);
    return {std::istream_iterator<std::string>(s), std::istream_iterator<std::string>()};
}

int main()
{
    std::map<std::string, std::function<void(const std::vector<std::string>&)>> func = {
        {"loop", loop}, {"add", add}, {"echo", echo}, 
        {"exit", [](const std::vector<std::string>&){std::exit(0);} },
    };
    std::string input;
    while(std::getline(std::cin, input)){
        auto tokens = tokenize(input);
        func.at(tokens[0])({tokens.begin() + 1, tokens.end()});
    }
}
echo hello, world
hello,
world
loop 0 10 2
0 2 4 6 8
add 1 1
2
exit

Process returned 0 (0x0)   execution time : 38.020 s
Press any key to continue.
Last edited on
Very interesting code MiiNiPaa.

Could you explain:

This

1
2
3
4
5
std::vector<std::string> tokenize(std::string in)
{
    std::istringstream s(in);
    return {std::istream_iterator<std::string>(s), std::istream_iterator<std::string>()};
}


And this

1
2
3
4
std::map<std::string, std::function<void(const std::vector<std::string>&)>> func = {
        {"loop", loop}, {"add", add}, {"echo", echo}, 
        {"exit", [](const std::vector<std::string>&){std::exit(0);} },
    };
The tokenize:
* The vector has a constructor that takes a range (the InputIterators): http://www.cplusplus.com/reference/vector/vector/vector/
* istream_iterator is an InputIterator: http://www.cplusplus.com/reference/iterator/istream_iterator/istream_iterator/
This
1
2
std::istringstream s(in);
return {std::istream_iterator<std::string>(s), std::istream_iterator<std::string>()};
is equivalent to
1
2
3
4
5
6
std::istringstream s(in);
std::vector<std::string> result;
std::string temp;
while(s >> temp)
    result.push_back(temp);
return result;
It uses stringstream to access input string as a stream (much like std::cin) http://en.cppreference.com/w/cpp/io/basic_istringstream
Then it just fills the vector and returns it. Original code uses two iterator constructor (4)
http://en.cppreference.com/w/cpp/container/vector/vector
An it uses istream iterator to read elements: http://en.cppreference.com/w/cpp/iterator/istream_iterator


map is an associative container: it is like array, where indices can be anything (in this case std::string). This map holds std::function: a function object you can call like a function.
http://en.cppreference.com/w/cpp/concept/FunctionObject
1
2
3
func.at(tokens[0])    ({tokens.begin() + 1, tokens.end()});
//        ↑                        ↑
// returns function   function call. Again uses 2 iter constructor to create parameter 
I used at() instead of [] to force exception if user enters something wrong. I would throw an exception later anyway, but that way we avoid creation of empty function.
Topic archived. No new replies allowed.