Dealing with char ** argv - c++

How do I assign a sequence of character strings to a char ** argv variable in a program? Its a command line argument. I'm currently trying to convert an .exe app to a dll.
For example:
{ "string1", "string2", "string3" } --- > char ** argv variable
My problem is somehow realted to this:
How does an array of pointers to pointers work? but I can't get it to work using the snippet shown there. Help!

const char* argv[] = {"string1", "string2", "string3", 0};
If the arguments aren't compile time constants I would do something like:
std::vector<const char*> arguments;
arguments.push_back(somePointer);
arguments.push_back(someOtherPointer);
arguments.push_back(0);
const char** argv = &arguments[0];
EDIT: Using PaxDiablos information that an argv-array should be null terminated.

what about getopt?

Note that Andreas Brincks answer is really what you want to do, where vector does all the heavy lifting of allocation and provides exception safety. I strongly suggest that you look into changing whatever reason there is for not being able to use vector. But if you really really cannot do so, I guess you could do something along the lines of the below code:
int numArgs = YOUR_NUMBER_HERE;
char **myArgv = new char*[numArgs+1];
for (int i=0; i<numArgs; ++i) {
myArgv[i] = new char[at least size of your argument + 1];
strncpy(myArgv[i], whereever your string is, buffer size);
myArgv[buffer size] = '\0';
}
myArgv[numArgs] = NULL;
// use myArgv here
// now you need to manually free the allocated memory
for (int i=0; i<numArgs; ++i) {
delete [] myArgv[i];
}
delete [] myArgv;

Related

Inside for loop: Convert text and int to const char* and pass to function

I'm trying to convert some text plus an int to const char* inside a "for loop", and then pass this const char* to a function from a library (HTTPClient - mbed). (The function from the library only accepts const char* as parameters, and it simply adds the const char* values to an array, and later on these values are send using HTTP POST).
This is my code:
for (int i = 0; i < 3; i++) {
char buf1[16];
char buf2[16];
char buf3[16];
sprintf(buf1,"%d",i);
sprintf(buf2,"Hello%d",i);
sprintf(buf3,"World%d",i);
const char* value1 = buf1;
const char* value2 = buf2;
const char* value3 = buf3;
map.put("id[]", value1);
map.put("test1[]", value2);
map.put("test2[]", value3);
}
But it seems that the values get overwritten during each loop, so that when the HTTP POST is executed the following values are send:
2 Hello2 World2
2 Hello2 World2
2 Hello2 World2
Instead of:
0 Hello0 World0
1 Hello1 World1
2 Hello2 World2
I know this has something to do with the fact that a const char* is a pointer, but i'm not sure how to fix it.
I hope you guys can help me.
Thanks!
On each iteration of the loop variables bufN get created and destroyed, but they happen to be created at the same address on the stack (otherwise loops would exhaust stack space).
It looks like map.put doesn't copy the strings but rather stores pointers to the strings, your bufN variables, which get overwritten with new values on each iteration, this is why you see the last written values.
Also note that bufN variables no longer exist after the loop terminate, so that the pointers stored in map become invalid. It just so happens that this memory wasn't overwritten with something else.
A fix would be to allocate space for all buffers, e.g.:
constexpr int N = 3;
char bufs[N][3][16];
for(int i = 0; i < N; ++i) {
snprintf(bufs[i][0], sizeof bufs[i][0], "%d", i);
snprintf(bufs[i][1], sizeof bufs[i][1], "Hello%d", i);
snprintf(bufs[i][2], sizeof bufs[i][2], "World%d", i);
map.put("id[]", bufs[i][0]);
map.put("test1[]", bufs[i][1]);
map.put("test2[]", bufs[i][2]);
}
You need to make sure that map doesn't try to access the strings after bufs variable has been destroyed (went out of scope).

How can I use a search function on a dynamic array?

