Converting std::wsting to char* with wcstombs_s - c++

I have input strings that contain only digits (just the plain Latin ones, 0-9, so for example "0123"), stored as std::wstring, and I need each as a char*. What's the best way for me to do this? This is my initial approach:
void type::convertWStringToCharPtr(_In_ std::wstring input, _Out_ char * outputString)
{
outputString = new char[outputSize];
size_t charsConverted = 0;
const wchar_t * inputW = input.c_str();
wcstombs_s(&charsConverted, outputString, sizeof(outputString), inputW, input.length());
}
EDIT: The code below works. Thanks all!
void type::convertWStringToCharPtr(_In_ std::wstring input, _Out_ char * outputString)
{
size_t outputSize = input.length() + 1; // +1 for null terminator
outputString = new char[outputSize];
size_t charsConverted = 0;
const wchar_t * inputW = input.c_str();
wcstombs_s(&charsConverted, outputString, outputSize, inputW, input.length());
}

You are not allocating enough memory for your buffer:
char * outputString = new char[input.length()];
Should be
char * outputString = new char[input.length() + 1];
because of terminating NUL-character.
Oh, and also, as per pm100's comment: sizeof(outputString) is giving you the size of the pointer. You should use input.length() + 1, as that is the size of the buffer.

There are a couple of errors in your code. First, you're not allocating enough space in your destination buffer for the NULL character. You must allocate at least input.length() + 1 chars for the function to succeed.
Second, you're not passing in the correct size of the output buffer to the function. sizeof(outputString) returns the size of outputString itself, a char *, and not the number of bytes pointed to by that pointer.
So your function should look like this:
void CoverageTileManager::convertWStringToCharPtr(_In_ std::wstring input, _Out_ char * outputString)
{
size_t outputSize = input.length() + 1;
outputString = new char[outputSize];
size_t charsConverted = 0;
wcstombs_s(&charsConverted, outputString, outputSize, input.c_str(), input.length());
// TODO verify charsConverted = outputSize
}

In C++ I would never use pure pointers: use vector if a char array needed in heap! Do you want to copy the source string? If not, const reference should be used for input. wcstombs_s is used only in Windows, so why doesn't use simply WideCharToMultiByte? Was the conversion success? Return value.
bool CoverageTileManager::convertWStringToCharPtr(const std::wstring& input, std::vector<char>& outputString )
{
if ( input.empty() ) {
return false;
}
int size = WideCharToMultiByte(CP_ACP,0,input.c_str(),input.size(),NULL,0,NULL,NULL);
if ( size <= 0 ) {
return false;
}
outputString.resize(size+1);
if ( WideCharToMultiByte(CP_ACP,0,input.c_str(),input.size(),&outputString[0],size,NULL,NULL) <= 0 ) {
outputString.clear();
return false;
}
outputString[size] = '\0';
return true;
}
Use vector to external C++ lib:
extern void call( const char*, size_t);
std::vector<char> buffer;
std::wstring input;
...
if ( convertWStringToCharPtr(input,buffer) ) {
call(&buffer[0],buffer.size());
}

Related

Return without memory leak

