I need to create a C compatible (friendly) return type so that my C++ functions can be used to work with C-based functions.
How I can convert a vector of wstring to a wchar_t** array?
You can iterate through the wstring vector and add each wstring::c_str() to your wchart_t** array.
Far better to avoid doing this at all if you possibly can.
If you really have no choice, you'd basically do something like allocating an array of pointers, then allocating space for each string, and copying each individual string in the input to the buffer you allocated.
wchar_t *dupe_string(std::wstring const &input) {
wchar_t *ret = new wchar_t[input.size()+1];
wcscpy(ret, input.c_str());
return ret;
}
wchar_t **ruin(std::vector<std::wstring> const &input) {
wchar_t **trash = new wchar_t*[input.size()];
for (int i=0; i<input.size(); i++)
trash[i] = dupe_string(input[i]);
return trash;
}
Based on the comments, however, I have some misgivings about this applying to the current situation though -- this assumes the input is wide strings, which would typically mean UTF-16 or UTF-32/UCS-4. If the input is really in the form of UTF-8, then the storage elements you're dealing with will really be char, not wchar_t, so your input should be narrow strings (std::string) and the matching output char ** rather than wchar_t **.
wstring is a templated instantiation of basic_string, so its c_str() function returns wchar_t*.
So, you can do something like
std::vector<const wchar_t*> pointers;
pointers.reserve(wstrVec.size());
for (auto it = wstrVec.begin(); it != wstrVec.end(); ++it) {
pointers.push_back(it->c_str());
}
const whcar_t** cptr = pointers.data();
Without more context it's difficult to advise the best way to deal with scope/lifetime issues. Are you writing a library (which suggests you have no control over scope) or providing an api for callbacks from C code you are supervising?
A common approach is to provide a sizing api so that the caller can provide a destination buffer of appropriate size:
size_t howManyWstrings()
{
return wstrVec.size();
}
bool getWstrings(const wchar_t** into, size_t intoSize /*in pointers*/)
{
const size_t vecSize = wstrVec.size();
if (intoSize < vecSize || into == nullptr)
return false;
for (size_t i = 0; i < vecSize; ++i) {
into[i] = wstrVec[i].c_str();
}
return true;
}
It sounds like your C function is expecting a pointer to a wchar_t buffer, and to be able to move this pointer around.
Well, this is mostly easy, though you'll have to manage the lifetime of the pointer. To that end, I suggest not doing this as a return type (and thus letting C ruin your API, not to mention your code's sanity), but performing this logic at the call site of the C function:
/** A function that produces your vector */
std::vector<wchar_t> foo();
/** The C function in question */
void theCFunction(wchar_t**);
int main()
{
std::vector<wchar_t> v = foo();
wchar_t* ptr = &v[0];
theCFunction(&ptr);
}
BTW from the question and some comments it sounds like you misunderstand what char and wchar_t are — they sit below the encoding layer and if you have UTF-8 then you should be storing each byte of your UTF-8 string as, well, as a single byte. This means using chars, as in a std::string. Sure, each individual byte in that string will not necessarily represent a single logical unicode character, but then that is not the point of it.
This is the function for converting a vector of std::wstring to a wchar_t** based string. It also won't leak any memory because of using that DisposeBuffer(); call unlike other answers.
wchar_t ** xGramManipulator::GetCConvertedString(vector< wstring> const &input)
{
DisposeBuffer(); //This is to avoid memory leak for calling this function multiple times
cStringArraybuffer = new wchar_t*[input.size()]; //cStringArraybuffer is a member variable of type wchar_t**
for (int i = 0; i < input.size(); i++)
{
cStringArraybuffer[i] = new wchar_t[input[i].size()+1];
wcscpy_s(cStringArraybuffer[i], input[i].size() + 1, input[i].c_str());
cStringArraySize++;
}
return cStringArraybuffer;
}
And this is the DisposeBuffer Helper Function to avoid memory leaks:
void xGramManipulator::DisposeBuffer(void)
{
for (size_t i = 0; i < cStringArraySize; i++)
{
delete [] cStringArraybuffer[i];
}
delete [] cStringArraybuffer;
cStringArraybuffer = nullptr;
cStringArraySize = 0;
}
And prior to these allocate a dummy space in your constructor:
xGramManipulator::xGramManipulator()
{
//allocating dummy array so that when we try to de-allocate it in GetCConvertedString(), dont encounter any undefined behavior
cStringArraybuffer = new wchar_t*[1];
cStringArraySize = 0;
for (int i = 0; i < 1; i++)
{
cStringArraybuffer[i] = new wchar_t[1 + 1];
cStringArraySize++;
}
}
And it's all done.
Related
I am using qsort c++ function. I am passing wordArr in my insert function. The objective is to sort the letters for each word belonging to wordArr.However, while using qsort, I get write access violation. Please let me know, where is my mistake.
char* wordArr[]={"cat","bat","dog"};
int tableClass::compChar(const void* a, const void* b)//in my header file this is static
{
return *(const char*)a - *(const char*)b;
}
void tableClass::insert(char* wordArr[],const int size)
{
for (int i = 0; i < size; i++)
{
qsort(wordArr[i], strlen(wordArr[i]), sizeof(char),tableClass::compChar);
}
}
There are several problems with your code:
1) The parameters are wrong, look at the documentation
2) You're trying to modify read-only memory by reordering an array of pointers to strings allocated into a read-only area. That is not allowed and can result in undefined behavior, i.e. anything could happen.
I would suggest using std::sort for this kind of things and possibly use a stl vector
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
void sort_stuff(std::vector<std::string>& arr)
{
sort(arr.begin(), arr.end());
}
bool myfunction (char *i,char *j) {
int res = strcmp(i,j); // Needed to compare all characters
return (res < 0) ? true : false; // Weak ordering criterion
}
int main() {
std::vector<std::string> arr;
arr.push_back("cat");
arr.push_back("dog");
arr.push_back("bat");
sort_stuff(arr);
// --- edit: if you really want to use a char array ---
char cat[] = "cat";
char bat[] = "bat";
char dog[] = "dog";
char* wordArr[]={cat, bat, dog};
sort(wordArr, wordArr+sizeof(wordArr)/sizeof(char*), myfunction);
cout << wordArr[0] << wordArr[1] << wordArr[2];
return 0;
}
Try it live: http://ideone.com/ErEWnb
Edit: I'm not sure why you really want to use a char array but in case you really need it, you should
1) Put those into writeable memory (e.g. local memory, not string literals)
2) Specify the comparison function since if you pass a char pointers array straight away to sort you would compare the pointers instead of the data they point to. And make sure you compare all characters of the strings. strcmp does what you want
bool myfunction (char *i,char *j) {
int res = strcmp(i,j); // Needed to compare all characters
return (res < 0) ? true : false; // Weak ordering criterion
}
...
char cat[] = "cat";
char bat[] = "bat";
char dog[] = "dog";
char* wordArr[]={cat, bat, dog};
sort(wordArr, wordArr+sizeof(wordArr)/sizeof(char*), myfunction);
cout << wordArr[0] << wordArr[1] << wordArr[2];
Your code attempts to sort the characters of each string.
char* wordArr[] = { "cat", "bat", "dog" };
Is an array of pointers to string literals. No matter that you store the location of those character literals as char* and not as char const* (which is only possible due to the wish of the c++ standards committee to preserve backwards compatibility), changing a string literal causes undefined behavior.
In your case, the storage for the string literals will be allocated in read only memory, leading to an access violation when you attempt to write it.
By storing the string literals in memory under your own control, the access violation does not happen:
char cat[] = "cat";
char bat[] = "bat";
char dog[] = "dog";
char* wordArr[]={cat, bat, dog};
I have an immutable wstring implementation of my own, however I have a problem when actually using it.When I need the wchar array I need it null-terminated, so I do this:
wchar* String::CStr() const
{
wchar* temp = new wchar[size + 1];
for(int i = 0; i < size; i++)
{
temp[i] = data[i];
}
temp[size] = L'\0';
return(temp);
}
Now this is good and all, but I have no way of releasing the newly created wchar array, so there's a memory leak each time CStr() is used.So instead I tried using an automatic pointer to fix it:
Auto<wchar> String::CStr() const
{
wchar* temp = new wchar[size + 1];
for(int i = 0; i < size; i++)
{
temp[i] = data[i];
}
temp[size] = L'\0';
return(Auto<wchar>(temp));
}
Auto just stores the wchar* and deletes it in the destructor.Of course it didn't work at all, since the Auto<> dies at the end of the function so I get an empty wchar*.Also, since Auto<> has a destructor, this method NEVER gets inlined.So I'm in a totally wrong direction.I tried looking around std::wstring source, however it's pretty unreadable with all the internal typedefs, what I noticed is that it doesnt just store something like my wchar* data, but also a wchar* that I assume is jut 1 character(the null terminator):
_Elem *_Myptr; // pointer to allocated string
_Elem _Nul; // nul terminator for unallocated string
However it doesn't relaly use _Nul in the method, it just returns _Myptr:
const _Elem *__CLR_OR_THIS_CALL c_str() const
{ // return NTBS
return (_Myptr != 0 ? _Myptr : &_Nul);
}
However I don't see where is _Myptr being null terminated prior to being returned?Or are they just throwing it out in its raw state?
You could store null terminated string in your data array, and just return it as const wchar *. It would eliminate the unneeded copying of data.
Edit:
About extra wchar pointer in the wstring source you mentioned. It is probably the end() pointer. The implementation allocates some data buffer where to store the string, but the allocated buffer is larger then the string, so it stores the pointer to the beginning of the buffer (data) and the pointer to the end of data ( to the '\0' wchar) . This way the size() function can be easily implemented as int size() const{ return end_ptr-data; } and works even if wstring contains \0 by itself.
_Myptr is null terminated, so there is no need to add the terminator when _Myptr is returned by c_str.
I am currently writing an assignment for my class that is supposed to act as a very basic shell. I am nearly finished, but I am running into an issue with execvp and my character array of parameters. Here is a light snippet of my code.
//Split the left content args
istringstream iss(left);
while(getline(iss, s, ' ')){
v.push_back(s);
}
//Get the split string and put it into array
const char* cmd_left[v.size()+1];
for(unsigned int i = 0; i < v.size(); i++){
cmd_left[i] = v.at(i).c_str();
}
cmd_left[v.size()] = 0;
v.clear();
And this is utilized by...
execvp(cmd_left[0], cmd_left);
My error is
assign3.cxx:96:34: error: invalid conversion from ‘const char**’ to ‘char* const*’ [-fpermissive]
I understand that the problem is that my character array isn't full of constant data, so I need to essentially go from const char* to const char* const. I read something about const_cast, but I wasn't sure if that is what I need to be doing.
If you would be so kind, could you help me get my array of character arrays to be properly accepted by that function? If you need me to post more of my code, let me know.
Thanks
The problem is you cannot pass const variable to function expecting non-const argument.
other word, const char * is a subset of char *.
remove the const
/*const*/ char* cmd_left[v.size()+1];
add const_cast here
cmd_left[i] = const_cast<char *>( v.at(i).c_str() );
other parts of your code look suspicious, but this will make it compile
Without any const_cast:
istringstream iss(left);
while(getline(iss, s, ' ')){
v.push_back(s);
}
//assuming v is not empty! which you were already
string command = v[0]; //store the command in a separate variable (this makes a copy of the string)
char* cmd_left[v.size()+1]; //not a (const char)*
for(unsigned int i = 0; i < v.size(); i++){
cmd_left[i] = new char[v[i].size()+1];
strcpy(cmd_left[i], v[i].c_str()); //copy contents of each string onto a new buffer
}
cmd_left[v.size()] = NULL;
v.clear(); //if you really want to; not necessary from the code you posted
//...
execvp(command.c_str(), cmd_left);
It is not easy, sometimes not possible to create a const dynamic array of elements because all the elements have to declared within the initializer {}.
But luckily you could tell the compiler that the array you are passing is going to be const at least for the certain duration. You could do the following this would yield
&((char* const) (const_cast<char*>(cmd_left[0]) ))
The const_cast inside would remove the const-ness of the array of characters std::string is owning. So, it is quite possible that function might change the contents of array of characters behind the back of std::string. When behaviour of functions taking such argument is known then this might be ok.
If you want to create a const array of char* without resorting to const_cast or managing memory using new/delete, you could use std::vector > instead of vector of strings.
istringstream iss(left);
while(getline(iss, s, ' ')){
v.push_back(std::vector<char>(s.length()+1));
strcpy(&v.back().front(),s.c_str());
}
//Get the split string and put it into array
char* cmd_left[v.size()+1];
for(unsigned int i = 0; i < v.size(); i++){
cmd_left[i] = &v.at(i).front();
}
cmd_left[v.size()] = 0;
v.clear();
execvp(cmd_left[0], &((char* const)cmd_left[0]));
Hope this helps.
Consider the following code:
char CeaserCrypt(char str[256],int key)
{
char encrypted[256],encryptedChar;
int currentAsci;
encrypted[0] = '\0';
for(int i = 0; i < strlen(str); i++)
{
currentAsci = (int)str[i];
encryptedChar = (char)(currentAsci+key);
encrypted[i] = encryptedChar;
}
return encrypted;
}
Visual Studio 2010 gives an error because the function returns an array. What should I do?
My friend told me to change the signature to void CeaserCrypt(char str[256], char encrypted[256], int key). But I don't think that is correct. How can I get rid of the compile error?
The return type should be char * but this'll only add another problem.
encrypted is "allocated" on the stack of CeaserCrypt and might not be valid when the function returns. Since encrypted would have the same length as the input, do:
int len = strlen(str);
char *encrypted = (char *) malloc(len+1);
encrypted[len] = '\0';
for (int i = 0; i < len; i++) {
// ...
}
Don't forget to deallocate the buffer later, though (with free()).
EDIT: #Yosy: don't feel obliged to just copy/paste. Use this as a pointer to improve your coding practice. Also, to satisfy criticizers: pass an already allocated pointer to your encryption routine using the above example.
It wants you to return a char* rather than a char. Regardless, you shouldn't be returning a reference or a pointer to something you've created on the stack. Things allocated on the stack have a lifetime that corresponds with their scope. After the scope ends, those stack variables are allowed to go away.
Return a std::vector instead of an array.
std::vector<char> CeaserCrypt(char str[256],int key)
{
std::vector<char> encrypted(256);
char encryptedChar;
int currentAsci;
encrypted[0] = '\0';
for(int i = 0; i < strlen(str); ++i)
{
currentAsci = (int)str[i];
encryptedChar = (char)(currentAsci+key);
encrypted[i] = encryptedChar;
}
return encrypted;
}
There's another subtle problem there though: you're casting an integer to a character value. The max size of an int is much larger than a char, so your cast may truncate the value.
Since you're using C++ you could just use an std::string instead. But otherwise, what your friend suggested is probably best.
There are a few problems here. First up:
char CeaserCrypt(char str[256],int key)
As others have pointed out, your return type is incorrect. You cannot return in a single character an entire array. You could return char* but this returns a pointer to an array which will be allocated locally on the stack, and so be invalid once the stack frame is removed (after the function, basically). In English, you'll be accessing that memory address but who knows what's going to be there...
As your friend suggested, a better signature would be:
void CeaserCrypt(char* encrypted, const char str*, const size_t length ,int key)
I've added a few things - a size_t length so you can process any length string. This way, the size of str can be defined as needed. Just make sure char* encrypted is of the same size.
Then you can do:
for(int i = 0; i < length; i++)
{
// ...
For this to work your caller is going to need to have allocated appropriately-sized buffers of the same length, whose length you must pass in in the length parameter. Look up malloc for C. If C++, use a std::string.
If you need C compatibility make encrypted string function argument.
If not, than use C++ std::string instead C style string.
And also In your code encrypted string isn't ending with '\0'
The problem with the original code is that you are trying to return a char* pointer (to which your local array decayed) from a function that is prototyped as one returning a char. A function cannot return arrays in C, nor in C++.
Your friend probably suggested that you change the function in such a way, that the caller is responsible for allocation the required buffer.
Do note, that the following prototypes are completely equal. You can't pass an array as a parameter to normal function.
int func(char array[256]);
int func(char* array);
OTOH, you should (if you can!) decide the language which you use. Better version of the original (in C++).
std::vector<unsigned char> CeaserCrypt(const std::string& str, const int key)
{
std::vector<unsigned char> encrypted(str.begin(), str.end());
for (std::vector<unsigned char>::iterator iter = vec.begin();
iter != vec.end(); ++iter) {
*iter += key;
}
return vec;
}
Do note that overflowing a signed integer causes undefined behavior.
VS2010 is "yelling" at you because you are trying to return a value that is allocated on the stack, and is no longer valid once your function call returns.
You have two choices: 1) Allocate memory on the heap inside your function, or 2) use memory provided to you by the caller. Number 2 is what your friend in suggesting and is a very good way to do things.
For 1, you need to call malloc() or new depending on whether you are working in C or C++. In C, I'd have the following:
char* encrypted = malloc(256 * sizeof(char));
For C++, if you don't want to use a string, try
char* encrypted = new char[256];
Edit: facepalm Sorry about the C noise, I should have looked at the question more closely and realized you are working in C++.
You can just do your Ceaser cipher in place, no need to pass arrays in and out.
char * CeaserCrypt(char str[256], int key)
{
for(unsigned i = 0; i < strlen(str); i++)
{
str[i] += key;
}
return str;
}
As a further simplification, skip the return value.
void CeaserCrypt(char str[256], int key)
{
for(unsigned i = 0; i < strlen(str); i++)
{
str[i] += key;
}
}
well what you're returning isn't a char, but a char array. Try changing the return type to char*(char* and a char array are ostensibly the same thing for the compiler)
char* CeaserCrypt(char str[256],int key)
EDIT: as said in other posts, the encrypted array will probably not be valid after the function call. you could always do a new[] declaration for encrypted, remembering to delete[] it later on.
As said in the title, the goal is to copy a C-style string into memory without using any standard library functions or subscripting.
Here is what I have so far [SOLVED]
#include "std_lib_facilities.h"
char* strdup(const char* p)
{
int count = 0;
while (p[count]) ++count;
char* q = new char[count+1];
for (int i = 0; i < count + 1; ++i) *(q + i) = *(p + i);
}
int main()
{
char word[] = "Happy";
char* heap_str = strdup(word);
}
Obviously the problem is that allocating just *p (which is equivalent to p[0]) only allocates the letter "H" to memory. I'm not sure how to go about allocating the C-style string without subscripting or STL functions.
C-style string ends with '\0'. You need to traverse the string inside the function character by character until you encounter '\0' to know how long it is. (This is effectively what you would do by calling strlen() to work it out.) Once you know how long the string is, you can allocate the right amount of memory, which is the length+1 (because of the '\0').
To access the i'th element of an array p, one use subscript: p[i].
Subscript of the form p[i] is formally defined to be *((p)+(i)) by both the C standard (6.5.2.1 of C99) and the C++ standard (5.2.1 of C99). Here, one of p or i is of the type pointer to T, and the other is of integral type (or enumeration in C++). Because array name is converted automatically (in most types of use anyway) to a pointer to the first element of said array, p[i] is thus the i'th element of array p.
And just like basic arithmetic, ((p)+(i)) is equivalent to ((i)+(p)) in pointer arithmetic. This mean *((p)+(i)) is equivalent to *((i)+(p)). Which also mean p[i] is equivalent to i[p].
Well, since this a self-teaching exercise, here's an alternative look at a solution that can be compared/contrasted with KTC's nice explanation of the equivalence between subscripting and pointer arithmetic.
The problem appears to be, "implement a strdup() function without using standard library facilities or subscripting".
I'm going to make an exception for malloc(), as there's no reasonable way to do the above without it, and I think that using it isn't detrimental to what's being taught.
First, let's do a basic implementation of strdup(), calling functions that are similar to the ones we might use from the library:
size_t myStrlen( char* s);
void myStrcpy( char* dst, char* src);
char* strdup( char* p)
{
size_t len = myStrlen( p);
char* dup = (char*) malloc( len + 1); /* include space for the termination character */
if (dup) {
myStrcpy( dup, p);
}
return dup;
}
Now lets implement the worker functions without subscripting:
size_t myStrlen( char* s)
{
size_t len = 0;
while (*s != '\0') { /* when s points to a '\0' character, we're at the end of the string */
len += 1;
s += 1; /* move the pointer to the next character */
}
return len;
}
void myStrcpy( char* dst, char* src)
{
while (*src != '\0') { /* when src points to a '\0' character, we're at the end of the string */
*dst = *src;
++dst; /* move both pointers to next character location */
++src;
}
*dst = '\0'; /* make sure the destination string is properly terminated */
}
And there you have it. I think this satisfies the condition of the assignment and shows how pointers can be manipulated to move though an array of data items instead of using subscripting. Of course, the logic for the myStrlen() and myStrcpy() routines can be moved inline if desired, and more idiomatic expressions where the pointer increment can happen in the expression that copies the data can be used (but I think that's more confusing for beginners).