I'm trying to use a linear search function on a dynamic array I created but then the teaching assistant for my computer science class told us that most search functions use const arrays.
Is there any way I can edit my dynamic array to become contant? Or is it also possible to make a search function that uses a dynamic array (and would not give errors?).
I'll give a brief insight into my code:
I dynamically create an array using the rows I read in from a file and then dynamically allocate each row to an array of columns.
char ** domain[] = new char * [rows];
for(int i = 0; i < rows; i++)
{
*domain = new char[columns];
domain++;
}
The type of function that we were taught for searching is:``
char searchArray( const char list[], char letter, int maxSize)
{
>code goes here
}
Is there any other method of using a search function that takes in dynamic multidimensional arrays?
In response to the comments, I can't use vectors. This is an assignment for us to use normal arrays. I haven't been taught how to to use vectors yet.
In the line
char ** domain[] = new char * [rows];
char ** domain[] tries to make an array of char **. If the compiler didn't complain about not having a valid array size in the [] and you would have a 3D structure. You want just plain old char ** for a 2D structure, so
char ** domain = new char * [rows];
The loop filling out the inner dimension is correct except it loses track of the starting point of domain
for(int i = 0; i < rows; i++)
{
*domain = new char[columns];
domain++;
}
Should be something like
char ** temp = domain;
for(int i = 0; i < rows; i++)
{
*temp = new char[columns];
temp++;
}
To preserve the starting point, but for this case array notation is probably the smarter and easier-to-read option.
for(int i = 0; i < rows; i++)
{
domain[i] = new char[columns];
}
On to searchArray. It needs to know it's getting two dimensions, (const char **) and that there are two max sizes (maxRow and maxColumn). It will look something like
char searchArray(const char ** list,
char letter,
int maxRow,
int maxColumn)
{
>code goes here
}
Code goes here is your problem, but will probably be two nested for loops iterating to maxRow and maxColumn and returning when letter is found.
But... Why return a char? Returning the location in the array is much more useful. We could use std::pair, but if std::vector is off limits, pair probably is as well. Consider something like the following instead:
struct coord
{
int row;
int column;
};
coord searchArray(const char ** list,
char letter,
int maxRow,
int maxColumn)
{
coord location;
>code goes here
return location;
}
If the item is not found, set row and column to something impossible to get like -1 so you can easily test for the not found case.
Stop here unless you want to <expletive deleted> with your teacher's brain.
The above doesn't build a 2D array. You can't get a dynamically allocated 2D array in C++. What you have is an array of arrays. There are a couple downsides to this, look at all the work that goes into stitching one together and computers love it when things go in straight lines. Array of arrays doesn't. Every different allocation can be somewhere completely different in memory forcing the program to hop around, waiting on and loading different chunks of memory. Sometimes The program will spend more time sitting around waiting for stuff to be found and loaded than it'll spend doing the actual work. This sucks.
The solution is to make a 1D array and make it look like a 2D array. Here's an example of that from the C++ FAQ
You'll learn a lot of neat stuff from following this example, not the least of which being RAII and the Rule of Three, two concepts without which you cannot write non-trivial high quality C++ code.

Asisgn LPCWSTR array from std::wstring