I try to write a function which converts a char* to a wchar_t* to simplify multiple steps in my program.
wchar_t* ConvertToWString(char* str)
{
size_t newStrSize = strlen(str) + 1;
wchar_t* newWStr = new wchar_t[newStrSize];
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, newWStr , newStrSize, str, _TRUNCATE);
return newWStr; // I know i need to call "delete[] newWStr;" but then I can't return the converted string...
}
The function works but it is obviously memory leaking. Does someone know another way how to convert a char* to a wchar_t*?
My issue is that the function needs to handle different string lengths.
Right now I am using a workaround with a fixed buffer but that can't be the only solution:
wchar_t* ConvertToWStringUgly(char* str)
{
wchar_t buffer[1024]; // fixed array for 1023 wchars
size_t newStrSize = strlen(str) + 1;
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, buffer, newStrSize, str, _TRUNCATE);
return buffer; // This is working but not really a good way
}
Classic. Use the C++ power ! ... Destructors freeing allocated memory
Instead of your
wchar_t buffer [1024];
why not declare and use a Wstr class, looking approximately like this (maybe malloc and free to used instead of new and delete ?):
class Wstr {
public :
Wstr () : val_ ((wchar_t*) NULL), size_ (0) {}
~Wstr () {
if (val_ != (wchar_t*)NULL) {
delete[] val_;
val_ = (wchar_t*)NULL;
}
}
Wstr& operator = (const char*& str) {
size_ = strlen(str) + 1;
if (val_ != (wchar_t*) NULL) {
delete [] val_;
val_ = (wchar_t*) NULL;
}
size_t newStrSize = strlen(str) + 1;
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, val_, newStrSize, str, _TRUNCATE);
size_ = newStrSize;
return *this;
}
//.. copy cons, op =, op ==, op != to be written
wchar_t* val_;
size_t size_;
};

Print the results of MD5 function

I want to print MD5 for some string. For this I have done the the function
std::string generateHashMD5(std::string text)
{
unsigned char * resultHash;
resultHash = MD5((const unsigned char*)text.c_str(), text.size(), NULL);
std::string result;
result += (char *) resultHash;
return result;
}
Mow I want to print the result of this function. I try to version of such function.
void printHash(std::string hash)
{
for (unsigned i = 0; i < str.size(); i++)
{
int val = (short) hash[i];
std::cout<<std::hex<<val<<':';
}
std::cout<<std::endl;
}
std::string printHash(std::string hash)
{
char arrayResult[200];
for(int i = 0; i < 16; i++)
sprintf(&arrayResult[i*2], "%02x", (unsigned short int)hash[i]);
std::string result;
result += arrayResult;
return result;
}
The problem is that unfortunately none of it does not show correct result. What should be changed in this function or where is the mistakes?
You improperly use std::string as a buffer:
result += (char *) resultHash;
treats resultHash as a c-string, so if there is \0 byte in middle it would not get enough data. If there is no \0 byte you would copy too much and get UB. You should use constructor with size:
std::string result( static_cast<const char *>( resultHash ), blocksize );
where block size probably is 16. But I would recommend to use std::array<uint8_t,blocksize> or std::vector<uint8_t> instead os std::string, as std::string for buffer is very confusing.
in case if MD5 returns byte array
result += (char *) resultHash;
return result;
conversion to string will lose numbers after 0 because string constructor interprets input as null-terminated string
so vector can be used or string construction with explicit number of characters.
Still, there are not enough information to say exactly

C++ - How to append a char to char*?

