String of hex into a byte array? [duplicate] - c#

This question already has answers here:
How can I convert a hex string to a byte array? [duplicate]
(4 answers)
Closed 5 years ago.
string hash = "4A|DA|6C|A9|C2|D5|71|EF|6E|2A|8C|C3|C9|4D|36|B9"
splitRHash2 = splitRHash.Split('|');
foreach (string i in splitRHash2)
{
//BYTEARRAY += Convert.ToByte(Convert.ToInt32(i, 16))???
}
I have no idea of going about this. I simply wanted this string of hex:
4ADA6CA9C2D571EF6E2A8CC3C94D36B9
Into a byte array with 16 bytes. This will greatly help me to call these values from the 'hash' and use it add round keys later on for a project. The problem is, I have no knowledge in getting the string at increments of 2 without using the .split method.
Any ideas? Thanks!!

Simply use LINQ to convert the splitted strings to bytes and to an array afterwards. Here is the code:
string hash = "4A|DA|6C|A9|C2|D5|71|EF|6E|2A|8C|C3|C9|4D|36|B9";
string[] splittedHash = hash.Split('|');
byte[] byteHash = splittedHash.Select(b => Convert.ToByte(b, 16)).ToArray();

You talking about something like this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApp
{
class Program
{
static void Main (string[] args)
{
var str = "4ADA6CA9C2D571EF6E2A8CC3C94D36B9";
var result = Partition (str, 2).ToArray ();
}
public static IEnumerable<string> Partition (string str, int partSize)
{
if (str == null) throw new ArgumentNullException ();
if (partSize < 1) throw new ArgumentOutOfRangeException ();
var sb = new StringBuilder (partSize);
for (int i = 0; i < str.Length; i++)
{
sb.Append (str[i]);
bool isLastChar = i == str.Length - 1;
if (sb.Length == partSize || isLastChar)
{
yield return sb.ToString ();
sb.Clear ();
}
}
}
}
}

You could make the solution with only basic data structures and O(n) time like this.
string hash = "4A|DA|6C|A9|C2|D5|71|EF|6E|2A|8C|C3|C9|4D|36|B9";
byte[] result = new byte[16];
int i = 0;
int j = 0;
while(i < hash.Length)
{
byte value = (byte)(HexCharToByte(hash[i]) * 16 + HexCharToByte(hash[i + 1]));
result[j] = value;
i += 3;
j++;
}
For HexCharToByte(), you could make up something like this:
static byte HexCharToByte(char c)
{
HashSet<char> NumSet = new HashSet<char>( new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} );
HashSet<char> CharSet = new HashSet<char>( new char[] { 'A', 'B', 'C', 'D', 'E', 'F' } );
if (NumSet.Contains(c))
{
return (byte)(c - '0');
}
else if (CharSet.Contains(c))
{
return (byte)(c - 'A' + 10);
}
throw new InvalidArgumentException("c");
}

Related

While loop for alphabet