I am creating a dynamic array of LPCWSTR, and want to assign values at run time.
I have following code :
cin>>count
LPCWSTR * lpwcstrArray = new LPCWSTR[count]();
for (int i = 0; i < count; i++)
{
// some logic to create different wstring on each iteration
wstring tempWString = L"somerandomstuff";
lpwcstrArray[i] = reinterpret_cast<LPSWSTR>tempWString.c_str();
}
Now if i access lpwcstrArray - all the indexs point at data of last string that was assigned.
I know this is not correct way to assign values, but i do not know the correct way.
wstring tempWString is created and destroyed with each iteration of the loop.
You have dangling pointers in your lpwcstrArray and are experiencing undefined behaviour when you access one of them.
You need to allocate the space yourself or use a std::wstring as the array type instead of a LPCWSTR.
You are storing pointers that point at the internals of temporary std::wstring objects. When those objects are destroyed on each loop iteration, your array is left with danging pointers. You need to dynamically allocate the individual strings instead, eg:
std::cin >> count
LPWSTR *lpwstrArray = new LPWSTR[count];
for (int i = 0; i < count; i++)
{
// some logic to create different wstring on each iteration
std::wstring tempWString = L"somerandomstuff";
LPWSTR str = new WCHAR[tempWString.length()+1];
const wchar_t *p = tempWString.c_str();
std::copy(p, p+tempWString.length(), str);
lpwstrArray[i] = str;
}
// use lpwstrArray as needed...
// don't forget to free the memory when you are done using it...
for (int i = 0; i < count; i++)
delete[] lpwstrArray[i];
delete[] lpwstrArray;
Depending on what you are really trying to accomplish, something more like the following would be safer, at least if you just need read-only access to the strings (which you likely do, as the C in LPCWSTR stands for const, so the user of the array is not going to be modifying them):
std::cin >> count
std::vector<std::wstring> wstrArray(count);
for (int i = 0; i < count; i++)
{
// some logic to create different wstring on each iteration
wstrArray[i] = L"somerandomstuff";
}
std::vector<LPWSTR> lpwstrArray(count);
for (int i = 0; i < count; i++)
lpwstrArray[i] = const_cast<wchar_t*>(wstrArray[i].c_str());
// use lpwstrArray as needed. if you need to pass it where an
// LPWSTR* is expected, you can use &lpwstrArray[0] for that...
// lpwstrArray and wstrArray will be freed automatically
// when they go out of scope...
Try the approach
std::wstring ws(_T("Hello"));
LPCTSTR lps= (LPCTSTR)(ws.c_str());
TRACE(lps);
Notes:
You should not use the W types directly (ex: LPCWSTR). Use the T types instead (ex: LPCTSTR). Why? Because they will automatically translate to the version they should be (LPCSTR for non-Unicode / ASCII; LPCWSTR for Unicode), depending on your project.
For the same reason you should surround your strings with _T() or precede them with an L.
Try to dive deep using "Go To Definition" successively beginning on LPCTSTR
See also the _tcscpy_s function documentation

copy char* to std::string at the specified pos not allocating new objects

Let me ask my question by code:
char* apples = "apples";
std::string str("I like .....");
// need to copy apples to str to have "I like apples", without creating new objects
There is assign function but unfortunately it seems is not possible to provide std::string offset.
I do not want to allocate new object as this is low-latency and frequently part of code.
upd by mistake i've put 5 dots above but I meant 6 dots to fit "apples" perfectly :) Of course if string capacity is not enought some objects have to be created. In my question I assume that string capacity is enough.
You can use std::copy algorithm http://www.cplusplus.com/reference/algorithm/copy/
std::copy(apples, apples + sz, str.begin() + offset);
Why not use std::string::replace?
Even assign will copy the content of whatever you pass to it. You will not be able to do what you try to. A string holds a pointer to a continuous block of characters in the memory. You can not just glue arbitrary things to it.
The answer of using the std::copy() algorithm is the best one AFAIK. You could also use plain old C (you understand, it is not actually C, C style would be a better name) to achieve the same thing:
char* apples = "apples";
std::string str("I like .....");
char * ptr = apples;
while( *ptr != 0 ) {
str.push_back( *ptr );
++ptr;
}
As you can see, there is no temporary object created here, but... Does that mean there are no allocations in the process? Indeed they are.
A std::string is basically a vector of chars. The string has a capacity() method that returns how many extra chars can be appended without triggering another allocation (which can involve a reallocation, thus copying the whole vector). The best you can do in order to avoid allocations is to ensure that the string will have enough space for all characters to insert.
char* apples = "apples";
std::string str("I like .....");
str.reserve( str.length() + strlen( apples ) );
char * ptr = apples;
while( *ptr != 0 ) {
str.push_back( *ptr );
++ptr;
}
This way you can ensure that there will be one allocation only in the std::string: the one triggered with reserve().
Hope this helps.
char * apples = "apples";
string something = "I like ....";
for (int i = 0; i < something.length() - 1; i++)
{
if (something.find('.'))
something.pop_back();
}
something.resize(something.length() + 1);
for (int i = 0; i < strlen(apples); i++)
something.push_back(apples[i]);
cout << something <<endl;

