a question about char**

H

happyvalley

I just wonder how to pass arguments to this function with a char**

void oldmain(int argv, char**argc)
{
........
}

void main(void)
{
int argv;
char ** argc;

string cmd[ ] = {"hello", "again", "again"};

// ????????? how to populate cmd[] into **argc

oldmain(argv, argc);
}

how to populate cmd[] into argc, the number of string in cmd[] is not
fixed.
thanks
 
O

Ondra Holub

happyvalley napsal:
I just wonder how to pass arguments to this function with a char**

void oldmain(int argv, char**argc)

I would name it
void oldmain(int argc, char** argv)

argc means argument count
argv menas argument values
{
........
}

void main(void)
{
int argv;
char ** argc;

string cmd[ ] = {"hello", "again", "again"};

// ????????? how to populate cmd[] into **argc

oldmain(argv, argc);
}

how to populate cmd[] into argc, the number of string in cmd[] is not
fixed.
thanks

oldmain(sizeof(cmd) / sizeof(cmd[0]), cmd);
 
H

happyvalley

Ondra said:
happyvalley napsal:
I just wonder how to pass arguments to this function with a char**

void oldmain(int argv, char**argc)

I would name it
void oldmain(int argc, char** argv)

argc means argument count
argv menas argument values
{
........
}

void main(void)
{
int argv;
char ** argc;

string cmd[ ] = {"hello", "again", "again"};

// ????????? how to populate cmd[] into **argc

oldmain(argv, argc);
}

how to populate cmd[] into argc, the number of string in cmd[] is not
fixed.
thanks

oldmain(sizeof(cmd) / sizeof(cmd[0]), cmd);

cmd is a string[], oldmain() cannot cast it to char**
 
M

Micah Cowan

happyvalley said:
I just wonder how to pass arguments to this function with a char**

void oldmain(int argv, char**argc)

Those names are the opposite of the traditional names, and are
extremely likely to lead to confusion.
{
........
}

void main(void)

main() always, always returns int. In C++, it has never been allowed to
return anything else. Your implementation may allow you to get away
with this, but the moment you write such a thing, it's no longer C++,
and not topical to this newsgroup. You don't even need to write a
return statement, since a zero-return is implicit otherwise: just
change the first "void" to an "int".
{
int argv;
char ** argc;

See above about confusing names...
string cmd[ ] = {"hello", "again", "again"};

// ????????? how to populate cmd[] into **argc

oldmain(argv, argc);
}

how to populate cmd[] into argc, the number of string in cmd[] is not
fixed.
thanks

I'm not sure you've given us enough information to answer your
question. First off: why must it be an array of std::string's (which is
what I'm assuming you're using, though you neither #included the
appropriate headers nor imported the appropriate name std)? Is it
something user-specified, or what?

If I had full control over your main() above, I'd have simply written
it with:

int argc;
char *argv[] = {"hello","again","again"};

And passed that argv to oldmain(). (Note that the above involves some
deprecated conversions from const char* to char*, and may not be
portable to future versions of the C++ language.)

What did you mean by "the number of [strings] in cmd[] is not fixed"?
The number of elements in any array is fixed. Perhaps your real code
doesn't use an array?

In either case, if you're really stuck with the input being C++
std::string's, then you cannot avoid copying them into a new array of
C-strings (the space for which you will need to allocate yourself). If
you're not really using an array for the srings (a std::vector,
perhaps), then you will proably need to allocate the space for the
array of (char*)s as well.

-Micah
 
H

happyvalley

Micah said:
happyvalley said:
I just wonder how to pass arguments to this function with a char**

void oldmain(int argv, char**argc)

Those names are the opposite of the traditional names, and are
extremely likely to lead to confusion.
{
........
}

void main(void)

main() always, always returns int. In C++, it has never been allowed to
return anything else. Your implementation may allow you to get away
with this, but the moment you write such a thing, it's no longer C++,
and not topical to this newsgroup. You don't even need to write a
return statement, since a zero-return is implicit otherwise: just
change the first "void" to an "int".
{
int argv;
char ** argc;

See above about confusing names...
string cmd[ ] = {"hello", "again", "again"};

// ????????? how to populate cmd[] into **argc

oldmain(argv, argc);
}

how to populate cmd[] into argc, the number of string in cmd[] is not
fixed.
thanks

I'm not sure you've given us enough information to answer your
question. First off: why must it be an array of std::string's (which is
what I'm assuming you're using, though you neither #included the
appropriate headers nor imported the appropriate name std)? Is it
something user-specified, or what?

If I had full control over your main() above, I'd have simply written
it with:

int argc;
char *argv[] = {"hello","again","again"};

And passed that argv to oldmain(). (Note that the above involves some
deprecated conversions from const char* to char*, and may not be
portable to future versions of the C++ language.)