I've tried so may ways on the Internet to append a character to a char* but none of them seems to work. Here is one of my incomplete solution:
char* appendCharToCharArray(char * array, char a)
{
char* ret = "";
if (array!="")
{
char * ret = new char[strlen(array) + 1 + 1]; // + 1 char + 1 for null;
strcpy(ret,array);
}
else
{
ret = new char[2];
strcpy(ret,array);
}
ret[strlen(array)] = a; // (1)
ret[strlen(array)+1] = '\0';
return ret;
}
This only works when the passed array is "" (blank inside). Otherwise it doesn't help (and got an error at (1)). Could you guys please help me with this ? Thanks so much in advanced !
Remove those char * ret declarations inside if blocks which hide outer ret. Therefor you have memory leak and on the other hand un-allocated memory for ret.
To compare a c-style string you should use strcmp(array,"") not array!="". Your final code should looks like below:
char* appendCharToCharArray(char* array, char a)
{
size_t len = strlen(array);
char* ret = new char[len+2];
strcpy(ret, array);
ret[len] = a;
ret[len+1] = '\0';
return ret;
}
Note that, you must handle the allocated memory of returned ret somewhere by delete[] it.
Why you don't use std::string? it has .append method to append a character at the end of a string:
std::string str;
str.append('x');
// or
str += x;
The function name does not reflect the semantic of the function. In fact you do not append a character. You create a new character array that contains the original array plus the given character. So if you indeed need a function that appends a character to a character array I would write it the following way
bool AppendCharToCharArray( char *array, size_t n, char c )
{
size_t sz = std::strlen( array );
if ( sz + 1 < n )
{
array[sz] = c;
array[sz + 1] = '\0';
}
return ( sz + 1 < n );
}
If you need a function that will contain a copy of the original array plus the given character then it could look the following way
char * CharArrayPlusChar( const char *array, char c )
{
size_t sz = std::strlen( array );
char *s = new char[sz + 2];
std::strcpy( s, array );
s[sz] = c;
s[sz + 1] = '\0';
return ( s );
}
The specific problem is that you're declaring a new variable instead of assigning to an existing one:
char * ret = new char[strlen(array) + 1 + 1];
^^^^^^ Remove this
and trying to compare string values by comparing pointers:
if (array!="") // Wrong - compares pointer with address of string literal
if (array[0] == 0) // Better - checks for empty string
although there's no need to make that comparison at all; the first branch will do the right thing whether or not the string is empty.
The more general problem is that you're messing around with nasty, error-prone C-style string manipulation in C++. Use std::string and it will manage all the memory allocation for you:
std::string appendCharToString(std::string const & s, char a) {
return s + a;
}
char ch = 't';
char chArray[2];
sprintf(chArray, "%c", ch);
char chOutput[10]="tes";
strcat(chOutput, chArray);
cout<<chOutput;
OUTPUT:
test

how to search a part of a string not all of it

in c++ how to search just a part of a string starting from startIndex and ending after some count of chars. in some cases I just need to search the first 5 chars for a special char or string why will I have to come over the whole string it may be 1000 chars or multiples of that. what I know in c++ run time library, all functions don't support something like that for example strchr it will search all of the string, I don't want that I want to compare a specific part of the string from [] to []. I've seen a solution for that problem using wmemchr but I need it to be dependent on the currently selected locale, if anybody know how to do that, I'd be grateful.
Also how to compare just 2 chars directly regarding to the locale?
I'm not aware of a way to do this directly with a standard library, but you could make your own function and strstr pretty easily.
/* Find str1 within str2, limiting str2 to n characters. */
char * strnstr( char * str1, const char * str2, size_t n )
{
char * ret;
char temp = str1[n]; // save our char at n
str2[n] = NULL; // null terminate str2 at n
ret = strstr( str1, str2 ); // call into strstr normally
str2[n] = temp; // restore char so str2 is unmodified
return ret;
}
For your second question:
Also how to compare just 2 chars directly regarding to the locale?
I'm not sure what you mean. Are you asking how to compare two characters directly? If so, you can just compare like any other values.
if( str1[n] == str2[n] ) { ...do something... }
You can use std::substr to limit your search area:
std::string str = load_some_data();
size_t pos = str.substr(5).find('a');
I solved it like that
int64 Compare(CHAR c1, CHAR c2, bool ignoreCase = false)
{
return ignoreCase ? _strnicoll(&c1, &c2, 1) : _strncoll(&c1, &c2, 1);
}
int64 IndexOf(const CHAR* buffer, CHAR c, uint count, bool ignoreCase = false)
{
for (uint i =0; i < count; i++)
{
if (Compare(*(buffer + i), c, ignoreCase) == 0)
{
return i;
}
}
return npos;
}
int64 LastIndexOf(const CHAR* buffer, CHAR c, uint count, bool ignoreCase = false)
{
while(--count >= 0)
{
if (Compare(*(buffer + count), c, ignoreCase) == 0)
{
return count;
}
}
return npos;
}
npos = -1
and to specify the start index pass to (buffer + startIndex) as the buffer to the second or the third method

making a new char* out of two old char*s