I am trying to code the following example.
Input ABCDEFGHIJKLMNOPQRSTUVWXYZ
Output ZYXWVUTSRQPONMLKJIHGFEDCBA
If user types in A it will output Z. It has to go past 25 characters to reach Z. So I am guessing a while loop will be needed, then if B it has to go through 23 times, so – 2 and so on until it reaches M as it will skip though 1 to reach N, then start again at 25.
Any suggestion on how to approach this?
Capital ASCII characters range according to the ASCII-table from 65 (0x41, 'A') to 90 (0x5A, 'Z').
This is the algorithm:
// inputChar is a char holding your character
char inputChar = getCharFromUser();
int inputVal = inputChar - 65; // e.g. 0 for 'A', 1 for 'B'
char outputChar = 90 - inputVal; // e.g. 90 - 1 = 89 = 'Y'
outputCharToUser(outputChar);
And this is how you might implement it in C#:
while (true)
{
var key = Console.ReadKey(intercept: true);
var inputChar = char.ToUpper(key.KeyChar);
var outputChar = (char)('Z' - inputChar + 'A');
Console.Write("{0}={1} ", inputChar, outputChar);
}
You could use two dictionaries which enable to lookup the char from index and vice-versa:
var indexLookup = "abcdefghijklmnopqrstuvwxyz"
.Select((chr, index) => new { chr, index })
.ToDictionary(x => x.chr, x => x.index);
var charLookup = "abcdefghijklmnopqrstuvwxyz"
.Select((chr, index) => new { chr, index })
.ToDictionary(x => x.index, x => x.chr);
Now it's simple, the essential part is charLookup[25 - indexOfChar]:
string userInput = "B";
bool isUpper = char.IsUpper(userInput[0]);
char inputChar = Char.ToLowerInvariant(userInput[0]);
if(indexLookup.ContainsKey(inputChar))
{
int indexOfChar = indexLookup[inputChar];
char oppositeChar = charLookup[25 - indexOfChar];
string result = isUpper ? Char.ToUpperInvariant(oppositeChar).ToString() : oppositeChar.ToString();
Console.Write(result); // Y
}
Actually you don't need two dictionaries but only one since the string can already be used to lookup a char by index. Here is a class which provides the logic:
public class CharSwap
{
private string alphabet;
private Dictionary<char, int> indexLookup;
public CharSwap() : this("abcdefghijklmnopqrstuvwxyz") { }
public CharSwap(string alphabet)
{
if(alphabet == null) throw new ArgumentNullException("alphabet");
this.alphabet = alphabet;
indexLookup = alphabet.Select((chr, index) => new { chr, index }).ToDictionary(x => x.chr, x => x.index);
}
public char? OppositeChar(char input)
{
char lowerChar = Char.ToLowerInvariant(input);
if (!indexLookup.ContainsKey(lowerChar))
return null;
int indexOfChar = indexLookup[lowerChar];
int indexOpposite = alphabet.Length - 1 - indexOfChar;
return Char.IsUpper(input)
? Char.ToUpperInvariant(alphabet[indexOpposite])
: alphabet[indexOpposite];
}
}
Test:
CharSwap cw = new CharSwap();
char? oppositeChar = cw.OppositeChar('B');
Console.Write(oppositeChar);
char input = 'B';
string Range = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char result = Range[Range.Length - 1 - Range.IndexOf(input)]; //Y
or maybe another approach
char input = 'B';
string Range = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char result = Range.Reverse().ElementAt(Range.IndexOf(input)); //Y
How about something like this?
char[] alphabet = {'A','B', 'C'} // and so on
char[] mapsTo = {'Z', 'Y', 'X'} // and so on, excluded for brevity
public function string changeLetter(char input)
{
int i = 0;
foreach (char c in alphabet) {
if (c == input) {
return mapsTo[i];
}
i++;
}
return '';
}
Converted to c#:
char[] alphabet = {'A','B', 'C'}; // and so on
char[] mapsTo = {'Z', 'Y', 'X'}; // and so on, excluded for brevity
public string changeLetter(char input)
{
int i = 0;
foreach (char c in alphabet) {
if (c == input) {
return mapsTo[i].ToString();
}
i++;
}
return default(char).ToString();
}
You would call this function like this (for instance):
public static void RunProgram()
{
Console.WriteLine("Please type in character");
input = Console.ReadKey().KeyChar;
Console.WriteLine("You typed in " + input + ". This results in: " + ChangeInput(input));
}
... where "ChangeInput" is the function defined earlier.
The easy way to solve this is to use a Dictionary<char, char>:
public class Atbash {
static string source = "abcdefghijklmnopqrstuvwxyz";
static List<char> keys = source.ToList();
static List<char> values = source.Reverse().ToList();
static Dictionary<char, char> Converter = keys.ToDictionary(x => x, x => values[keys.IndexOf(x)]);
public static char Convert(char input)
{
char output;
bool isUpper = char.IsUpper(input);
input = char.ToLowerInvariant(input);
if(Converter.ContainsKey(input)) {
output = Converter[input];
return (isUpper) ? char.ToUpperInvariant(output) : output;
}
throw new ArgumentOutOfRangeException("Input char is unknown");
// of course, it can return default(char) instead of throwing an exception.
}
}
Why Atbash? read about it here.

