본문 바로가기
프로그래밍/C# (WinForms)

C#, WinForms ] float to hex / hex to float Converter

by eteo 2023. 4. 9.

 

 

엔디안을 선택하면 시스템 아키텍쳐에 따라 메모리에 저장된 대로 보여주고, Hex값은 0x 접두사를 붙이거나 혹은 공백 구분자를 두거나 선택할 수 있게했다.

 

 

 

 

 

디자이너 부분을 먼저 살펴보면 Form은 사용자가 크기를 변경할 수 없도록 FormBorderStyle을 FixedSingle로 하고 Form에 있는 Font들이 다 상속받을 수 있도록 기본 Font를 설정한다.

 

라디오버튼과 변환 부분은 panel을 사용해 구분 짓고, 변환 후 결과를 보여주는 textBox는 사용자가 copy만 할 수 있게 ReadOnly 속성을 true로 하였다.

 

this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
// ...
this.textBox1_2.ReadOnly = true;

 

 

 

 

 

 

 

 

 

float to hex 변환

 

public Form1()
{
    InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
    textBox1_1.Focus();
}

private void button1_Click(object sender, EventArgs e)
{
    if(this.textBox1_1.Text != "")
    {
        float floatValue;
        if (float.TryParse(this.textBox1_1.Text, out floatValue))
        {
            this.textBox1_1.Text = floatValue.ToString();
            byte[] floatBytes = BitConverter.GetBytes(floatValue);
            if(this.radioButton_Little.Checked)
            {
                Array.Reverse(floatBytes);
            }
            uint hexValue = BitConverter.ToUInt32(floatBytes, 0);
            string hexString = hexValue.ToString("X8");
            if(this.radioButton_0x.Checked)
            {
                this.textBox1_2.Text = "0x" + hexString.ToUpper();
            }
            else
            {
                string[] tokens = Enumerable.Range(0, hexString.Length / 2).Select(x => hexString.Substring(x * 2, 2)).ToArray();
                this.textBox1_2.Text = string.Join(" ", tokens);
            }
        }
        else
        {
            this.textBox1_2.Text = "ERROR";
        }
    }
}

 

 

1. 먼저 textBox에 입력된 string을 float 타입으로 변환한다.

float -> string 으로 변환하는 것은 float.Parse(), float.TryParse(), Conver.ToSingle() 메서드를 사용할 수 있는데 float.TryParse의 경우 문자열이 float 형태로 변환될 수 없는 경우 예외처리를 따로 할 필요가 없기 안전하다.

 

2. BitConverter.GetBytes() 메서드를 사용해 float 값을 바이트 배열로 변환한다. BitConverter 클래스는 다양한 데이터 타입을 바이트 배열로 반환하거나, 바이트 배열을 다양한 데이터 타입으로 변환하는 기능을 제공한다.

 

3. 라디오 버튼 체크상태를 확인해 바이트 배열을 Array.Reverse() 메서드를 통해 역순으로 재배치할 지 결정한다.

 

4. 변환된 바이트 배열을 BitConverter.ToUInt32() 함수를 사용해 UInt32 형태로 변환한다. 두번째 인자는 바이트 배열의 startIndex이다.

 

5. .ToString("X8") 메서드를 통해 UInt32 객체를 8자리의 16진수 문자열로 변환한다.

 

6. 라디오 버튼 체크 상태에 따라 변환한 문자열에 "0x" 접두사를 붙일지, 공백으로 구분된 형태로 출력할지 결정한다.

문자열을 공백으로 구분하거나, 공백으로 구분된 문자열을 붙이는 건 LINQ 문법을 사용했다.

 

 

 

 

 

 

 

hex to float 변환

 

private void button2_Click(object sender, EventArgs e)
{
    if (this.textBox2_1.Text != "")
    {
        string hexString = this.textBox2_1.Text;
        hexString = hexString.Replace("0x", "");
        hexString = hexString.Replace(" ", "");

        if (Regex.IsMatch(hexString, "^[0-9a-fA-F]{1,8}$"))
        {
            if(hexString.Length < 8)
            {
                hexString = hexString.PadLeft(8, '0');
            }
        
            byte[] floatBytes = Enumerable.Range(0, hexString.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(hexString.Substring(x, 2), 16)).ToArray();
            if (this.radioButton_Big.Checked)
            {
                Array.Reverse(floatBytes);
            }
            float floatValue = BitConverter.ToSingle(floatBytes, 0);
            this.textBox2_2.Text = floatValue.ToString();
        }
        else
        {
            this.textBox2_2.Text = "ERROR";
        }

    }
}

 

 

