Im trying to convert the command line arguments to string form instead of char*, but it obviously isnt working since Im asking this question
Heres the code:
Code:
string* charstararray2stringarray(int args, char* argv[]);
int main(int args, char* argv[])
{
string* stringarray;
stringarray = charstararray2stringarray(args,argv);
retrun 0;
}
string* charstararray2stringarray(int args, char* argv[])
{
//converts char*[] to string[]
//used for command line
string* retVal;
retVal = new string[args];
for (unsigned int i = 0; i <= args; i++)
{
retVal[i] = (string)argv[i];
}
return *retVal;
delete [] retVal;
}
You basically have the typical array-returning problem that many new C/C++ programmers have.
You should never return an array from a function. It will always get you into trouble.
It's a matter of scoping. Consider this code:
Code:
int *retar();
int main()
{
int *ar = retar();
}
int *retar()
{
int ar[10] = {0};
return ar;
}
Where's the problem with that code? ar in retar is created on the stack, therefore it is destroyed once the function exits. ar in main now contains a pointer to the destroyed array, it is invalid memory!
You might want to solve this by using new or malloc (as you have done). Then there is the problem of freeing this memory. The caller should not be responsible for this, after all he can't know it's really dynamic memory, it could be something else. You're bound to get memory leaks when you do this.
Neither can the calling function free the memory. There are two ideas:
Code:
int *funcy()
{
int * p = new int[20];
// free the memory
delete [] p;
// and return
return p;
}
This obviously can't work as p is invalid after the delete.
Here's what you did:
Code:
int *morefunc()
{
int *p = new int[20];
return p;
delete [] p;
}
Now why doesn't this work?
The moment the cpu encounters the return statement it leaves the function. The delete line is never executed. You have a memory leak.
The Solution
You never return an array. Instead the called passes a buffer which will be filled.
A buffer is any memory location. It can be statically allocated, dynamically allocated, it doesn't matter because the caller knows what to do with it. To prevent overflow (writing more data in the buffer than it can hold) the size of the buffer is passed too, either in bytes or (better) in the number of elements it can hold.
This would work:
Code:
// return value is usually the actual number of elements written
// but could also be some sort of error code
int charstararray2stringarray(int bufsize, string *buffer, int args, char * argv[]);
int main(int args, char *argv[])
{
// you could either allocate a static array:
// string ararg[20];
// or dynamically allocate it
string *ararg = new string[args];
int elems = charstararray2stringarray(args /* or 20 if statically allocated*/,
ararg, args, argv);
// if you allocated dynamically, you must free it
delete [] arargs;
}
All the buzzt CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
Thanks for spending the effor to teach me this. It is much appreciated
But:
What would be the code for the charstararraytostringarray function in the solution? What do I do with the new variable passed to it? instead of returning something I change the address of the ararg? If so then whats elems there for?
int charstararray2stringarray(int bufsize, string *buffer, int args, char * argv[])
{
int count = min(args, bufsize);
for (unsigned int i = 0; i < count; ++i)
{
buffer[i] = argv[i];
}
return count;
}
Some things:
a) in loops that traverse an array from start to end, it's always
for(loopvar = 0; loopvar < arlength, ++loopvar)
or loopvar++, doesn't really matter on a good compiler.
If you use loopvar <= arlength then there will be one iteration where loopvar == arlength. Since C/C++ arrays start indexing at 0, arlength is not a valid index anymore.
b) You don't do (string)"text" to convert a char array to string. This is the old C-style cast and not to be used. Instead you either explicitly call the contructor: string("text") or in this case take advantage of the fact that the = operator is overloaded to take char*:
string s = "text";
This avoid creating a temporary string object and is therefore faster.
All the buzzt CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
for (unsigned int i = 0; i < count; ++i)
{
buffer[i] = argv[i];
}
return count;
}
Take away unsigned since count is signed, it will give compiler warnings... i dont know if this is usefull but i dont like seeing ANY ERRORS or WARNINGS when i compile :P
Originally posted by MoMad Take away unsigned since count is signed, it will give compiler warnings... i dont know if this is usefull but i dont like seeing ANY ERRORS or WARNINGS when i compile :P
Rather than removing the unsigned, make sure that count is unsigned (which it should be).
I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You". -- Linus Torvalds
Originally posted by CornedBee You fill the provided array:
Code:
int charstararray2stringarray(int bufsize, string *buffer, int args, char * argv[])
{
int count = min(args, bufsize);
for (unsigned int i = 0; i < count; ++i)
{
buffer[i] = argv[i];
}
return count;
}
Some things:
a) in loops that traverse an array from start to end, it's always
for(loopvar = 0; loopvar < arlength, ++loopvar)
or loopvar++, doesn't really matter on a good compiler.
If you use loopvar <= arlength then there will be one iteration where loopvar == arlength. Since C/C++ arrays start indexing at 0, arlength is not a valid index anymore.
b) You don't do (string)"text" to convert a char array to string. This is the old C-style cast and not to be used. Instead you either explicitly call the contructor: string("text") or in this case take advantage of the fact that the = operator is overloaded to take char*:
string s = "text";
This avoid creating a temporary string object and is therefore faster.
I got:
cant convert from char* to string, and min() not defined...
Hey CB, whats that you said about gcc and post-incrementing? Is it not good??
Isnt i++ and ++i in a for loop the same, since as soon as its out of that line, it will increment, or it will increment first, then execute the line. hmm... in msvc i realized that it doesnt matter weather or not u post/pre increment in the FOR loop, because by the time it finishes with that line:
step 1
step 2
step 4
step 3
// repeat 4 and 3 as necessary
then step 5
[/php]
so each step thru, it will only do the increments either before the step or after (pre/post). But in step 3, there is nothing else going on, so it doesnt matter wether u use pre or post increment/decrement.
So, after all this ranting, i wanna ask you weather or not you agree with this or what is with the ++i (maybe a preference or ?)
Maybe I shouldnt praise myself just yet. I came across a problem when cout-ing the first 3 elements in ararg. When I type './a.out arg2 arg3' I get two Q's with squiggles in them (the first is lowercase and the seocnd is upper) that I get after the bash prompt. There isnt even a new line where I had the endl on the cout statements. No compiler errors or warnings...
Actually it is more likely that the inc e?x instructions would be add e?x 1 instructions, they are nearly equivalent.
If you compile in release mode you'll have no code at all.
Where is the difference between the two commands? Obviously only the register in which the value is saved. eax is called the accumulator, it is the best register for mathematical operations and is treated in a special way by the cpu: additions are much faster there than anywhere else. add eax ??? takes 2 cycles compared to 7 in any other register!
All compilers will by default do a i++ in edx and a ++i in eax, this is why ++i is faster.
doesn't really matter on a good compiler.
I said this because I assume that if nothing special is done most compilers are smart enough to optimize this difference away and do a i++ in eax. Yet I'm not sure.
All the buzzt CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.