c# decimal to hex & hex to decimal / hex to ascii in LINQ - c#

I'm trying to do some conversion and would like to use Linq to achieve the following,
Decimal to Hex,
Decimal to Ascii,
Hex to Decimal,
Hex to Ascii
Can someone please show me how to do this efficently in Linq?
I'll be displaying the output into textboxes.
Also, I have a prefix and delimiter field that will also need to be included,
Example:
string input = txtAscii.Text;
string delim = txtDelimiter.Text;
string prefix = txtPrefix.Text;
if (checkBox1.Checked == true && string.IsNullOrEmpty(delim)) delim = " ";
//Linq, Ascii to Decimal.
txtDecimal.Text = string.Join(delim, input.Select(c => prefix + ((int)c).ToString()));
Thanks all.

LINQ is for querying collections, not converting values. It is wrong to say you want to use LINQ to convert X to Y.
That said, here's the building blocks you need:
// string in decimal form to int
Int32.Parse("12345");
// string in hexadecimal form to int
Int32.Parse("ABCDE", NumberStyles.HexNumber);
// int to string in decimal form
12345.ToString();
// int to string in hexadecimal form
12345.ToString("x");
Then to do something like converting between decimal form to hexadecimal form:
var inDecimal = "12345";
var asInt = Int32.Parse(inDecimal);
var asHex = asInt.ToString("x");
Your "ASCII to (hexa)decimal" conversions could be done with a little bit of LINQ using the above building blocks. Assuming you mean the (hexa)decimal representation of each character's ASCII code:
var str = "FOOBAR!";
var asAsciiInt = String.Join(" ", str.Select(c => (int)c));
var asAsciiHex = String.Join(" ", str.Select(c => ((int)c).ToString("x2")));
// asAsciiInt == "70 79 79 66 65 82 33"
// asAsciiHex == "46 4f 4f 42 41 52 21"
var asciiInt = "70 79 79 66 65 82 33";
var charStrs = asciiInt.Split();
var asStr = String.Concat(charStrs.Select(cs => (char)Int32.Parse(cs)));
// asStr == "FOOBAR!"
var asciiHex = "46 4f 4f 42 41 52 21";
var charStrs = asciiHex.Split();
var asStr = String.Concat(charStrs.Select(cs => (char)Int32.Parse(cs, NumberStyles.HexNumber)));
// asStr == "FOOBAR!"

To convert numeric value to hex is dead easy.
Decimal d = 10M;
d.ToString("X")
I am however utterly confused by what you mean "decimal to ascii"

I don't really understand why you'd need to use LINQ here, but you can do the conversion between decimal and hex like this:
decimal dec1 = 182;
//convert decimal as a hex in a string variable
string hex = dec.ToString("X");
//convert the hex string back to the decimal
decimal dec2 = decimal.Parse(hex, System.Globalization.NumberStyles.HexNumber);

Related

Declaring a string from a character has an unexpected result. Why is this so?

Half a day looking for this bug. Why is there an unexpected result in the third case?
// case 1
string value1 = "a" + "a" + "A";
byte[] asciiBytes1 = Encoding.ASCII.GetBytes(value1); // expected: 97 - 97 - 65
Console.WriteLine(string.Join(" - ", asciiBytes1)); // result: 97 - 97 - 65
// case 2
string value21 = 'a' + "A";
byte[] asciiBytes21 = Encoding.ASCII.GetBytes(value21); // expected: 97 - 65
Console.WriteLine(string.Join(" - ", asciiBytes21)); // result: 97 - 65
// case 3
string value22 = 'a' + 'a' + "A";
byte[] asciiBytes22 = Encoding.ASCII.GetBytes(value22); // expected: 97 - 97 - 65
Console.WriteLine(string.Join(" - ", asciiBytes22)); // result: 49 - 57 - 52 - 65
It's the order of operations, In all of the other examples you add a char to a string. However in the third example you add a char to a char, which acts as a byte and does integer multiplication.
And then it integer is added to the string "A"
so 'a' + 'a' = 194
and 194 + "A" = 197A
and thats the results you are seeing
You are mixing chars and strings.
This:
'a' + 'a'
results in the integer addition of the ascii char values.

Convert.To[Type](hexa, base) versus [Type].Parse(hexa, NumberStyles.HexNumber)

