I have a wide char variable which I want to initialize with a size of string.
I tried following but didn't worked.
std::string s = "aaaaaaaaaaaaaaaaaaaaa"; //this could be any length
const int Strl = s.length();
wchar_t wStr[Strl ]; // This throws error message as constant expression expected.
what option do i have to achieve this? will malloc work in this case?
Since this is C++, use new instead of malloc.
It doesn't work because C++ doesn't support VLA's. (variable-length arrays)
The size of the array must be a compile-time constant.
wchar_t* wStr = new wchar_t[Strl];
//free the memory
delete[] wStr;
First of all, you can't just copy a string to a wide character array - everything is going to go berserk on you.
A std::string is built with char, a std::wstring is built with wchar_t. Copying a string to a wchar_t[] is not going to work - you'll get gibberish back. Read up on UTF8 and UTF16 for more info.
That said, as Luchian says, VLAs can't be done in C++ and his heap allocation will do the trick.
However, I must ask why are you doing this? If you're using std::string you shouldn't (almost) ever need to use a character array. I assume you're trying to pass the string to a function that takes a character array/pointer as a parameter - do you know about the .c_str() function of a string that will return a pointer to the contents?
std::wstring ws;
ws.resize(s.length());
this will give you a wchar_t container that will serve the purpose , and be conceptually a variable length container. And try to stay away from C style arrays in C++ as much as possible, the standard containers fit the bill in every circumstance, including interfacing with C api libraries. If you need to convert your string from char to wchar_t , c++11 introduced some string conversion functions to convert from wchar_t to char, but Im not sure if they work the other way around.
Related
I am now using C++ to program a robot using PROS. Pros has a print function, which is taking in a const char*. Now, I'm using lvgl to create my own screen, and I want to replicate the print function. Like the printf() functions, I want it to include variadic params to do the %d effect (so it converts all the %? to the corresponding values). The problem now is about the conversions between functions. I wanted to make a convert function to convert a string and the variadic params into a complete string. I need to input is a string which is like "hey" and I'm unsure what the type name should be. I need to be able to get size, search in it for %ds but I need the function to return a const char* to pass onto the lvgl to pring on the screen. I am having a bad time trying to convert a string into an const char* for the out put of the convert function.
Also, I tried using the input type as a char*, and when I input a string like "hello" is says a error [ISO C++11 does not allow conversion from string literal to 'char ' [-Wwritable-strings]]. But instead, when is use a const char, the error disappears. Anyone knows why?
Thanks everyone for your kind help!
char* and const char* are two flavours of the same thing: C-style strings. These are a series of bytes with a NUL terminator (0-byte). To use these you need to use the C library functions like strdup, strlen and so on. These must be used very carefully as missing out on the terminator, which is all too easy to do by accident, can result in huge problems in the form of buffer-overflow bugs.
std::string is how strings are represented in C++. They're a lot more capable, they can support "wide" characters, or variable length character sets like UTF-8. As there's no NUL terminator in these, they can't be overflowed and are really quite safe to use. Memory allocation is handled by the Standard Library without you having to pay much attention to it.
You can convert back and forth as necessary, but it's usually best to stick to std::string inside of C++ as much as you can.
To convert from C++ to C:
std::string cppstring("test");
const char* c_string = cppstring.c_str();
To convert from C to C++:
const char* c_string = "test";
std::string cppstring(c_string);
Note you can convert from char* (mutable) to const char* (immutable) but not in reverse. Sometimes things are flagged const because you're not allowed to change them, or that changing them would cause huge problems.
You don't really have to "convert" though, you just use char* as you would const char*.
std::string A = "hello"; //< assignment from char* to string
const char* const B = A.c_str(); //< call c_str() method to access the C string
std::string C = B; //< assignment works just fine (with allocation though!)
printf("%s", C.c_str()); //< pass to printf via %s & c_str() method
I have char array as follows:
TCHAR name[256] = L"abc";
Also I have another wstring vector as follows,
std::vector<std::wstring> nameList;
nameList.push_back(L"cde");
nameList.push_back(L"fgh");
I want to assign nameList vector first element to name array,
Can any one help for that me?
You can use std::copy; name is an array with a bound, but it's usage as a function argument decays to a pointer to it's first element, which satisfies the requirements for an output iterator.
So you can:
wchar_t name[256] = L"abc";
std::vector<std::wstring> nameList;
nameList.push_back(L"cde");
nameList.push_back(L"fgh");
std::copy(nameList.front().begin(), nameList.front().end(), name);
Note that: this will not add any trailing \0 terminator to the buffer; If you wanted to replace/overwrite name, you should as well just use std::wstring and save yourself some hassles
Given your question and the assumption that you must use an array instead of a wstring, your best bet may be to use either std::copy or even an old fashioned memcpy. However these are dangerous for the following two reasons:
If TCHAR is not actually a wchar_t there are likely be to memory errors.
If nameList contains a string that is longer than 255 TCHAR characters you will have a buffer overflow.
That said, you can do this safely with the following:
if (nameList[0].size() >= 256) {
throw std::length_error("string too long");
}
std::copy(nameList[0].begin(), nameList[0].end(), name);
name[nameList[0].size()] = TCHAR(0);
You could also add a static_assert to force a compiler error if TCHAR is not a wchar_t, but it probably isn't necessary as the copy would perform any implicit conversion on a character by character basis.
[I'm new to D (currently writing my first useful program) and I don't have much C background - just some C# and other mostly pointerless languages.]
Do I need to always append '\0' to the wstring before casting? Is that the only way to ensure that my wchar* will be null-terminated? When it is cast, is it a new copy of the wstring, or does it just get a pointer to the same wstring you're casting?
For calling Windows *W functions use http://www.digitalmars.com/d/2.0/phobos/std_utf.html#toUTF16z
Also note that string literals already are 0-terminated so you can pass them directly.
The toStringz functions convert D strings to C-style zero-terminated strings.
immutable(char)* toStringz(const(char)[] s);
immutable(char)* toStringz(string s);
e.g.
string s;
immutable(char)* cstr = s.toStringz();
//or: toStringz(s);
toStringz allocates a new string on the heap only if the string isn't already null terminated, otherwise it just returns s.ptr.
If you merely want a pointer, the correct way is to use the 'ptr' property (available for all dynamic arrays, not just strings)
str.ptr
However, if you are wanting something to use with C, to ensure it is nul-terminated, use toStringz
import std.string;
toStringz(str);
toStringz will not perform a copy if the string is already nul terminated.
How do I append a string to a char?
strcat(TotalRam,str);
is what i got but it does not support strings
std::String has a function called c_str(), that gives you a constant pointer to the internal c string, you can use that with c functions. (but make a copy first)
Use + on strings:
std::string newstring = std::string(TotalRam) + str;
If you want it as a char[] instead, you need to allocated memory on the heap or stack first. After that, strcat or sprintf are possible options.
You can't append a string to a char, you can only append a string to a string (or a char* if using the C string functions). In your example, you'll have to copy (the char) TotalRam into a string of some sort, either a C++ std::string, or make a char[2] to hold it and the required terminating NULL character. Then you can either use the C++ string with C++ functions or the char[2] with strcat and friends.
for performance, do this:
char ministring[2] = {0,0};
// use ministring[0] as your char, fill it in however you like
strcat(ministring,str);
The char array is stack-allocated so it is extremely fast, and the second char with the value of zero acts as a string terminator so that functions like strcat will treat it as a 'c' string.
I'm trying to make changes to some legacy code. I need to fill a char[] ext with a file extension gotten using filename.Right(3). Problem is that I don't know how to convert from a CStringT to a char[].
There has to be a really easy solution that I'm just not realizing...
TIA.
If you have access to ATL, which I imagine you do if you're using CString, then you can look into the ATL conversion classes like CT2CA.
CString fileExt = _T ("txt");
CT2CA fileExtA (fileExt);
If a conversion needs to be performed (as when compiling for Unicode), then CT2CA allocates some internal memory and performs the conversion, destroying the memory in its destructor. If compiling for ANSI, no conversion needs to be performed, so it just hangs on to a pointer to the original string. It also provides an implicit conversion to const char * so you can use it like any C-style string.
This makes conversions really easy, with the caveat that if you need to hang on to the string after the CT2CA goes out of scope, then you need to copy the string into a buffer under your control (not just store a pointer to it). Otherwise, the CT2CA cleans up the converted buffer and you have a dangling reference.
Well you can always do this even in unicode
char str[4];
strcpy( str, CStringA( cString.Right( 3 ) ).GetString() );
If you know you AREN'T using unicode then you could just do
char str[4];
strcpy( str, cString.Right( 3 ).GetString() );
All the original code block does is transfer the last 3 characters into a non unicode string (CStringA, CStringW is definitely unicode and CStringT depends on whether the UNICODE define is set) and then gets the string as a simple char string.
First use CStringA to make sure you're getting char and not wchar_t. Then just cast it to (const char *) to get a pointer to the string, and use strcpy or something similar to copy to your destination.
If you're completely sure that you'll always be copying 3 characters, you could just do it the simple way.
ext[0] = filename[filename.Length()-3];
ext[1] = filename[filename.Length()-2];
ext[2] = filename[filename.Length()-1];
ext[3] = 0;
I believe this is what you are looking for:
CString theString( "This is a test" );
char* mychar = new char[theString.GetLength()+1];
_tcscpy(mychar, theString);
If I remember my old school MS C++.
You do not specify where is the CStringT type from. It could be anything, including your own implementation of string handling class. Assuming it is CStringT from MFC/ATL library available in Visual C++, you have a few options:
It's not been said if you compile with or without Unicode, so presenting using TCHAR not char:
CStringT
<
TCHAR,
StrTraitMFC
<
TCHAR,
ChTraitsCRT<TCHAR>
>
> file(TEXT("test.txt"));
TCHAR* file1 = new TCHAR[file.GetLength() + 1];
_tcscpy(file1, file);
If you use CStringT specialised for ANSI string, then
std::string file1(CStringA(file));
char const* pfile = file1.c_str(); // to copy to char[] buffer