13

I need to save all arguments to a vector or something like this. I'm not a programmer, so I don't know how to do it, but here's what I've got so far. I just want to call a function system to pass all arguments after.

#include "stdafx.h"
#include "iostream"
#include "vector"
#include <string>
using namespace std;

int main ( int argc, char *argv[] )
{
       for (int i=1; i<argc; i++)
       {
           if(strcmp(argv[i], "/all /renew") == 0)
           {
                 system("\"\"c:\\program files\\internet explorer\\iexplore.exe\" \"www.stackoverflow.com\"\"");
           }
           else
              system("c:\\windows\\system32\\ipconfig.exe"+**All Argv**);
       }

       return 0;
}
Keith Pinson
  • 7,835
  • 7
  • 61
  • 104
user793035
  • 131
  • 1
  • 1
  • 3
  • 3
    Note: `argv` contains the tokens separated by whitespace, so I doubt it will ever contain both `/all` and `/renew`. – André Caron Jun 15 '11 at 17:25

2 Answers2

74

i need to save all arguments to a vector or something

You can use the range constructor of the vector and pass appropriate iterators:

std::vector<std::string> arguments(argv + 1, argv + argc);

Not 100% sure if that's what you were asking. If not, clarify.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • (silently replaces a `for` loop in his own code by a range constructor in the initializer list. Repeat after me: "a class constructor shall not do any work, a class constructor must not do any work") – rubenvb Jun 15 '11 at 17:28
  • 9
    @rubenvb: why blindly comply to a principle that asks you to write more code for no apparent reason? – André Caron Jun 15 '11 at 17:31
  • @rubenvb - 1) why must a class constructor do no work? 2) Perhaps you'd prefer `vector args; args.insert(args.end(), argv+1, argv+argc);` – Robᵩ Jun 15 '11 at 17:31
  • @Fred: from OP's use case, it seems the required output is not the vector itself, but a concatenation of the arguments... – André Caron Jun 15 '11 at 17:32
  • 1
    @Bo, @André, @Rob: you all misunderstood me. I had a class with a constructor that filled a vector through a for loop, while I could have done the same thing through the correct `vector` constructor call. I do not want to build vector myself, I do not comply blindly to that principle; my code has not seen the need to do otherwise, and 1) it prevents accidentally throwing exceptions if you don't catch these inside the constructor code block. 2) good suggestion, but irrelevant due to aforementioned misunderstanding. My apologies for not being clear enough. – rubenvb Jun 15 '11 at 17:35
  • 2
    @rebenvb: the exception being thrown out of the constructor is a feature! Why would you want a partially constructed object? – André Caron Jun 15 '11 at 17:38
  • @André: I've read all the discussions here on SO on the subject, and frankly, I currently don't use exceptions except when either the program runs out of memory (a situation I don't want to handle gracefully) or I made some stupid programmer error. All the others are considered bugs that need to be fixed. I understand the pro's of doing what you say, just haven't met the need to use it. – rubenvb Jun 15 '11 at 17:42
  • @RedX Because `vector` has a range constructor, and because `char*` is convertible to `string`? – fredoverflow Mar 13 '14 at 16:27
  • `argv` NOT `argv + 1` –  Jun 29 '14 at 23:13
  • 2
    @DBJDBJ `argv[0]` is usually the name and path of the executable, which in most cases you don't care about. – fredoverflow Jun 30 '14 at 08:57
  • @fredoverflow Why did you write `argv + argc` and not just `argc`. Doesn't `argv` represent a neutral element here (0)? – Jonathan Komar Jun 05 '20 at 20:16
  • 1
    @JonathanKomar Because the `vector` constructor requires two iterators, in this case char pointer pointers. `argc` is just an `int`, whereas `argv` and `argv+argc` are `char**`s. – fredoverflow Jun 06 '20 at 06:45
  • @fredoverflow So you‘re taking advantage of implicit type conversion... – Jonathan Komar Jun 06 '20 at 06:46
0

To build string with all argument concatenated and then run a command based on those arguments, you can use something like:

#include <string>
using namespace std;
string concatenate ( int argc, char* argv[] )
{
    if (argc < 1) {
        return "";
    }
    string result(argv[0]);
    for (int i=1; i < argc; ++i) {
        result += " ";
        result += argv[i];
    }
    return result;
}
int main ( int argc, char* argv[] )
{
    const string arguments = concatenate(argc-1, argv+1);
    if (arguments == "/all /renew") {
        const string program = "c:\\windows\\system32\\ipconfig.exe";
        const string command = program + " " + arguments;
        system(command.c_str());
    } else {
        system("\"\"c:\\program files\\internet explorer\\iexplore.exe\" \"www.stackoverflow.com\"\"");
    }
}
André Caron
  • 44,541
  • 12
  • 67
  • 125
  • 1
    Note: for a better string concatenation, use `stringstream` instead. – André Caron Jun 15 '11 at 17:35
  • @André: and for better performance generally (not that this particular use case will slow you down much...) – rubenvb Jun 15 '11 at 17:43
  • Edit: fixed bug in concatenation, spaces are required. – André Caron Jun 15 '11 at 17:50
  • @Andre Caron Why is `stringstream` better for concatenation? `std::string` supports concatenation directly; `std::ostringstream` is for formatting output. – James Kanze Jun 15 '11 at 18:12
  • @James: the difference is not as explicit when using `operator+=` with the string because most implementations give it a nice allocation policy (they grow quick). However, repeated use of `operator+` will likely perform one allocation per concatenation. – André Caron Jun 16 '11 at 15:40
  • 1
    @Andre Caron I'm not sure I understand your point. The natural way of concatenating strings is the `+` operator (or `+=`). Anything else is obfuscation. – James Kanze Jun 16 '11 at 17:11