1. textBox에 입력된 문자열에 "0x"가 있거나 " " 공백이 있는 경우 이를 제거한다.

 

2. 정규표현식을 사용해 문자열을 처리하기 위해 상단에 using System.Text.RegularExpressions; 를 추가한다.

 

3. Regex.IsMatch(hexString, "^[0-9a-fA-F]{1,8}$"); 해당 문자열이 16진수 형식으로 표현된 값이며 8자리 이하인지를 검사한다.

  • ^ : 문자열의 시작을 의미한다.
  • [ ] : 문자열이 [ ] 안의 문자와 매치하는지 검사한다. [^ ] 괄호 안에 ^가 있으면 그 외 문자와 매치한다.
  • { } : {m} 은 m번 반복, {m, n} 은 m번에서 n번 사이로 반복, {m,} 은 m번 이상 반복, {,n}은 n번 이하로 반복되는 걸 의미한다.
  • $ : 문자열의 끝을 의미한다.

4. 문자열이 8자 미만이면 string 클래스의 PadLeft() 메서드를 사용하여, 왼쪽을 '0'으로 패딩한다.

 

5. 문자열을 LINQ의 Enumerable 클래스를 사용해 바이트 배열로 변환한다. 예를들어 "12345678"을 {0x12, 0x34, 0x56, 0x78} 로 변환한다.

 

6. 라디오 버튼 체크상태를 확인해 바이트 배열을 Array.Reverse() 메서드를 통해 역순으로 재배치할 지 결정한다.

 

7. 바이트 배열을 float 형태로 변환 한뒤 다시 string 타입으로 변환해 textBox에 출력한다.

 

 

 

 

 

 

 

아래는 위에서 문자열을 조작해 문자열 배열 또는 byte 배열로 변환하는 데 LINQ문법을 사용한 것이다.

2023.04.09 - [프로그래밍/C# (WinForms)] - C#, LINQ ] Enumerable 클래스, Range(), Select(), Where(), ToArray() 메서드

 

 

string[] tokens = Enumerable.Range(0, hexString.Length / 2).Select(x => hexString.Substring(x * 2, 2)).ToArray();
this.textBox1_2.Text = string.Join(" ", tokens);

 

1. 먼저 0부터 hexString.Length / 2 까지의 숫자 시퀀스를 생성한다. hexString.Length가 8이라면 [0, 1, 2, 3] 시퀀스가 생성된다.

2. Select() 메서드로 시퀀스의 각 요소를 x로 받아서 hexString 문자열에서 x * 2 인덱스부터 길이가 2인 문자열을 추출한 시퀀스를 반환한다.

3. ToArray() 메서드로 해당 시퀀스를 문자열 배열로 변환한 뒤 string.Join()을 사용해 배열의 모든 요소를 " " 공백 문자 구분자로 연결해서 하나의 문자열로 결합한다.

 

 

 

 

 

 

 

byte[] floatBytes = Enumerable.Range(0, hexString.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(hexString.Substring(x, 2), 16)).ToArray();
float floatValue = BitConverter.ToSingle(floatBytes, 0);

 

1. 먼저 0부터 hexString.Length 까지의 숫자 시퀀스를 생성한다.

2. Where() 로 짝수 번째만 필터링한 시퀀스를 반환한다. hexString.Length가 8이라면 [0, 2, 4, 6] 으로 이루어진 새 시퀀스가 생성된다.

3. Convert.ToByte()는 문자열을 바이트 값으로 변환하는 메소드이고 첫번째 인자가 문자열, 두번째 인자가 진법 값이다. 예를 들어 Convert.ToByte("12", 16) 하면 0x12인 바이트값이 반환되어 결과는 18이고, Convert.ToByte("12", 10)하면 결과는 12가된다.

4. Select() 메서드로 문자열 x 인덱스부터 길이가 2인 문자열을 추출하고 이를 16진법으로 생각해 바이트로 변환한 시퀀스를 반환하게 된다.

5. ToArray() 메서드로 시퀀스를 배열로 변한한뒤 BitConverter.ToSingle()로 다시 float 값으로 변환한다.