Sampaio
Sampaio

Reputation: 367

char to system.string in windowsforms

I wrote a program to write numbers in different bases (base 10, binary, base 53, whatever...)

I inicially wrote it as a win32 console application, in visual c++ 2010, and then converted it to a Windows Form Application (I know, I know...)

In the original form, it worked perfectly, but after the conversion, it stopped working. I narrowed down the problem to this:

The program uses a function that receives a digit and returns a char:

char corresponding_digit(int digit)
{
    char corr_digit[62] = {'0','1','2','3','4','5','6','7','8','9',
                           'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P' ,'Q','R','S' ,'T','U','V','W','X','Y','Z',
                           'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p' , 'q','r','s' ,'t','u','v','w','x','y','z'};
    return corr_digit[digit];
}

This function takes numbers from 1 to 61, and return the corresponding character: 0-9 -> 0-9; 10-35 -> A-Z; 36-61 a->z.

The program uses the function like this:

//on a button click
//base is an integer got from the user
String^ number_base_n = "";
if(base == 10)
    number_base_n = value.ToString();
else if(base==0)
    number_base_n = "0";
else
{
    int digit, power, copy_value;
    bool number_started = false;
    copy_value = value;
    if(copy_value > (int)pow(float(base), MAX_DIGITS)) //cmath was included
        number_base_n = "Number too big";
    else
    {
        for(int i = MAX_DIGITS; i >= 0; i--)
        {
            power = (int)pow(float(base), i);
            if(copy_value >= power)
            {
                digit = copy_value/power;
                copy_value -= digit*power;
                number_started = true;
                number_base_n += corresponding_digit(digit);
            }
            else if (number_started || i==0)
            {
                number_base_n += "0";
            }
        }
     }
}       
textBox6->Text = number_base_n;

After debugging a bit, I realized the problem happens when function corresponding_digit is called with digit value "1", which should return '1', in the expression

//number base_n equals ""
number_base_n += String(corresponding_digit(digit));
//number_base_n equals "49"

number_base_n, starting at "", ends with "49", which is actually the ASCII value of 1. I looked online, and all I got was converting the result, with String(value) or value.ToString(), but apparently I can't do

number_base_n += corresponding_digit(digit).ToString();

I tried using an auxiliar variable:

aux = corresponding_digit(digit);
number_base_n += aux.ToString();

but I got the exact same (wrong) result... (Same thing with String(value) )

I fumbled around a bit more, but not anything worth mentioning, I believe. So... any help?

Also: base 10 and base 0 are working perfectly

Edit: If the downvoter would care to comment and explain why he downvoted... Constructive criticism, I believe is the term.

Upvotes: 0

Views: 1461

Answers (1)

David Yaw
David Yaw

Reputation: 27864

In C++/CLI, char is the same thing as it is in C++: a single byte, representing a single character. In C#, char (or System.Char) is a two byte Unicode codepoint. The C++ and C++/CLI equivalent to C#'s char is wchar_t. C++'s char is equivalent to System::Byte in C#.

As you have it now, attempting to do things with managed strings results in the managed APIs treating your C++ char as a C# byte, which is a number, not a character. That's why you're getting the ASCII value of the character, because it's being treated as a number, not a character.

To be explicit about things, I'd recommend you switch the return type of your corresponding_digit method to be System::Char. This way, when you operate with managed strings, the managed APIs will know that the data in question are characters, and you'll get your expected results.

System::Char corresponding_digit(int digit)
{
    System::Char corr_digit[62] = {'0','1','2','3','4','5','6','7','8','9',
                           'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
                           'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    return corr_digit[digit];
}

Other possible changes you could make:

  • Use a StringBuilder instead of appending strings.
  • Switch corr_digit to a managed array (array<System::Char>^), and store it somewhere reusable. As the code is written now, the corresponding_digit method has to re-create this array from scratch every time the method is called.

Upvotes: 1

Related Questions