In working with hexadecimal (strings stored in a database), integer and binary numeric representations, what is the difference between the folowwing 2 ways of converting from hexadecimal to integer:
List<string> hexadecimals = new List<string>
{
"A1F9",
"D",
"BF17D0015",
"972AB"
};
foreach(var hexadecimal in hexadecimals)
{
var i1 = Convert.ToInt64(hexadecimal, 16);
var i2 = Int64.Parse(hexadecimal, NumberStyles.HexNumber);
Console.WriteLine($"hexa: {hexadecimal}, converted: {i1}, parsed: {i2}. Are equal: [{i1.Equals(i2)}]");
}
Convert.ToInt64(hexadecimal, 16);
Int64.Parse(hexadecimal, NumberStyles.HexNumber);
Should I prefer one to another ?
Output:

How to set space between TextBox values into array

How to set space between TextBox values into array?
TextBox values:
1 32 54 76 89 89 454 23
Expected output array:
value[1]=1;
value[2]=32;
value[3]=76
...
Try this:
var numbers = textBox1.Text.Split(' ');
List<int> lst = numbers.Select(item => int.Parse(item)).ToList();
It will be even better if you use method group like this:
List<int> lst = numbers.Select(int.Parse).ToList();
Then you can get it's values like this:
lst[0] --> 1
lst[1] --> 32
and ...
You first have to split the users input:
var values = myTextBox.Text.Split(' ');
Now you can easily set your array of integers:
var myArr = values.Select(x => Convert.ToInt32(x)).ToArray();
Alternativly you can also use Int.Parse instead of Convert.ToInt32.
String[] values = tv.Text.Split(' '); // the values as string
int[] arr = new int[values.Length]; // the values as integer
for (int i = 0; i < arr.Length; i++)
arr[i] = int.Parse(values[i]);
If I understand you correct you need to create int array from string you can do it like this:
string TextBoxText = "1 32 54 76 89 89 454 23";
var value = TextBoxText.Split(' ').Select(Int32.Parse).ToList();
Then you can use your array like this:
Console.WriteLine(value[1]);
Console.WriteLine(value[2]);
TextBoxText should be Text property of your TextBox component.

How to cast int digit to char without loosing digit value in c#

Mabby it's a stupid question, but how can I cast digit of type int to digit of type char?
Standard conversion OPs doesn't do this:
int x = 5;
char myChar = Convert.ToChar(5); // myChar is now a unicode character
char secondChar = (char)x; // again I get a unicode character, not a digit '5'
I need this because I have a method that returns IEnumerable of Char and I need to return a collection of ints somehow.
For instance:
int[] {1, 2, 3}
convert to
char[] {'1', '2', '3'}
Is it possible to do such a conversion in C#?
Add 48 to your int value before converting to char:
char c = (char)(i + 48);
Or for int[] -> char[] conversion:
var source = new int[] { 1, 2, 3 };
var results = source.Select(i => (char)(i + 48)).ToArray();
It works, because '0' character in ASCII table has 48 value. But it will work only if your int values is between 0 and 9.
If you know for sure that the values are in the 0 .. 9 range (both inclusive), you can slightly improve efficiency by making use of a bitwise or, instead of addition:
(char) ('0' | i);
this works since '0' has as binary codepoint 0011 0000, and the ten digits thus all are between 0011 0000 and 0011 1001.
You can thus convert an IEnumerable<int> to an IEnumerable<char> with:
data.Select(i => (char) ('0' | i));
var yourInts = new int[]{1,2,3};
var result = yourInts.Select(x=>x.ToString()[0]).ToArray();
This should work :
(char) (i + '0')
Example:
var i = 8;
var c = (char) (i + '0');//Gives '8'

Distinguishing string being parsed using String Split

