Some hints, assuming that the point of this exercise is to teach you some bit twiddling.
string
is [essentially] a sequence of char
.
char
is, under the covers, a 16-bit unsigned integer (ushort
).
Once you have that integral value, conversion to [a textual representation of] different bases is pretty simple. Conversion to a binary, octal or hex, since those are all power-of-2 bases is simply a matter of bit shifting and masking. Conversion to decimal (base 10) involves division.
Here are some examples that make minimal use of built-in conversion/formatting utilities.
Conversion to Hex (Base 16). Hex is a convenient shorthand for representing binary values. It takes bits in groups of 4 ('nibbles'), thus each hex "digit" has a range of 16 values (0-15). Conversion is a matter of shifting and masking in units of 4. Since we're shifting and masking, we can build the result in order:
private static string CharToHexString( char c )
{
StringBuilder sb = new StringBuilder();
int codePoint = (ushort) c ;
int shiftAmount = 16 ;
do
{
shiftAmount -= 4 ;
// shift the value the correct number of bits to the right and mask off everthing but the low order nibble
int nibble = (codePoint>>shiftAmount)&0x000F ;
sb.Append( "0123456789ABCDEF"[nibble] ) ;
} while ( shiftAmount > 0 ) ;
string value = sb.ToString() ;
return value ;
}
Conversion to Octal (base 8) is essentially the same as conversion to hex. The difference is that the nibble size is 3 bits and thus the domain of the digit is 0-7 (8 values):
private static string CharToOctalString( char c )
{
StringBuilder sb = new StringBuilder();
int codePoint = (ushort) c ;
int shiftAmount = 18 ; // has to be integral multiple of nibble size
do
{
shiftAmount -= 3 ;
// shift the value the correct number of bits to the right and mask off everthing but the low order nibble
int nibble = (codePoint>>shiftAmount)&0x0007 ;
sb.Append( "01234567"[nibble] ) ;
} while ( shiftAmount > 0 ) ;
string value = sb.ToString() ;
return value ;
}
Conversion to Binary (base 2), likewise, is essentially the same as the above, with the nibble size being 1 bit:
private static string CharToBinaryString( char c )
{
StringBuilder sb = new StringBuilder();
int codePoint = (ushort) c ;
int shiftAmount = 16 ;
do
{
shiftAmount -= 1 ;
// shift the value the correct number of bits to the right and mask off everything but the low order nibble
int nibble = (codePoint>>shiftAmount)&0x0001 ;
sb.Append( "01"[nibble] ) ;
} while ( shiftAmount > 0 ) ;
string value = sb.ToString() ;
return value ;
}
Conversion to decimal (base 10). This is a little different, since the base is not a power of 2. That means we have to use division to peel off the digits in reverse order, starting with the low order digit. To do that, we're going to use a Stack<T>
, since a stack is a LIFO (last-in, first-out) data structure, which will give use the reversing quality we need. To that effect:
private static string CharToDecimalString( char c )
{
Stack<char> digits = new Stack<char>() ;
int codePoint = (ushort) c ;
do
{
int digit = codePoint % 10 ; // modulo 10 arithmetic gives us the low order digit
codePoint = codePoint / 10 ; // integer division by 10 shifts the lower order digit off
digits.Push("0123456789"[digit]);
} while ( codePoint > 0 ) ;
string value = new string( digits.ToArray() ) ; // this pops the entire stack, thus reversing the digits.
return value ;
}