0

I'm new to C++ and want to achieve something extremely simple, but it will not let me. I've read a bunch of ways to "assign" or "link" or "copy" arrays, but NONE of these seem to work at all.

Consider the following:

in file: header.h:

using namespace std;

Class Proc
{
    public: static char args;
};

in file: main.cpp:

using namespace std;

#include <cstdlib>
#include <memory>
#include "header.h"

int main(int argc, char* argv[])
{
    Proc::args = argv;                // yea i know this won't work :(
    // Proc::args[argc] = argv;       // not working either
    // memcpy(argv, Proc::args, sizeof(argv));   // nope
    // copy(begin(argv), end(argv), begin(Proc.args));   // nope
}

In fact I don't really want to "copy" it at all, linking it is just fine, but the g++ compiler keeps throwing up in my face about undefined reference to 'Proc::args' and who knows what else.

I'm about to put a drill to my ear, can anyone please make an example?

It is different from undefined reference to'Proc::args'because I also get:error: invalid use of qualified-name 'Proc::args'and also that it complains aboutchar**&char*not being the same... - and when I add an asterisk to Proc'schar* args` then it throws some more.

  • Possible duplicate of [Undefined reference to static class member](http://stackoverflow.com/questions/272900/undefined-reference-to-static-class-member) – MikeCAT Dec 27 '15 at 13:35
  • 4
    `args` isn't an array, for starters. It's a single character. – chris Dec 27 '15 at 13:38
  • thanks, I tried that, but still does not answer the question of how to actually assign the `argv` to the `Proc.args`, as it complains about the datatype being incompatible, where clearly they are the same, or so I think? –  Dec 27 '15 at 13:38
  • I get that, see, clearly I have no clue what is going on there.. as to my knowledge of PHP & Javascript, it should work.. and when I do `cout` << argv[0] I do get the first argument, so it does "behave" like an array though... –  Dec 27 '15 at 13:40
  • see my answer @Charl Steynberg. This is c and argv is array of char pointers. so you have argc number of strings. – phoenix Dec 27 '15 at 13:46
  • @Sri.U The type of `argv` is really pointer to pointer to `char`. – juanchopanza Dec 27 '15 at 13:51
  • array of char pointers means exactly the same. char * argv[] is the definition. so it means you have array of char pointers. please do google. – phoenix Dec 27 '15 at 13:53
  • array is always a pointer(address) of first element of array in c. that is how it is represented. So what you said is right and what I said is also right. – phoenix Dec 27 '15 at 13:55
  • 1
    @Sri.U No. Not the same type at all. Please don't spread confusing falsehoods. – juanchopanza Dec 27 '15 at 13:57
  • 1
    @Sri.U: An array can decay into a pointer, but they are different and their distinction really matters, especially on the stack and for struct members and variables. See the corresponding entry in the [C FAQ](http://c-faq.com/aryptr/aryptr2.html). – DarkDust Dec 27 '15 at 14:05
  • @CharlSteynberg did you actually type "Class" in your header file instead of "class" or did you just make a typo when you typed it into Stack Overflow? If it's the latter, you should edit the question to avoid confusion. – Klitos Kyriacou Dec 27 '15 at 14:12
  • hmm... no I used all lowercase... but why does it not moan about that though? - i mean that's rather worrying :O –  Dec 27 '15 at 14:13
  • @CharlSteynberg sorry I'm not sure I understand your reply. You wrote "Class" in your question (which is wrong) but you're saying you wrote "class" in lowercase (which is correct) in your header file, so why would it moan about that? – Klitos Kyriacou Dec 27 '15 at 14:52
  • @KlitosKyriacou - sorry, yes I used all lowercase, the question has a typo, but I can't seem to edit it again :( ... anyway, I still don't have a good answer though... I'm willing to sacrifice the little points I have left for a bounty if that's what it will cost me, but, I really just need a good answer here... as I need to access this `Proc` globally and access its `members` statically (i mean: not having to create an instance of the class every time - nor having to loop through a member's keys in order to use a specific one ... that's just wasteful. Any input is greatly appreciated, thanks –  Dec 27 '15 at 15:02
  • @CharlSteynberg I think kebs provided a good answer for you, based on best practices in the usage of C++. However, if you really need to access it globally, and statically, then see Sri.U's edit (the last sentence in his answer) - that provides exactly what you are asking. (Then just do `Proc::args = argv;` in your main().) – Klitos Kyriacou Dec 27 '15 at 15:12
  • @KlitosKyriacou - thanks, yes I tried that, but, I still get the same error: `cannot convert ‘char**’ to ‘char*’ in assignment`, maybe I'm just missing something REALLY obvious, ... i reverted back to @Sri.u's answer, but I don't know how to apply that in `main`, as I still have no clue as to how to simply `assign` the `argv` var to `Proc::args`; even though in the `Proc` class I am using it as @Sri.U suggests, any help will be greatly appreciated, thanks. –  Dec 27 '15 at 15:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/99054/discussion-between-charl-steynberg-and-klitos-kyriacou). –  Dec 27 '15 at 15:22

4 Answers4

2

If I understand correctly, you want to copy command-line arguments into some variable.

Here is one way to do that, that does the copy. It is also possible to save a pointer on original data, but it's usually no worth the effort.

struct Proc
{
   std::vector<std::string> args;
   Proc( int argc, char* argv[] )
   {
      for( size_t i=0; i<(size_t)argc; ++i )
         args.push_back( argv[i] );
   }
};

int main(int argc, char* argv[])
{
    Proc cla( argc, argv ); // saves cl args into variable
    for( const auto& c: cla.args ) // print out
      std::cout << c << "\n";
}

Live here

Side comment: I disagree with @Sri.U 's answer, usage of memcpy is not recommended with modern C++. Similarly, usage of raw arrays is also discouraged as the library provides safer containers (string and vector).

kebs
  • 6,387
  • 4
  • 41
  • 70
  • @ kebs - thanks, I can't print it out to see if Proc.args[0] is working though.. now it moans this: When I use: `cout << Proc::args` then I get: `error: ‘args’ is not a member of ‘Proc’` - and when I do: `cout << Proc.args` I get: `error: expected primary-expression before ‘.’ token` Any advice? –  Dec 27 '15 at 14:06
  • @ kebs - thanks, it works! - beers all around !!! - I had to check your `live` example first though as you used headers I did not include at first. Thank you very VERY much! –  Dec 27 '15 at 14:18
  • Using @kebs's answer, I have another problem .. is there no way I can just access 1 of the `args` from `Proc` like this: `Proc::args[0]` or `Proc::args[1]` ? .. I don't mind converting it to some other data type or whatever... just, it seems odd to be forced to use a loop & possibly conditional logic to do so - thanks –  Dec 27 '15 at 14:29
  • Yes, use cla.args[0] etc. – Klitos Kyriacou Dec 27 '15 at 15:03
1

I think there are two problems in the sample code you have shown:-

  1. Static should be initialized after declaration, outside of the class like -
char Proc::args = '\0';

int main(int argc, char* argv[]) 
{
  //Proc::args = argv; /* invalid conversion */

  return 0;
}

This will resolve your undefined reference problem.

  1. You are doing invalid conversion from char** to char by doing Proc::args = argv; you can use static char **args instead.
danishansari
  • 634
  • 5
  • 21
0

You can have:

public: static char args[NUM_ARGS][STRING_LENGTH];


Then you can do memcpy for each of the arguments like this:

for (i=0; i < argc; i++) {
    memcpy (argv[i], args[i], sizeof(argv[i])):
}


The argument in main function argv is array of char pointers. So you have argc number of strings.

So instead of

public: static char args[NUM_ARGS][STRING_LENGTH];


you can also have array of pointers and allocate it in main like below:

public: static char *args[STRING_LENGTH];


Edit based on OPs comment: If you just want to assign it to args, then you need to have

public: static char **args;
phoenix
  • 3,069
  • 3
  • 22
  • 29
  • AT Sri.u - thanks, but that doesn't help me though.. I need to simply assign the `argv` array as it is to the `Proc.args` property, both being the same data-type, preferably linked, not copied, but if I really have to copy them I will do that.. remember also that: arguments vary, in number and (string)-length, so if I need to use the lengths, then surely I will need to define some constant for new array or whatever, I just really don't know how, I've been at this since 7am this morning ;( –  Dec 27 '15 at 13:55
  • hope it helps now. but could not understand what you do after that. – phoenix Dec 27 '15 at 13:58
  • To clarify the edited answer, you should add that you need to put the declaration `static char **Proc::args;` in the global scope (outside of `main()`) and then inside of main do `Proc::args = argv;` – Klitos Kyriacou Dec 27 '15 at 15:18
  • okay, I've done that now, and it moaned about `char**` not being the same as `char*` (weird) so I added an extra asterisk to the property definition in the `Proc` class, and done as you & @danishansari pointed out, .. now I get this: `error: ‘static’ may not be used when defining (as opposed to declaring) a static data member [-fpermissive] static char **Proc::args;` –  Dec 27 '15 at 15:36
  • Sorry about that, that was my mistake (fingers in gear, brain in neutral) - the 'static' shouldn't be there. – Klitos Kyriacou Dec 27 '15 at 15:39
  • oh wow okay it works now, I just removed the `static` in front of the `Proc` as you've mentioned, but rather fused what you & @danishansari said both, and now it works !!! - I can now access Proc::args[0] - without any issue –  Dec 27 '15 at 15:40
  • I can't select an answer, will not pick my own as I merely put it together, but, I can't choose an answer at all, the option is missing! - does anyone know what to do in this case? I think it's because of the "possible duplicate" thingy. –  Dec 27 '15 at 16:24
  • you need to click on the tick mark below the votes for the answer you want to pick – phoenix Dec 27 '15 at 16:26
0

Thanks so much to all for your input!

Using what you taught me I "frankensteined" the answers & comments together and came up with a working solution (below)

I hope this helps someone, and again thanks very much for all your effort. Please feel free to shorten the code, or make it more elegant.

in file: header.h:

using namespace std;

class Proc
{
    public: static char** args;

    public: static void init(char* args[])
    {
        Proc::args = args;
    };
};

char **Proc::args;   // important!

in file: main.cpp:

using namespace std;

#include <iostream>

int main(int argc, char* argv[])
{
    Proc::init(argv);
    cout << Proc::args[0];    // works !!
}
  • 1
    A couple of suggestions. 1. Don't put `using namespace std;` in a header file. This is considered bad style in most guidelines and it may cause a problem in some future code that uses your header as it can create a name clash. 2. The definition `char **Proc::args;` should be in its own file, not in a header file which is typically included by multiple .cpp files and would break the One Definition Rule. You can read more about these two things in most good C++ books - see [FAQ](https://isocpp.org/wiki/faq/how-to-learn-cpp#best-book). – Klitos Kyriacou Dec 27 '15 at 17:26