I need to parse a line that is in a similar format as following:
s = "Jun 21 09:47:50 ez-x5 user.debug if_comm: [TX] 02 30 20 0f 30 31 39 24 64 31 30 31 03 54 ";
I am splitting the line with [TX] or [RX]. Here's what I do with the parsed string:
s = "Jun 21 09:47:50 ez-x5 user.debug if_comm: [TX] 02 30 20 0f 30 31 39 24 64 31 30 31 03 54 ";
string[] stringSeparators = new string[] { "[TX] " + start_key };
string transfer = s.Split(stringSeparators, 2, StringSplitOptions.None)[1];
//At this point, transfer[] = 02 30 20 0f 30 31 39 24 64 31 30 31 03 54
if (!string.IsNullOrEmpty(transfer))
{
string key = "";
string[] split = transfer.Split(' ');
if (split[0] == start_key)
{
for (int i = 0; i < key_length; i++)
{
key += split[i + Convert.ToInt32(key_index)];
}
TX_Handle(key);
}
}
stringSeparators = new string[] { "[RX]" + start_key };
transfer = s.Split(stringSeparators, 2, StringSplitOptions.None)[1];
if (!string.IsNullOrEmpty(transfer))
{
string key = "";
string[] split = transfer.Split(' ');
if (split[0] == start_key)
{
for (int i = 0; i < key_length; i++)
{
key += split[i + Convert.ToInt32(key_index)];
}
RX_Handle(key);
}
}
Basically, because I have no realistic way of comparing whether the given token is [TX] or [RX], I am forced to use the above approach to separate the string, which requires me to write essentially the same code twice.
What is a way I can get around this problem and know which token is being parsed so that I don't have to duplicate my code?
The best way to do this is look at what is common. What is common in your code? Splitting based on 2 different tokens and a function call based on 2 different tokens. This can be broken into a conditional, so, why not move the common element into a conditional?
const string receiveToken = "[RX] ";
const string transmitToken = "[TX] ";
string token = s.IndexOf(receiveToken) > -1 ? receiveToken : transmitToken;
..now you have your token, so you can remove most of the duplication.
stringSeparators = new string[] { token + start_key };
transfer = s.Split(stringSeparators, 2, StringSplitOptions.None)[1];
if (!string.IsNullOrEmpty(transfer))
{
string key = "";
string[] split = transfer.Split(' ');
if (split[0] == start_key)
{
for (int i = 0; i < key_length; i++)
{
key += split[i + Convert.ToInt32(key_index)];
}
RX_TX_Handle(key, token);
}
}
..then you can have a common handler, eg:
void RX_TX_Handle(string key, string token)
{
token == receiveToken ? RX_Handle(key) : TX_Handle(key);
}
How about a different approach and use a regular expression. Mixin a little bit of LINQ and you have some pretty easy to follow code.
static void ParseLine(
string line,
int keyIndex,
int keyLength,
Action<List<byte>> txHandler,
Action<List<byte>> rxHandler)
{
var re = new Regex(#"\[(TX|RX)\](?: ([0-9a-f]{2}))+");
var match = re.Match(line);
if (match.Success)
{
var mode = match.Groups[1].Value; // either TX or RX
var values = match.Groups[2]
.Captures.Cast<Capture>()
.Skip(keyIndex)
.Take(keyLength)
.Select(c => Convert.ToByte(c.Value, 16))
.ToList();
if (mode == "TX") txHandler(values);
else if (mode == "RX") rxHandler(values);
}
}
Or without regular expressions:
static void ParseLine(
string line,
int keyIndex,
int keyLength,
Action<List<byte>> txHandler,
Action<List<byte>> rxHandler)
{
var start = line.IndexOf('[');
var end = line.IndexOf(']', start);
var mode = line.Substring(start + 1, end - start - 1);
var values = line.Substring(end + 1)
.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Skip(keyIndex)
.Take(keyLength)
.Select(s => Convert.ToByte(s, 16))
.ToList();
if (mode == "TX") txHandler(values);
else if (mode == "RX") rxHandler(values);
}
I am not 100% sure if this answers your questions but I would create a TokenParser class that is responsible for parsing a token. You'll find it much easier to unit test.
public enum TokenType
{
Unknown = 0,
Tx = 1,
Rx = 2
}
public class Token
{
public TokenType TokenType { get; set; }
public IEnumerable<string> Values { get; set; }
}
public class TokenParser
{
public Token ParseToken(string input)
{
if (string.IsNullOrWhiteSpace(input)) throw new ArgumentNullException("input");
var token = new Token { TokenType = TokenType.Unknown };
input = input.ToUpperInvariant();
if (input.Contains("[TX]"))
{
token.TokenType = TokenType.Tx;
}
if (input.Contains("[RX]"))
{
token.TokenType = TokenType.Rx;
}
input = input.Substring(input.LastIndexOf("]", System.StringComparison.Ordinal) + 1);
token.Values = input.Trim().Split(Convert.ToChar(" "));
return token;
}
}
The example could be easily extended to allow multiple token parsers if the logic for parsing each token is vastly different.

Categories

Resources