Replacing letters in words

Hello I'm having a little trouble on this one aspect in my code. I have some strings and I have a array of chars. I'm trying to replace the last two letters of each string
with the characters in the char array until the last one.
My array of char is as follows:
char[] array = { 'v', 'x', 'f' };
My code so far:
char[] array = { 'v', 'x', 'f' };
string newWord="";
string apple="apple";
string sam="sam";
foreach(char c in array)
{
apple= apple.Substring(0, apple.Length - 2) +""; ///DON'T KNOW WHAT TO PUT HERE;
sam= sam.Substring(0, sam.Length - 2)+""; ///DON'T KNOW WHAT TO PUT HERE;
newWord = apple+Environment.NewLine+sam ;
}
The output should like like this:
appvx
sfm
Maybe I'm doing this wrong but I'm explicitly telling it in the substring to get rid of the last to letters in the word but if the array runs out won't it still delete the last two. For instance the word sam still needs to have m at the end of it since all the chars in the array have already been used like what the out but shows but replace a with f
something like this?
private static void something()
{
List<char> tokens = new List<char>(new char[]{ 'v', 'x', 'f' });
List<char[]> lArr = new List<char[]>();
lArr.Add("apple".ToCharArray());
lArr.Add("sam".ToCharArray());
List<string> lStr = new List<string>();
int cnt = 2;
foreach (var token in tokens)
{
var aktArr = lArr.FirstOrDefault();
if (aktArr == null)
break;
if (cnt == 0)
{
cnt = 2;
lStr.Add(new string(aktArr));
lArr.RemoveAt(0);
aktArr = lArr.FirstOrDefault();
if (aktArr == null)
break;
}
aktArr[aktArr.Length - cnt--] = token;
}
lStr.AddRange(lArr.Select(x => new string(x)));
foreach (var item in lStr)
{
Console.WriteLine(item);
}
}
You can treat a string as an array of chars, so the result can be something like this (supposing that you have an array of words, not only 2 variables for them and a little helper to replace chars)
var words = new [] {"apple", "sam"};
var wordPos = 0;
for (int i = 0; i < array.Length; i++)
{
var wordLen = words[wordPos].Length;
var letterPos = i % 2 == 0 ? 1 : 2;
words[wordPos] = words[wordPos].ReplaceAt(wordLen - letterPos, letter);
if (letterPos == 1) wordPos++;
}
public static string ReplaceAt(this string input, int index, char newChar)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
char[] chars = input.ToCharArray();
chars[index] = newChar;
return new string(chars);
}
I think something like this will do what you need:
var charArray = new[] {'a', 'b', 'c'};
var words = new List<string> {"apple", "sam"};
var currentWord = 0;
var currentChar = 0;
var charsToReplace = 2;
while (currentChar < charArray.Length && currentWord != words.Count)
{
var word = words[currentWord].ToCharArray();
word[word.Length - charsToReplace] = charArray[currentChar];
words[currentWord] = new string(word);
charsToReplace--;
currentChar++;
if (charsToReplace == 0)
{
charsToReplace = 2;
currentWord++;
}
}
words.ForEach(Console.WriteLine);

Check if a character is a vowel or consonant?