What did you mean by "the number of [strings] in cmd[] is not fixed"?
The number of elements in any array is fixed. Perhaps your real code
doesn't use an array?

In either case, if you're really stuck with the input being C++
std::string's, then you cannot avoid copying them into a new array of
C-strings (the space for which you will need to allocate yourself). If
you're not really using an array for the srings (a std::vector,
perhaps), then you will proably need to allocate the space for the
array of (char*)s as well.

-Micah

Hi, Micah

thanks a lot for your correction and your time.
don't worry about the variable name, my typo. anyway thanks for
reminder
basically, I have a program running accepting arguments from char**
argv. the number of arguments is not fixed.

now I wrap this within a server, now my server receive a query command
string from the client. the string is parsered into several tokens and
I want to populate them into char** cmd
and then call the old main function oldmain(int argc, char**argv).
in this way, I can easily debug the code in standalone mode, and wrap
it within the server by just changing the main function name.

#include .....
int oldmain(int argc, char**argv)
{
...... // do something
return 0;
}

int main(void)
{
//create a socket
// connect to a client
// receive a string from client
string acmd = myServer.readFromClient()

// now I parse the string into char**argv
stringstream os(astr);
vector<string> argc;
argv.push_back("nameofthisprograme")

string temp;
while (os>>temp)
argv.push_back(temp);

// now I have the arguments saved in a string vector, just wonder
how to populate them
//into char**.
char **tempargv;
// ?????????

oldmain( argv.length(), tempargv);

return 0;
}

thanks, hope this 'v made the question clear,
 
O

Ondra Holub

happyvalley napsal:
Ondra said:
happyvalley napsal:
I just wonder how to pass arguments to this function with a char**

void oldmain(int argv, char**argc)

I would name it
void oldmain(int argc, char** argv)

argc means argument count
argv menas argument values
{
........
}

void main(void)
{
int argv;
char ** argc;

string cmd[ ] = {"hello", "again", "again"};

// ????????? how to populate cmd[] into **argc

oldmain(argv, argc);
}

how to populate cmd[] into argc, the number of string in cmd[] is not
fixed.
thanks

oldmain(sizeof(cmd) / sizeof(cmd[0]), cmd);

cmd is a string[], oldmain() cannot cast it to char**

Ooops... I didn't see that, sorry. There is no simple command to
convert array of strings to array of char*. You have to either create
new array of char* from array of std::string or overload function
oldmain to accept array of string.
 
M

Micah Cowan

happyvalley said:
Hi, Micah

thanks a lot for your correction and your time.
don't worry about the variable name, my typo. anyway thanks for
reminder
basically, I have a program running accepting arguments from char**
argv. the number of arguments is not fixed.

now I wrap this within a server, now my server receive a query command
string from the client. the string is parsered into several tokens and
I want to populate them into char** cmd
and then call the old main function oldmain(int argc, char**argv).
in this way, I can easily debug the code in standalone mode, and wrap
it within the server by just changing the main function name.

#include .....
int oldmain(int argc, char**argv)
{
...... // do something
return 0;
}

int main(void)
{
//create a socket
// connect to a client
// receive a string from client
string acmd = myServer.readFromClient()

// now I parse the string into char**argv
stringstream os(astr);
vector<string> argc;
argv.push_back("nameofthisprograme")

string temp;
while (os>>temp)
argv.push_back(temp);

// now I have the arguments saved in a string vector, just wonder
how to populate them
//into char**.
char **tempargv;
// ?????????

oldmain( argv.length(), tempargv);

return 0;
}

thanks, hope this 'v made the question clear,

If it were me, I probably wouldn't bother with the vector of C++
strings in the first place. I'd probably do a vector of
pointers-to-char, and then pass the address of the first element as
argv (given that that is now explicitly well-defined in C++03).

If you'd prefer to convert to C++ strings and then into C strings,
though, you'll first need to dynamically allocate an array of C
strings:

char **tempargv = new (char *[ argv.size()+ 1 ]);
// new array of {arv.size()+1} pointers to char
tempargv[argv.size()] = 0;
// that's what the + 1 was for: argv is
// required to end with a null pointer.

And then allocate space for new C strings to go in there, perhaps via:

for (vector<string>::size_type s = 0; s != argv.size(); ++s) {
tempargv = new char[argv.size() + 1];
// + 1 for the terminating null byte
memcpy(tempargv, argv.c_str(), argv.size() + 1);
// or: copy(argv.begin(), argv.end(), tempargv);
}

The code above assumes some potential additions to your #include-list,
and possibly to your using declarations as well.

Don't just copy-and-paste the solution I've given you: if anything
about the above allocation-and-copy loop is unclear to you, please ask
about it. Failing to learn from this exercise would be the worst
blunder you could make. :)