Is it possible to pass char[][] to a function requesting char**?

I am trying to call a function that takes char** as a parameter. Its job is to fill an array of strings (i.e. an array of char*). I know the max length of the strings, and I can pass the max number to fill as another parameter, so I was hoping to stack allocate it like this:
fill_my_strings(char** arr_str, int max_str); // function prototype
char fill_these[max_strings][max_chars_per_string]; // allocating chars
fill_my_strings(fill_these, max_strings); // please fill them!
Of course, I get the "cannot convert char[max_strings][max_chars_per_string] to char**" error.
I know this is some subtle (or not-so-subtle) problem with my understanding of the difference between arrays and pointers. I'm just not sure why it's not possible to pass this block of memory to something wanting a char** and have it fill in my stack-allocated chars. Could somebody please explain if this is possible, or if not, why not?
Is it possible to call a function like this without calling malloc / new?
The simple answer to your question is no; a two dimensional array is different than a pointer-to pointer type. Arrays decay to pointers to their first element, but pointers actually are that value.
The difference between these types is clear, if you cast both to char*
int x;
char *arr_pp[] = {"foo", "bar", "baz"};
char arr_2d[][4] = {"foo", "bar", "baz"};
char *cp = (char*)arr_pp;
for(x=0; x<3; x++)
printf("%d ", cp[x]);
printf("\n");
cp = (char*)arr_2d;
for(x=0; x<3; x++)
printf("%d ", cp[x]);
printf("\n");
The output (on my computer) is:
-80 -123 4
102 111 111
Where the first row is gibberish formed by the fact that I'm printing an address cast into bytes, and the second row is the ascii values of "foo".
In a function taking a char ** the compiler can't know to decay array types, which don't actually contain pointers.
Suppose you have n pointers to strings of m-1 maximum characters (m characters including the NULL).
So, in pure C:
sizeof(char[n][m]) will return n*m.
sizeof(char**) will return the size of a pointer in your architecture, probably 32 (if x86) or 64 (if x86_64).
char[n][m] actually allocates the n*m byte contiguously. char** allocates a single pointer. This pointer references a memory stripe of *n bytes. Each of these n pointers points to a memory stripe of m characters.
So, considering that sizeof(char) == u, if you declare char a[n][m], when you use a[i][j], the compiler understands *(a + i*m*u + j*u).
So, considering that sizeof(char *) == w, if you declare char **a, when you use a[i][j], the compiler understands ((a + i*w) + j*w).
Completely different data management.
The closes thing you could do to handle your special case is to create a char** variable, and populate it with the addresses of your stack allocated matrix.
char **tmp = malloc(max_strings * sizeof(char *));
int i;
for(i = 0; i < max_strings; i++){
tmp[i] = &(fill_these[i][0]); //you probably can't reference a char[][] with a single index - not confirmed
}
I am not sure why fill_my_strings() need a char** parameter. From your example, caller have already allocated the memory from stack. So using a char* should be OK.
But if you want to use char** or you can't modify the fill_my_strings() function, try following example code:
void fill_my_strings(char** arr_str, int max_chars_per_string, int max_strings)
{
for(int i = 0; i < max_strings; ++i)
{
//Make sure you have enough space
memcpy(*arr_str, "ABCD", sizeof("ABCD"));
*arr_str += max_chars_per_string;
}
}
char fill_these[max_strings][max_chars_per_string];
char* pointer = (char*)fill_these;
fill_my_strings(&pointer, max_strings, max_chars_per_string);
The obvious thing to do is build an index
In c use something like:
char string_list[num_strings][str_length];
// ...
char**index = calloc( (num_strings+1), sizeof(*index) ); // calloc insures NULL termination
for (int i=0; i<num_strings; ++i) {
index[i] = string_list[i]
}
In c++ prefer new[] to calloc;