Jump to content
357mag

How do I convert from string to char?

Recommended Posts

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 by 357mag

Share this post


Link to post

It clearly tells you that a string is an array of characters.

That should give you some ideas?

Share this post


Link to post

 

 

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
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
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 by Remy Lebeau

Share this post


Link to post
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 by Remy Lebeau

Share this post


Link to post

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

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 by 357mag

Share this post


Link to post

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

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

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

Your have defined 

AnsiString myString

But then not used it.....

 

myString = AnsiString(EditCharacterEntry -> Text);


 

Share this post


Link to post

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
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 by Remy Lebeau

Share this post


Link to post

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
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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×