-Micah
 
S

Salt_Peter

Micah said:
If it were me, I probably wouldn't bother with the vector of C++
strings in the first place. I'd probably do a vector of
pointers-to-char, and then pass the address of the first element as
argv (given that that is now explicitly well-defined in C++03).

If you'd prefer to convert to C++ strings and then into C strings,
though, you'll first need to dynamically allocate an array of C
strings:

Sorry, i disagree with the above statement, a std::vector< std::string
is the perfect candidate for the job at hand. Also, std::string's c_str() member function returns a const pointer to a C-type terminated string in the case that's required.

The OP can simply declare oldmain(...) with a reference to that vector:

#include <iostream>
#include <ostream>
#include <vector>
#include <iterator>

int oldmain(std::vector< std::string >& r_v)
{
std::copy( r_v.begin(),
r_v.end(),
std::eek:stream_iterator< std::string >(std::cout, "\n") );
return 0;
}

int main(int argc, char* argv[])
{
std::vector< std::string > vs;
for(int i = 0; i < argc; ++i)
{
vs.push_back(argv);
}
int result = oldmain( vs );

// in the case of cmd:
std::string cmd[ ] = {"hello", "again", "another"};
std::vector< std::string > vcmd(cmd, cmd + 3); // one past the end
oldmain( vcmd );

return result;
}
 
M

Micah Cowan

Salt_Peter said:
Sorry, i disagree with the above statement, a std::vector< std::string

(The immediately above line ends up looking a bit strange when
quoted... oh, well.)

Actually, you don't disagree with the above statement, which I
carefully qualified with an assumption ("if you'd prefer..."), whose
condition you have discarded. ^_^
The OP can simply declare oldmain(...) with a reference to that vector:

Of course he should, and it makes for a far simpler/more elegant
solution. I was assuming that, for some reason or other, the OP
couldn't do this practically, as it seemed the obvious first choice.
But I may have been assuming too much; I should have mentioned this
explicitly. And meant to, actually.
#include <iostream>
#include <ostream>
#include <vector>
#include <iterator>

int oldmain(std::vector< std::string >& r_v)
{
std::copy( r_v.begin(),
r_v.end(),
std::eek:stream_iterator< std::string >(std::cout, "\n") );
return 0;
}

int main(int argc, char* argv[])
{
std::vector< std::string > vs;
for(int i = 0; i < argc; ++i)
{
vs.push_back(argv);
}
int result = oldmain( vs );

// in the case of cmd:
std::string cmd[ ] = {"hello", "again", "another"};
std::vector< std::string > vcmd(cmd, cmd + 3); // one past the end


My one complaint with your otherwise excellent example is the magic
number above. The moment the number of elements in cmd[] is changed,
the above line is broken.

(sizeof cmd)/(sizeof cmd[0]) has the advantage of being a good deal
more flexible, and the disadvantage of being a good deal more
complicated. This is one of the few cases in C++ where I still tend to
use a preprocessing macro, such as NUM_ELEM(ary).
oldmain( vcmd );

return result;
}

Yes, thanks for implementing the better behavior of returning
oldmain()'s result, instead of simply discarding it as in the OP's
original example.
 
D

Daniel T.

happyvalley said:
thanks a lot for your correction and your time. don't worry about
the variable name, my typo. anyway thanks for reminder basically, I
have a program running accepting arguments from char** argv. the
number of arguments is not fixed.

now I wrap this within a server, now my server receive a query
command string from the client. the string is parsered into several
tokens and I want to populate them into char** cmd and then call the
old main function oldmain(int argc, char**argv). in this way, I
can easily debug the code in standalone mode, and wrap it within the
server by just changing the main function name.

// what should this be?
http://www.research.att.com/~bs/bs_faq2.html#void-main
int oldmain( int argc, char* argv[] )
{
// do something
return 0;
}

template < typename T >
T* getPtr( vector<T>& vec )
{
return &vec[0];
}

int main()
{
vector<vector<char> > args( 1 );
const char* program = "nameofthisprograme";
copy( program, program + strlen( program ) + 1,
back_inserter( args.back() ) );
{
//create a socket
// connect to a client
// receive a string from client
string acmd = myServer.readFromClient()

stringstream os( acmd );
string temp;
while ( os >> temp ) {
args.push_back( vector< char >() );
copy( temp.begin(), temp.end(), back_inserter( args.back() )
);
args.back().push_back( 0 );
}
} // force acmd, os, and temp to release their memory

vector< char* > argv;
transform( args.begin(), args.end(), back_inserter( argv ),
&getPtr<char> );
int result = oldmain( argv.size(), &argv[0] );
// handle result
return 0;
}

The nice thing about this solution is that there is no need to delete
anything, the vector class takes care of that for you.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top