|
Hi.
Please consider the following fixed values...
unsigned int value1 = 396;
unsigned int value2 = 398565;
1) The above values will change, but value1 will always be 3 digits, and value2 will always be 6 digits.
How do I....
A) Place both values into one DWORD?
b) Encode it as a 4 byte array.
So, as an example (not actual values)
396 + 398565 -> (DWORD) = 396398565 -> BYTE[] = {0x00, 0x00, 0x00, 0x00 } (whatever the hex would be)
And then, I would need to reverse it, although I think I have the code working to do that, but cant test it properly until I can get the above to work.
Thank you,
Steve
|
|
|
|
|
I still don't see why you insist on the array of bytes.
Here's a rather simple way without unsafe code:
uint a = 396 ;
uint b = 398565 ;
uint c = ( a << 20 ) | ( b & 0x0FFFFFu ) ;
byte[] d = new byte [ sizeof(uint) ] ;
for ( int i = 0 ; i < d.Length ; i++ )
{
d [ i ] = (byte ) ( ( c >> 8 * i ) & 0x0FF ) ;
}
uint e = 0 ;
for ( int i = 0 ; i < d.Length ; i++ )
{
e |= (uint) ( d [ i ] << 8 * i ) ;
}
uint f = e >> 20 ;
uint g = e & 0x0FFFFFu ;
|
|
|
|
|
FYI: I know you're not fond of converter classes, however
BitConverter.GetBytes() and
BitConverter.ToUInt32() are exactly what you want here.
|
|
|
|
|
Luc Pattyn wrote: what you want
What I want?
Actually, I also looked at some code I wrote a while back that does that sort of thing, and I found that the existing tools didn't work properly with some types (e.g. enumerations, DateTime), so I wrote my own.
Here's a taste of that technique:
private static unsafe byte[]
ToByteArray
(
object Value
,
byte[] Buffer
)
{
System.Runtime.InteropServices.GCHandle h =
System.Runtime.InteropServices.GCHandle.Alloc
( Value , System.Runtime.InteropServices.GCHandleType.Pinned ) ;
try
{
byte* b = (byte*) h.AddrOfPinnedObject().ToPointer() ;
for ( int i = 0 ; i < Buffer.Length ; i++ )
{
Buffer [ i ] = b [ i ] ;
}
}
finally
{
h.Free() ;
}
return ( Buffer ) ;
}
I may have to try this BitConverter, but I doubt I'll like it.
What I presented, though, is obviously very simple, about the minimum required for the stated task.
|
|
|
|
|
Hi Luc,
This time I was going to use BitCOnverter, but because the first problem was to get 2 int values into one uint, uint32 or whatever I would need, and then convert to a byte array.
Thank you,
Stephen
|
|
|
|
|
Ah, I see that the BitConverter only works with a few, rarely used, datatypes (and not strings! ) -- I want (not need) a more general solution.
|
|
|
|
|
Hi.
This does not seem to work.
It produces the following uint:
129098304
and I need 396398565
Thank you,
Stephen
|
|
|
|
|
|
BitConverter.GetBytes(a + 1000000*b)
|
|
|
|
|
|
Hi,
Sorry, this produces a different result than required.
uint val1 = 583;
uint val2 = 728439;
I should have 583728439, which sould be (in bytes) 0x22CAFD37.
Am I doing something wrong?
Thank you,
Stephen
|
|
|
|
|
|
You can combine them using division and modulo operations:
const uint shift = 1000000;
uint val1 = 539;
uint val2 = 666666;
uint combined = (val1 * shift) + val2;
uint restore_val1 = combined / shift;
uint restore_val2 = combined % shift;
As for getting the byte array, you can use the BitConverter:
byte[] combined_bin = BitConverter.GetBytes(combined);
|
|
|
|
|
Thank you very much.
That works perfect.
Steve
|
|
|
|
|
Hi.
The following function was taken from c++ code, and I have tried to adapt it for my c# code, however, I am not sure if it is doing the same thing?
The full c++ function is...
void ShowProdKey(unsigned char *ProdKey)
{
unsigned int Val1, Val2;
Val1 = *(unsigned int *)ProdKey;
Val1 &= 0x7fffffff;
Val1 >>= 1;
Val2 = CheckDigit(Val1 % 1000000);
Val1 /= 1000000;
printf("Your product ID should be XXXXX-%.3u-%.7u-XXXXX.\n", Val1, Val2);
}
and my adapted function is the following (it works as in as far as it is producing a result which looks correct, but I am unsure if the changed part of the function is doing the same as in the above code)
void ShowProdKey(byte[] prodKey)
{
uint val1, val2;
val1 = BitConverter.ToUInt32(prodKey, 0);
val1 &= 0x7fffffff;
val1 >>= 1;
val2 = CheckDigit(val1 % 1000000);
val1 /= 1000000;
string output = ("");
output = val1.ToString();
output += val2.ToString();
MessageBox.Show(output);
}
So the part I changed was this in c++
Val1 = *(unsigned int *)ProdKey;
To this...
val1 = BitConverter.ToUInt32(prodKey, 0);
The output should be a double word formatted something like...
000 - 0000000
My version does produce a value like this, so I think it may be doing the same thing?
Also, how would I write code to reverse the function?
Or, in other words, the above function takes 4 bytes and produces a DWORD, which it formats into two unsigned ints...
How would I write a function that would take two unsigned ints, and produce a DWORD, and then encode that into 4 bytes, the reverse of the above function?
Thank you VERY much for your help...
Stephen
|
|
|
|
|
stephen.darling wrote: Val1 = *(unsigned int *)ProdKey;
Can probably be done with unsafe code.
stephen.darling wrote: Val1 >>= 1;
Probably makes it non-reversible (except with a 50/50 probability of being correct).
stephen.darling wrote: CheckDigit
What does that do?
What is it trying to do? It doesn't seem to use all the bits that are sent in.
|
|
|
|
|
Hi,
Well, using that function, if the 4 bytes are:
0x22CAFD37, the function should produce the following number:
583728439
Now, using the c++ version it works correct, but my c# version does not produce the correct value, it does produce a 9 digit number, but not that one.
However, if I try to use:
Val1 = *(unsigned int *)ProdKey;
in my c# version, it wont compile, so not sure if the code I changed is doing something else?
To answer what it is, let me explain...
My keygenerator generates the above 9 digit number, as a kind of product ID value, and encodes it into a 4 byte array to build part of a serial number..
When the serial number is entered into my application, the 4 bytes are decoded back into a dword, and the above function formats it into the 9 digits shown, and my app checks them,
It is working, and 9 digits are produced, but they are incorrect????
Also, how do I reverse the code to get two int values into one DWORD, and then encode it back into a 4 byte array?
Thank you,
Stephen
|
|
|
|
|
The BitConverter code looks correct. (Just like a cast in C, though, it will give a different answer if the machine has the opposite endianness.) Your code is doing more than just that – what is CheckDigit doing?
|
|
|
|
|
Hi.
Thank you. So How do I check and/or fix the endian?
If it helps, the text I have says that it is stored in little endian byte order, and the following four bytes: 0x22CAFD37 should produce 583728439.
The checkdigit function then calculates and adds a checkdigit so that the above is then:
5837284392
here is the code for check digit...
<pre>uint CheckDigit(uint val)
{
uint sum, copy;
sum = 0;
copy = val;
while (copy !=0)
{
sum += copy % 10;
copy /= 10;
}
return val * 10 + 7 - (sum % 7);
}</pre>
thank you
|
|
|
|
|
On my machine (Windows 32 bit) I'm getting the opposite order:
$BitConverter:GetBytes(5)
(5 0 0 0)
$BitConverter:GetBytes(583728439)
(55 253 202 34)
{x: x:ToString "X2"}¨($BitConverter:GetBytes(583728439))
(37 FD CA 22)
This should be the same in C++, however.
(I can't so easily test the other way around, my toy language doesn't understand about bytes as a native type at the moment.)
|
|
|
|
|
OK,thank you.
I will keep trying on with this.
Steve
|
|
|
|
|
Hi All !
myVal=1365 , and in the String.Format i want to get only Two last digit number(65) .
using with String.Format , any body help to this :
String.Format("{0:00}",myVal); but the output is : 1365
Regards !
|
|
|
|
|
|
thanks , but is it possible with String Format
|
|
|
|
|
Not to my knowledge.
|
|
|
|
|