Is there a code to check if a character is a vowel or consonant? Some thing like char = IsVowel? Or need to hard code?
case ‘a’:
case ‘e’:
case ‘i’:
case ‘o’:
case ‘u’:
case ‘A’:
case ‘E’:
case ‘I’:
case ‘O’:
case ‘U’:
You could do this:
char c = ...
bool isVowel = "aeiouAEIOU".IndexOf(c) >= 0;
or this:
char c = ...
bool isVowel = "aeiou".IndexOf(c.ToString(), StringComparison.InvariantCultureIgnoreCase) >= 0;
Once you add international support for things like éèe̋ȅëêĕe̊æøи etc. this string will get long, but the basic solution is the same.
Here's a function that works:
public static class CharacterExtentions
{
public static bool IsVowel(this char c)
{
long x = (long)(char.ToUpper(c)) - 64;
if (x*x*x*x*x - 51*x*x*x*x + 914*x*x*x - 6894*x*x + 20205*x - 14175 == 0) return true;
else return false;
}
}
Use it like:
char c = 'a';
if (c.IsVowel()) { // it's a Vowel!!! }
(Yes, it really works, but obviously, this is a joke answer. Don't downvote me. or whatever.)
No. You need to define first what you regard as a vowel and as a consonant. For example, in English, “y” could be a consonant (as in “yes”) or a vowel (as in “by”). Letters like “é” and “ü” are probably vowels in all languages in which they are used, but it seems that you did not consider them at all. Primarily, you should define why you wish to classify letters as consonants and vowels.
Console.WriteLine("Please input a word or phrase:");
string userInput = Console.ReadLine().ToLower();
for (int i = 0; i < userInput.Length; i++)
{
//c stores the index of userinput and converts it to string so it is readable and the program wont bomb out.[i]means position of the character.
string c = userInput[i].ToString();
if ("aeiou".Contains(c))
{
vowelcount++;
}
}
Console.WriteLine(vowelcount);
The other methods given work. Here I am concerned with performance. For the two approaches I tested - using LINQ's Any method and using bit arithmetic, the use of bit arithmetic was more than ten times faster. Results:
Time for LINQ = 117 msec
Time for Bit masks = 8 msec
public static bool IsVowelLinq(char c)
{
char[] vowels = new[] { 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' };
return vowels.Any(ch => ch == c);
}
private static int VowelMask = (1 << 1) | (1 << 5) | (1 << 9) | (1 << 15) | (1 << 21);
public static bool IsVowelBitArithmetic(char c)
{
// The OR with 0x20 lowercases the letters
// The test c > 64 rules out punctuation, digits, and control characters.
// An additional test would be required to eliminate characters above ASCII 127.
return (c > 64) && ((VowelMask & (1 << ((c | 0x20) % 32))) != 0);
}
See https://dotnetfiddle.net/WbPHU4 for the code in a test with timings.
The key idea with the bit mask is that the second bit is set for 'a', the sixth bit is set for 'e', etc. Then you take the letter, shift left by its ASCII value as an integer, and see if that bit in the mask is set. One bit is set in the mask for each vowel, and the OR operation performs the lowercasing of the letter first.
You can use "IsVowel" as you wanted. However the only thing is there is likely no default C# library or function that already does this out of the box, well if this is what you wanted. You will need to write a util method for this.
bool a = isVowel('A');//example method call
public bool isVowel(char charValue){
char[] vowelList = {'a', 'e', 'i', 'o', 'u'};
char casedChar = char.ToLower(charValue);//handle simple and capital vowels
foreach(char vowel in vowelList){
if(vowel == casedChar){
return true;
}
}
return false;
}
This works just fine.
public static void Main(string[] args)
{
int vowelsInString = 0;
int consonants = 0;
int lengthOfString;
char[] vowels = new char[5] { 'a', 'e', 'i', 'o', 'u' };
string ourString;
Console.WriteLine("Enter a sentence or a word");
ourString = Console.ReadLine();
ourString = ourString.ToLower();
foreach (char character in ourString)
{
for (int i = 0; i < vowels.Length; i++)
{
if (vowels[i] == character)
{
vowelsInString++;
}
}
}
lengthOfString = ourString.Count(c => !char.IsWhiteSpace(c)); //gets the length of the string without any whitespaces
consonants = lengthOfString - vowelsInString; //Well, you get the idea.
Console.WriteLine();
Console.WriteLine("Vowels in our string: " + vowelsInString);
Console.WriteLine("Consonants in our string " + consonants);
Console.ReadKey();
}
}
Why not create an array of the vowels/consonants and check if the value is in the array?
You can do something like this in.
private bool IsCharacterAVowel(char c)
{
string vowels = "aeiou";
return vowels.IndexOf(c.ToString(),StringComparison.InvariantCultureIgnoreCase) >= 0;
}
You can use the following extension method:
using System;
using System.Linq;
public static class CharExtentions
{
public static bool IsVowel(this char character)
{
return new[] {'a', 'e', 'i', 'o', 'u'}.Contains(char.ToLower(character));
}
}
Use it like:
'c'.IsVowel(); // Returns false
'a'.IsVowel(); // Returns true
return "aeiou".Any( c => c.Equals( Char.ToLowerInvariant( myChar ) ) );
Try this out:
char[] inputChars = Console.ReadLine().ToCharArray();
int vowels = 0;
int consonants = 0;
foreach (char c in inputChars)
{
if ("aeiou".Contains(c) || "AEIOU".Contains(c))
{
vowels++;
}
else
{
consonants++;
}
}
Console.WriteLine("Vowel count: {0} - Consonant count: {1}", vowels, consonants);
Console.ReadKey();
Look at this code to check for both Vowel and Consonant , C#
private static void Vowel(string value)
{
int vowel = 0;
foreach (var x in value.ToLower())
{
if (x.Equals('a') || x.Equals('e') || x.Equals('i') || x.Equals('o') || x.Equals('u'))
{
vowel += 1;
}
}
Console.WriteLine( vowel + " number of vowels");
}
private static void Consonant(string value)
{
int cont = 0;
foreach (var x in value.ToLower())
{
if (x > 'a' && x <= 'd' || x > 'e' && x < 'i' || x > 'j' && x < 'o' || x >= 'p' && x < 'u' || x > 'v' && x < 'z')
{
cont += 1;
}
}
Console.WriteLine(cont + " number of consonant");
}

Convert from string ascii to string Hex

Suppose I have this string
string str = "1234"
I need a function that convert this string to this string:
"0x31 0x32 0x33 0x34"
I searched online and found a lot of similar things, but not an answer to this question.
string str = "1234";
char[] charValues = str.ToCharArray();
string hexOutput="";
foreach (char _eachChar in charValues )
{
// Get the integral value of the character.
int value = Convert.ToInt32(_eachChar);
// Convert the decimal value to a hexadecimal value in string form.
hexOutput += String.Format("{0:X}", value);
// to make output as your eg
// hexOutput +=" "+ String.Format("{0:X}", value);
}
//here is the HEX hexOutput
//use hexOutput
This seems the job for an extension method
void Main()
{
string test = "ABCD1234";
string result = test.ToHex();
}
public static class StringExtensions
{
public static string ToHex(this string input)
{
StringBuilder sb = new StringBuilder();
foreach(char c in input)
sb.AppendFormat("0x{0:X2} ", (int)c);
return sb.ToString().Trim();
}
}
A few tips.
Do not use string concatenation. Strings are immutable and thus every time you concatenate a string a new one is created. (Pressure on memory usage and fragmentation) A StringBuilder is generally more efficient for this case.
Strings are array of characters and using a foreach on a string already gives access to the character array
These common codes are well suited for an extension method included in a utility library always available for your projects (code reuse)
Convert to byte array and then to hex
string data = "1234";
// Convert to byte array
byte[] retval = System.Text.Encoding.ASCII.GetBytes(data);
// Convert to hex and add "0x"
data = "0x" + BitConverter.ToString(retval).Replace("-", " 0x");
System.Diagnostics.Debug.WriteLine(data);
static void Main(string[] args)
{
string str = "1234";
char[] array = str.ToCharArray();
string final = "";
foreach (var i in array)
{
string hex = String.Format("{0:X}", Convert.ToInt32(i));
final += hex.Insert(0, "0X") + " ";
}
final = final.TrimEnd();
Console.WriteLine(final);
}
Output will be;
0X31 0X32 0X33 0X34
Here is a DEMO.
A nice declarative way to solve this would be:
var str = "1234"
string.Join(" ", str.Select(c => $"0x{(int)c:X}"))
// Outputs "0x31 0x32 0x33 0x34"
[TestMethod]
public void ToHex()
{
string str = "1234A";
var result = str.Select(s => string.Format("0x{0:X2}", ((byte)s)));
foreach (var item in result)
{
Debug.WriteLine(item);
}
}
This is one I've used:
private static string ConvertToHex(byte[] bytes)
{
var builder = new StringBuilder();
var hexCharacters = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
for (var i = 0; i < bytes.Length; i++)
{
int firstValue = (bytes[i] >> 4) & 0x0F;
int secondValue = bytes[i] & 0x0F;
char firstCharacter = hexCharacters[firstValue];
char secondCharacter = hexCharacters[secondValue];
builder.Append("0x");
builder.Append(firstCharacter);
builder.Append(secondCharacter);
builder.Append(' ');
}
return builder.ToString().Trim(' ');
}
And then used like:
string test = "1234";
ConvertToHex(Encoding.UTF8.GetBytes(test));

Random string with no duplicates

I'm trying to generate a 16 chars random string with NO DUPLICATE CHARS. I thoght that it shouldn't be to hard but I'm stuck.
I'm using 2 methods, one to generate key and another to remove duplicate chars. In main I've created a while loop to make sure that generated string is 16 chars long.
There is something wrong with my logic because it just shoots up 16-char string
with duplicates. Just can't get it right.
The code:
public string RemoveDuplicates(string s)
{
string newString = string.Empty;
List<char> found = new List<char>();
foreach (char c in s)
{
if (found.Contains(c))
continue;
newString += c.ToString();
found.Add(c);
}
return newString;
}
public static string GetUniqueKey(int maxSize)
{
char[] chars = new char[62];
chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
byte[] data = new byte[1];
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
crypto.GetNonZeroBytes(data);
data = new byte[maxSize];
crypto.GetNonZeroBytes(data);
StringBuilder result = new StringBuilder(maxSize);
foreach (byte b in data)
{
result.Append(chars[b % (chars.Length)]);
}
return result.ToString();
}
string builder = "";
do
{
builder = GetUniqueKey(16);
RemoveDuplicates(builder);
lblDir.Text = builder;
Application.DoEvents();
} while (builder.Length != 16);
Consider implementing shuffle algorithm with which you will shuffle your string with unique characters and then just pick up first 16 characters.
You can do this in-place, by allocating single StringBuffer which will contain your initial data ("abc....") and just use Durstenfeld's version of the algorithm to mutate your buffer, than return first 16 chars.
There are many algorithms for this.
One easy one is:
Fill an array of chars with the available chars.
Shuffle the array.
Take the first N items (where N is the number of characters you need).
Sample code:
using System;
namespace ConsoleApplication2
{
internal class Program
{
private static void Main(string[] args)
{
var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
Random rng = new Random();
for (int i = 0; i < 10; ++i)
{
string randomString = RandomString(16, chars, rng);
Console.WriteLine(randomString);
}
}
public static string RandomString(int n, char[] chars, Random rng)
{
Shuffle(chars, rng);
return new string(chars, 0, n);
}
public static void Shuffle(char[] array, Random rng)
{
for (int n = array.Length; n > 1; )
{
int k = rng.Next(n);
--n;
char temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
}
}
const string chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
var r = new Random();
var s = new string(chars.OrderBy(x => r.Next()).Take(16).ToArray());
I am using a GUID generation method it itself generates random strings and you can modify it if a number appears in the beginning,
use the code given below:
string guid = System.Guid.NewGuid().ToString("N");
while (char.IsDigit(guid[0]))
guid = System.Guid.NewGuid().ToString("N");
Hope that helps.
See if this helps:
RandomString()
{
string randomStr = Guid.NewGuid().ToString();
randomStr = randomStr.Replace("-", "").Substring(0, 16);
Console.WriteLine(randomStr);
}
This returns alpha-numeric string.

Categories

Resources