357mag 2 Posted April 12, 2023 (edited) My program prompts the user to enter a character (like 'A' for example). Then I'm trying to store it in a character variable. But C++ is telling me it can't cast from Unicode string to a character. How do I handle it? My code looks like this: char ch = 0; int chValue = 0; LabelPrompt -> Caption = "Enter a character: "; ch = static_cast<char>(EditCharacterEntry -> Text); The goal of this program is to print the Ascii code for the letter the user entered. Then it would show something like 'w' is 119. 'x' is 120. Edited April 12, 2023 by 357mag Share this post Link to post
Lars Fosdal 1793 Posted April 13, 2023 https://docwiki.embarcadero.com/Libraries/Alexandria/en/System.UnicodeString Share this post Link to post
357mag 2 Posted April 13, 2023 That article doesn't help a beginner hobbyist. Share this post Link to post
Lars Fosdal 1793 Posted April 13, 2023 It clearly tells you that a string is an array of characters. That should give you some ideas? Share this post Link to post
Roger Cigol 107 Posted April 13, 2023 The EditCharacterEntry->Text is a Unicode string (remember it would be possible for someone to enter several characters (including characters that can't be represented as C++ char type). So the first thing you need to do is to convert this to an 8 bit char string. Any easy way to do this is to construct and AnsiString from the Unicode String. So you use AnsiString(EditCharacterEntry->Text). This will lose (ie corrupt) characters that are Unicode and can't be represented in Ansi. Next you need to get the first character of the AnsiString. In a VCL framework application the first character has an index of 1. So you use char ch = AnsiString(EditCharacterEntry->Text)[1]; Share this post Link to post
Lajos Juhász 295 Posted April 13, 2023 5 hours ago, Roger Cigol said: har ch = AnsiString(EditCharacterEntry->Text)[1] I don't know how will the C++ handle the case when the Text property is empty string. Share this post Link to post
Remy Lebeau 1436 Posted April 13, 2023 (edited) 19 hours ago, 357mag said: C++ is telling me it can't cast from Unicode string to a character. How do I handle it? Like any other string type, UnicodeString is an array of characters. You can index into individual characters, eg: // UnicodeString is 1-based, not 0-based! System::Char ch = EditCharacterEntry->Text[1]; int chValue = static_cast<int>(ch); Note that UnicodeString is a UTF-16 encoded string, where System::Char is a UTF-16 codeunit. It is wchar_t on Windows and char16_t on other platforms. If you need the 8-bit 'char' type specifically, you will have to perform a Unicode->ANSI data conversion at runtime, eg: // AnsiString is also 1-based! char ch = AnsiString(EditCharacterEntry->Text)[1]; int chValue = static_cast<int>(ch); Note that such a conversion is potentially lossy for non-ASCII characters > 127. AnsiString uses the caller's default codepage, so you will lose data if the UnicodeString holds Unicode characters that are not present in that codepage. You can use AnsiStringT<T> instead if you need to specify a specific codepage, eg: // AnsiStringT is also 1-based! // 28591 = ISO-8859-1, see https://learn.microsoft.com/en-us/windows/win32/intl/code-page-identifiers char ch = AnsiStringT<28591>(EditCharacterEntry->Text)[1]; int chValue = static_cast<int>(ch); Note that UTF8String is an alias for AnsiStringT<65001>. Edited April 13, 2023 by Remy Lebeau Share this post Link to post
Remy Lebeau 1436 Posted April 13, 2023 (edited) 1 hour ago, Lajos Juhász said: I don't know how will the C++ handle the case when the Text property is empty string. Using UnicodeString::operator[] to index outside of the bounds of the string (< 1, or > Length()) will throw an ERangeError exception. Edited April 13, 2023 by Remy Lebeau Share this post Link to post
Roger Cigol 107 Posted April 13, 2023 Remy is (of course) correct. My example was to show you one possible solution. You would be wise to check for the String being empty before doing the conversion. String type has a function IsEmpty() to do just that. Share this post Link to post
357mag 2 Posted April 13, 2023 (edited) Don't know what's wrong because I'm getting garbage values in my LabelAnswer. I even get a graphic of a tiny square in the output. I want the output to be like this: A is 65 B is 66 Here is my code: int chValue = 0; AnsiString myString; Char ch = EditCharacterEntry -> Text[1]; chValue = static_cast<int>(ch); LabelAnswer -> Caption = ch + " is " + chValue; Sometimes the output will be correct, like if I enter 'A' it will say 'A' is 65. But other times it just says "is 32". Edited April 14, 2023 by 357mag Share this post Link to post
357mag 2 Posted April 14, 2023 I noticed that if I hit the Clear button, that is when the output is wrong. If I don't hit the Clear button, then the output is correct: A is 65 B is 66 C is 67 Share this post Link to post
357mag 2 Posted April 14, 2023 Well it appears to be working now. All I did to the Clear button was this: void __fastcall TFormCharacterValues::ButtonClearClick(TObject *Sender) { EditCharacterEntry -> Text = " "; LabelAnswer -> Caption = " "; EditCharacterEntry -> SetFocus(); } Share this post Link to post
357mag 2 Posted April 14, 2023 I mean my Clear button looks like this: EditCharacterEntry -> Text = " "; EditCharacterEntry -> SetFocus(); Don't know how that "is 32" thing got in there before. Share this post Link to post
Roger Cigol 107 Posted April 14, 2023 Your have defined AnsiString myString But then not used it..... myString = AnsiString(EditCharacterEntry -> Text); Share this post Link to post
Roger Cigol 107 Posted April 14, 2023 Hmm - last bit of my previous post doesn't seem to have been displayed / submitted correctly. I also included a line of code: char ch = myString[1]; // rem: this is an example of use and does not include a check for an empty string Share this post Link to post
Remy Lebeau 1436 Posted April 14, 2023 (edited) 19 hours ago, 357mag said: Don't know what's wrong because I'm getting garbage values in my LabelAnswer. The expression: ch + " is " + chValue Does not do what you think it does. It does not perform string concatenation, it actually performs pointer arithmetic instead. The string literal " is " is a 'const char[5]' array, which in this context will decay into a 'const char*' pointer to its 1st character. You are adding a 'char' and an 'int' (both integer types) to that pointer, moving around where it points in memory. So, for example, if 'A' is entered, then you are advancing the pointer forward in memory by 65+65=130 characters. And then, you are assigning that final pointer to the Label->Caption, which is why you end up with garbage output. If you are going to append integer values to strings, make sure you append them to String objects, not to char* pointers. AnsiString and UnicodeString have overloaded constructors for converting various data types, including integers, eg: Char ch = EditCharacterEntry->Text[1]; int chValue = static_cast<int>(ch); LabelAnswer->Caption = ch + String(" is ") + chValue; Alternatively, you can convert the integers to String object before concatenating them, eg: Char ch = EditCharacterEntry->Text[1]; int chValue = static_cast<int>(ch); LabelAnswer->Caption = String(ch) + " is " + String(chValue); // or IntToStr(chValue) Alternatively, use a function that to designed for formatting strings from different types of inputs, such as Sysutils::Format() or String::sprintf(), eg: Char ch = EditCharacterEntry->Text[1]; int chValue = static_cast<int>(ch); LabelAnswer->Caption = Format("%s is %d", ARRAYOFCONST((ch, chValue))); or LabelAnswer->Caption = String().sprintf(_D("%c is %d"), ch, chValue); Edited April 14, 2023 by Remy Lebeau Share this post Link to post
357mag 2 Posted April 29, 2023 Your first code example does not work. C++ Builder wrote an extremely long line complaining about something. It also said chValue is assigned a value that is never used. Your second code example worked though. Share this post Link to post
Remy Lebeau 1436 Posted April 29, 2023 21 minutes ago, 357mag said: Your first code example does not work. C++ Builder wrote an extremely long line complaining about something. Then you are going to have to show the actual error message, and the code it refers to. Every code I've shown here is correct and should be working fine. 21 minutes ago, 357mag said: It also said chValue is assigned a value that is never used. None of my examples have unused values. On the other hand, some of your examples do. Share this post Link to post