I am open to using intermediary C++ code, though C code is the preference.
I have code like the following:
char *fileName1 = "graph";
char *extension1 = ".eps";
I want to create a new char* variable called fileName1WithExtension1 which would correspond to "graph.eps", formed from the two char* variables given above. How can this be done?
If you use C++, have those as std::string strings:
std::string fileName1 = "graph";
std::string extension1 = ".eps";
And then simply
std::string fileName1WithExtension1 = filename1 + extension1;
If you then need to pass that to a C library function expecting a C string, get char pointer with fileName1WithExtension1.c_str()
There really is no reason to muck about with plain C strings in C++ code. It is so error-prone and tedious, that it should be actively avoided.
char *new_string;
new_string = malloc(strlen(fileName1) + strlen(extension1) + 1);
sprintf(new_string, "%s%s", fileName1, extension1);
...
free(new_string)
You can use the asprintf() function
char *buffer;
asprintf (&buffer, "%s%s", fileName1, extension1);
When the buffer variable become useless in your code, you have to free the memory allocated for buffer by asprintf with
free(buffer);
char *joined;
joined = (char*)malloc(strlen(fileName1) + strlen(extension1) + 1);
strcpy(joined, fileName1)
strcat(joined, extension1)
For a small performance increase, if the compiler is smart enough at optimizing, change the last line to
strcpy(joined+strlen(fileName1), extension1)
Even better, store the length of fileName1 in a variable the first time you determine it, and use it in the final strcpy().
If you want to go REALLY low-level, with ugly loops and such, you can do this: (Tested, it compiles and gives the expected and desired results)
char* filename1 = "graph";
char* extension1 = ".eps";
char* filename1WithExtension1 = combine(filename1, extension1);
where:
char* combine(char* str1, char* str2)
{
int str1len = 0, str2len = 0;
while(str1[str1len] != '\0') {
str1len++;
}
while(str2[str2len] != '\0') {
str2len++;
}
int outputlen = str1len + str2len + 1;
char* output = new char[outputlen];
for(int i = 0; i < str1len; i++)
{
output[i] = str1[i];
}
for(int i = str1len; i < outputlen; i++)
{
output[i] = str2[i - str1len];
}
return output;
}
I did a bit of C brush-up for fun, here's an alternative (C90 and C++ compatible code) for joining an array of C strings with separator. It should be very efficient with any decently optimizing compiler, too:
#include <string.h>
#include <stdlib.h>
/* **parts are strings to join, a NULL-terminated array of char*
* sep is separator string, use "" for no separator, must not be NULL
* returns malloc-allocated buffer which must be freed
* if len_out!=NULL, sets *len_out to strlen of result string */
char *astrjoin(int *len_out, const char *sep, char **parts) {
int part_count;
int parts_total_len = 0;
for(part_count = 0; parts[part_count]; ++part_count) {
parts_total_len += strlen(parts[part_count]);
}
if (part_count > 0) {
int malloc_size = (part_count - 1) * strlen(sep) + parts_total_len + 1;
char *result = (char*)malloc(malloc_size);
char *dest = result;
for(;;) {
const char *src;
for(src=*parts; *src; ++src) *dest++ = *src;
if (!*++parts) break;
for(src=sep ; *src; ++src) *dest++ = *src;
}
*dest = 0;
if (len_out) *len_out = malloc_size - 1;
return result;
} else {
if (len_out) *len_out = 0;
return strdup("");
}
}
Example usage:
int main(int argc, char *argv[]) {
/* argv is NULL-terminated array of char pointers */
char *commandline = astrjoin(NULL, " ", argv);
printf("argc: %d\nargv: %s\n", argc, commandline);
free(commandline);
return 0;
}
To call that in context of your question, it could be something like:
char *tmparr[] = { fileName1, exteansion1, NULL };
char *fileName1WithExtension1 = astrjoin(NULL, "", tmparr);
It would be trivial to create a version with sep and/or len_out dropped, or a version supporting "varargs", with signature looking something like:
char *astrjoin_va(int *len_out, const char *sep, ...);
Which would be nicer to call in context of your question:
char *fileName1WithExtension1 = astrjoin_va(NULL, "", fileName1, extension1, NULL);