I am new to c++. I want to take input a unsigned 128 bit integer using scanf and print it using printf. As I am new to c++ , I only know these two methods for input output. Can someone help me out?
You could use boost, but this library set must be installed yourself:
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
int main()
{
using namespace boost::multiprecision;
uint128_t v = 0;
std::cin >> v; // read
std::cout << v << std::endl; // write
return 0;
}
If you want to get along without boost, you can store the value into two uint64_t as such:
std::string input;
std::cin >> input;
uint64_t high = 0, low = 0, tmp;
for(char c : input)
{
high *= 10;
tmp = low * 10;
if(tmp / 10 != low)
{
high += ((low >> 32) * 10 + ((low & 0xf) * 10 >> 32)) >> 32;
}
low = tmp;
tmp = low + c - '0';
high += tmp < low;
low = tmp;
}
Printing then, however, gets more ugly:
std::vector<uint64_t> v;
while(high | low)
{
uint64_t const pow10 = 100000000;
uint64_t const mod = (((uint64_t)1 << 32) % pow10) * (((uint64_t)1 << 32) % pow10) % pow10;
tmp = high % pow10;
uint64_t temp = tmp * mod % pow10 + low % pow10;
v.push_back((tmp * mod + low) % pow10);
low = low / pow10 + tmp * 184467440737 + tmp * /*0*/9551616 / pow10 + (temp >= pow10);
high /= pow10;
}
std::vector<uint64_t>::reverse_iterator i = v.rbegin();
while(i != v.rend() && *i == 0)
{
++i;
}
if(i == v.rend())
{
std::cout << 0;
}
else
{
std::cout << *i << std::setfill('0');
for(++i; i != v.rend(); ++i)
{
std::cout << std::setw(8) << *i;
}
}
Above solution works up to (including)
340282366920938463463374516198409551615
= 0x ffff ffff ffff ffff ffff ad06 1410 beff
Above, there is an error.
Note: pow10 can be varied, then some other constants need to be adjusted, e. g. pow10 = 10:
low = low / pow10 + tmp * 1844674407370955161 + tmp * 6 / pow10 + (temp >= pow10);
and
std::cout << std::setw(1) << *i; // setw also can be dropped in this case
Increasing results in reducing the maximum number for which printing still works correctly, decreasing raises the maximum. With pow10 = 10, maximum is
340282366920938463463374607431768211425
= ffff ffff ffff ffff ffff ffff ffff ffe1
I don't know where the error for the very highest numbers comes from, yet, possibly some unconsidered overflow. Any suggestions appreciated, then I'll improve the algorithm. Until then, I'd reduce pow10 to 10 and introduce a special handling for the highest 30 failing numbers:
std::string const specialValues[0] = { /*...*/ };
if(high == 0xffffffffffffffff && low > 0xffffffffffffffe1)
{
std::cout << specialValues[low - 0xffffffffffffffe2];
}
else
{
/* ... */
}
So at least, we can handle all valid 128-bit values correctly.
You can try from_string_128_bits and to_string_128_bits with 128 bits unsigned integers in C :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
__uint128_t from_string_128_bits(const char *str) {
__uint128_t res = 0;
for (; *str; res = res * 10 + *str++ - '0');
return res;
}
static char *to_string_128_bits(__uint128_t num) {
__uint128_t mask = -1;
size_t a, b, c = 1, d;
char *s = malloc(2);
strcpy(s, "0");
for (mask -= mask / 2; mask; mask >>= 1) {
for (a = (num & mask) != 0, b = c; b;) {
d = ((s[--b] - '0') << 1) + a;
s[b] = "0123456789"[d % 10];
a = d / 10;
}
for (; a; s = realloc(s, ++c + 1), memmove(s + 1, s, c), *s = "0123456789"[a % 10], a /= 10);
}
return s;
}
int main(void) {
__uint128_t n = from_string_128_bits("10000000000000000000000000000000000001");
n *= 7;
char *s = to_string_128_bits(n);
puts(s);
free(s); // string must be freed
// print 70000000000000000000000000000000000007
}
Related
I want to write a function to reverse one of two parts of number :
Input is: num = 1234567; part = 2
and output is: 1234765
So here is part that can be only 1 or 2
Now I know how to get part 1
int firstPartOfInt(int num) {
int ret = num;
digits = 1, halfDig = 10;
while (num > 9) {
ret = ret / 10;
digits++;
}
halfDigits = digits / 2;
for (int i = 1; i < halfDigits; i++) {
halfDigits *= 10;
}
ret = num;
while (num > halfDigits) {
ret = ret / 10;
}
return ret;
}
But I don't know how to get part 2 and reverse the number. If you post code here please do not use vector<> and other C++ feature not compatible with C
One way is to calculate the total number of digits in the number and then calculate a new number extracting digits from the original number in a certain order, complexity O(number-of-digits):
#include <stdio.h>
#include <stdlib.h>
unsigned reverse_decimal_half(unsigned n, unsigned half) {
unsigned char digits[sizeof(n) * 3];
unsigned digits10 = 0;
do digits[digits10++] = n % 10;
while(n /= 10);
unsigned result = 0;
switch(half) {
case 1:
for(unsigned digit = digits10 / 2; digit < digits10; ++digit)
result = result * 10 + digits[digit];
for(unsigned digit = digits10 / 2; digit--;)
result = result * 10 + digits[digit];
break;
case 2:
for(unsigned digit = digits10; digit-- > digits10 / 2;)
result = result * 10 + digits[digit];
for(unsigned digit = 0; digit < digits10 / 2; ++digit)
result = result * 10 + digits[digit];
break;
default:
abort();
}
return result;
}
int main() {
printf("%u %u %u\n", 0, 1, reverse_decimal_half(0, 1));
printf("%u %u %u\n", 12345678, 1, reverse_decimal_half(12345678, 1));
printf("%u %u %u\n", 12345678, 2, reverse_decimal_half(12345678, 2));
printf("%u %u %u\n", 123456789, 1, reverse_decimal_half(123456789, 1));
printf("%u %u %u\n", 123456789, 2, reverse_decimal_half(123456789, 2));
}
Outputs:
0 1 0
12345678 1 43215678
12345678 2 12348765
123456789 1 543216789
123456789 2 123459876
if understand this question well you need to reverse half of the decimal number. If the number has odd number of digits I assume that the first part is longer (for example 12345 - the first part is 123 the second 45). Because reverse is artihmetic the reverse the part 1 of 52001234 is 521234.
https://godbolt.org/z/frXvCM
(some numbers when reversed may wrap around - it is not checked)
int getndigits(unsigned number)
{
int ndigits = 0;
while(number)
{
ndigits++;
number /= 10;
}
return ndigits;
}
unsigned reverse(unsigned val, int ndigits)
{
unsigned left = 1, right = 1, result = 0;
while(--ndigits) left *= 10;
while(left)
{
result += (val / left) * right;
right *= 10;
val = val % left;
left /= 10;
}
return result;
}
unsigned reversehalf(unsigned val, int part)
{
int ndigits = getndigits(val);
unsigned parts[2], digits[2], left = 1;
if(ndigits < 3 || (ndigits == 3 && part == 2))
{
return val;
}
digits[0] = digits[1] = ndigits / 2;
if(digits[0] + digits[1] < ndigits) digits[0]++;
for(int dig = 0; dig < digits[1]; dig++) left *= 10;
parts[0] = val / left;
parts[1] = val % left;
parts[part - 1] = reverse(parts[part - 1], digits[part - 1]);
val = parts[0] * left + parts[1];
return val;
}
int main()
{
for(int number = 0; number < 40; number++)
{
unsigned num = rand();
printf("%u \tpart:%d\trev:%u\n", num,(number & 1) + 1,reversehalf(num, (number & 1) + 1));
}
}
My five cents.:)
#include <iostream>
int reverse_part_of_integer( int value, bool first_part = false )
{
const int Base = 10;
size_t n = 0;
int tmp = value;
do
{
++n;
} while ( tmp /= Base );
if ( first_part && n - n / 2 > 1 || !first_part && n / 2 > 1 )
{
n = n / 2;
int divider = 1;
while ( n-- ) divider *= Base;
int first_half = value / divider;
int second_half = value % divider;
int tmp = first_part ? first_half : second_half;
value = 0;
do
{
value = Base * value + tmp % Base;
} while ( tmp /= Base );
value = first_part ? value * divider + second_half
: first_half * divider +value;
}
return value;
}
int main()
{
int value = -123456789;
std::cout << "initial value: "
<< value << '\n';
std::cout << "First part reversed: "
<< reverse_part_of_integer( value, true ) << '\n';
std::cout << "Second part reversed: "
<< reverse_part_of_integer( value ) << '\n';
}
The program output is
initial value: -123456789
First part reversed: -543216789
Second part reversed: -123459876
Just for fun, a solution that counts only half the number of digits before reversing:
constexpr int base{10};
constexpr int partial_reverse(int number, int part)
{
// Split the number finding its "halfway"
int multiplier = base;
int abs_number = number < 0 ? -number : number;
int parts[2] = {0, abs_number};
while (parts[1] >= multiplier)
{
multiplier *= base;
parts[1] /= base;
}
multiplier /= base;
parts[0] = abs_number % multiplier;
// Now reverse only one of the two parts
int tmp = parts[part];
parts[part] = 0;
while (tmp)
{
parts[part] = parts[part] * base + tmp % base;
tmp /= base;
}
// Then rebuild the number
int reversed = parts[0] + multiplier * parts[1];
return number < 0 ? -reversed : reversed;
}
int main()
{
static_assert(partial_reverse(123, 0) == 123);
static_assert(partial_reverse(-123, 1) == -213);
static_assert(partial_reverse(1000, 0) == 1000);
static_assert(partial_reverse(1009, 1) == 109);
static_assert(partial_reverse(123456, 0) == 123654);
static_assert(partial_reverse(1234567, 0) == 1234765);
static_assert(partial_reverse(-1234567, 1) == -4321567);
}
I have a function that interleaves the bits of 32 bit words and returns a 64 bit result. For this simple test case, the bottom 3 bytes are correct, and the contents of the top 5 bytes are incorrect. intToBin_32 and intToBin_64 are convenience functions to see the binary representation of the arguments and return val. I've placed casts from the 32 bit type to the 64 bit type everywhere I think they are needed, but I'm still seeing this unexpected (to me, at least) behavior. Is there an implicit conversion going on here, or is there some other reason this doesn't work correctly?
#include <stdint.h>
#include <stdio.h>
struct intString_32 {char bstr [32 + 1 + 8];};
struct intString_64 { char bstr [64 + 1 + 8];};
intString_32 intToBin_32(int a)
{
intString_32 b;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 5; j++)
{
if (j != 4)
{
b.bstr[5*i + j] = * ((a & (1 << (31 - (4*i + j)))) ? "1" : "0");
}
else
{
b.bstr[5*i + j] = 0x20;
}
}
}
b.bstr[40] = * ( "\0" );
return b;
}
intString_64 intToBin_64(long long a)
{
intString_64 b;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 9; j++)
{
if (j != 8)
{
b.bstr[9*i + j] = * ((a & (1 << (63 - (8*i + j)))) ? "1" : "0");
}
else
{
b.bstr[9*i + j] = 0x20;
}
}
}
b.bstr[72] = * ( "\0" );
return b;
}
uint64_t interleaveBits(unsigned int a, unsigned int b)
{
uint64_t retVal = 0;
for (unsigned int i = 0; i < 32; i++)
{
retVal |= (uint64_t)((uint64_t)((a >> i) & 0x1)) << (2*i);
retVal |= (uint64_t)((uint64_t)((b >> i) & 0x1)) << (2*i + 1);
}
return retVal;
}
int main(int arc, char* argv)
{
unsigned int foo = 0x0004EDC7;
unsigned int bar = 0x5A5A00FF;
uint64_t bat = interleaveBits(foo, bar);
printf("foo: %s \n", intToBin_32(foo).bstr);
printf("bar: %s \n", intToBin_32(bar).bstr);
printf("bat: %s \n\n", intToBin_64(bat).bstr);
}
Through debugging I noticed it's your intToBin_64 which is wrong, to be specific, in this line:
b.bstr[9*i + j] = * ((a & (1 << (63 - (8*i + j)))) ? "1" : "0");
take a closer look on the shift:
(1 << (63 - (8*i + j)))
The literal 1 is a integer, however, shifting a integer by more than 31 bits is undefined behavior. Shift a longlong instead:
b.bstr[9*i + j] = * ((a & (1ll << (63 - (8*i + j)))) ? "1" : "0");
so the idea of my class is to take a string of numbers const char* s = "123456654987" i took each couple of number and stored them in one byte
num[0] = 12 , num[1] = 34 and so on .....
this is how i did it
unsigned char* num;
num = new unsigned char[ strlen(s)/2 + strlen(s)%2];
if(strlen(s)%2 == 1)
num[0] = s[0]-'0';
unsigned int i;
int j=strlen(s)%2;
for(i=strlen(s)%2;i<strlen(s);i+=2)
{
int left = s[i] - '0';
int right = s[i+1] - '0';
num[j] = left << 4 ;
num[j] |= right;
j++;
}
for example s[0] = 12 is represented in memory as 00010010 not as 00000110
but now that i'm trying to overload the += operator i didn't know how to proceed
my best try was this but even i know that is not going to work
int i,sum,carry=0;
for(i=this->size-1;i>=0;i--)
{
sum = ((num[i] ^ rhs.num[i]) ^ carry);
carry = ((num[i] & rhs.num[i]) | (num[i] & carry)) | (rhs.num[i] & carry);
num[i] = sum;
}
anyhelp guys
You will need to do the addition one digit (4 bit) at a time because 9+9=18 and 18 won't fit in 4 bits.
x-oring multibit digits however is not the correct operation.. the correct algorithm for sum is something like
int carry = 0;
for(int i=0; i<n; i++) {
if ((i & 1) == 0) {
int x = (a[i] & 15) + (b[i] & 15) + carry;
result[i] = (x & 15);
carry = x > 15;
} else {
int x = (a[i] >> 4) + (b[i] >> 4) + carry;
result[i] |= (x << 4);
carry = x > 15;
}
}
Working in assembler many processors supports detection of an overflow in the lower 4 bits when doing an operation and there are specific instructions to "fix" the result so that it becomes the correct two-digit binary decimal representation (e.g. x86 provides DAA instruction to fix the result of an addition).
Working at the C level however this machinery is not available.
I have been trying to carry out a conversion from CString that contains Hex string to a Byte array and have been
unsuccessful so far. I have looked on forums and none of them seem to help so far. Is there a function with just a few
lines of code to do this conversion?
My code:
BYTE abyData[8]; // BYTE = unsigned char
CString sByte = "0E00000000000400";
Expecting:
abyData[0] = 0x0E;
abyData[6] = 0x04; // etc.
You can simply gobble up two characters at a time:
unsigned int value(char c)
{
if (c >= '0' && c <= '9') { return c - '0'; }
if (c >= 'A' && c <= 'F') { return c - 'A' + 10; }
if (c >= 'a' && c <= 'f') { return c - 'a' + 10; }
return -1; // Error!
}
for (unsigned int i = 0; i != 8; ++i)
{
abyData[i] = value(sByte[2 * i]) * 16 + value(sByte[2 * i + 1]);
}
Of course 8 should be the size of your array, and you should ensure that the string is precisely twice as long. A checking version of this would make sure that each character is a valid hex digit and signal some type of error if that isn't the case.
How about something like this:
for (int i = 0; i < sizeof(abyData) && (i * 2) < sByte.GetLength(); i++)
{
char ch1 = sByte[i * 2];
char ch2 = sByte[i * 2 + 1];
int value = 0;
if (std::isdigit(ch1))
value += ch1 - '0';
else
value += (std::tolower(ch1) - 'a') + 10;
// That was the four high bits, so make them that
value <<= 4;
if (std::isdigit(ch2))
value += ch1 - '0';
else
value += (std::tolower(ch1) - 'a') + 10;
abyData[i] = value;
}
Note: The code above is not tested.
You could:
#include <stdint.h>
#include <sstream>
#include <iostream>
int main() {
unsigned char result[8];
std::stringstream ss;
ss << std::hex << "0E00000000000400";
ss >> *( reinterpret_cast<uint64_t *>( result ) );
std::cout << static_cast<int>( result[1] ) << std::endl;
}
however take care of memory management issues!!!
Plus the result is in the reverse order as you would expect, so:
result[0] = 0x00
result[1] = 0x04
...
result[7] = 0x0E
I'm working on a program in c++ to do md5 checksums. I'm doing this mainly because I think I'll learn a lot of different things about c++, checksums, OOP, and whatever else I run into.
I'm having trouble the check sums and I think the problem is in the function padbuff which does the message padding.
#include "HashMD5.h"
int leftrotate(int x, int y);
void padbuff(uchar * buffer);
//HashMD5 constructor
HashMD5::HashMD5()
{
Type = "md5";
Hash = "";
}
HashMD5::HashMD5(const char * hashfile)
{
Type = "md5";
std::ifstream filestr;
filestr.open(hashfile, std::fstream::in | std::fstream::binary);
if(filestr.fail())
{
std::cerr << "File " << hashfile << " was not opened.\n";
std::cerr << "Open failed with error ";
}
}
std::string HashMD5::GetType()
{
return this->Type;
}
std::string HashMD5::GetHash()
{
return this->Hash;
}
bool HashMD5::is_open()
{
return !((this->filestr).fail());
}
void HashMD5::CalcHash(unsigned int * hash)
{
unsigned int *r, *k;
int r2[4] = {0, 4, 9, 15};
int r3[4] = {0, 7, 12, 19};
int r4[4] = {0, 4, 9, 15};
uchar * buffer;
int bufLength = (2<<20)*8;
int f,g,a,b,c,d, temp;
int *head;
uint32_t maxint = 1<<31;
//Initialized states
unsigned int h[4]{ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476};
r = new unsigned int[64];
k = new unsigned int[64];
buffer = new uchar[bufLength];
if(r==NULL || k==NULL || buffer==NULL)
{
std::cerr << "One of the dyn alloc failed\n";
}
// r specifies the per-round shift amounts
for(int i = 0; i<16; i++)
r[i] = 7 + (5 * ((i)%4) );
for(int i = 16; i < 32; i++)
r[i] = 5 + r2[i%4];
for(int i = 32; i< 48; i++)
r[i] = 4 + r3[i%4];
for(int i = 48; i < 63; i++)
r[i] = 6 + r4[i%4];
for(int i = 0; i < 63; i++)
{
k[i] = floor( fabs( sin(i + 1)) * maxint);
}
while(!(this->filestr).eof())
{
//Read in 512 bits
(this->filestr).read((char *)buffer, bufLength-512);
padbuff(buffer);
//The 512 bits are now 16 32-bit ints
head = (int *)buffer;
for(int i = 0; i < 64; i++)
{
if(i >=0 && i <=15)
{
f = (b & c) | (~b & d);
g = i;
}
else if(i >= 16 && i <=31)
{
f = (d & b) | (~d & b);
g = (5*i +1) % 16;
}
else if(i >=32 && i<=47)
{
f = b ^ c ^ d;
g = (3*i + 5 ) % 16;
}
else
{
f = c ^ (b | ~d);
g = (7*i) % 16;
}
temp = d;
d = c;
c = b;
b = b + leftrotate((a + f + k[i] + head[g]), r[i]);
a = temp;
}
h[0] +=a;
h[1] +=b;
h[2] +=c;
h[3] +=d;
}
delete[] r;
delete[] k;
hash = h;
}
int leftrotate(int x, int y)
{
return(x<<y) | (x >> (32 -y));
}
void padbuff(uchar* buffer)
{
int lack;
int length = strlen((char *)buffer);
uint64_t mes_size = length % UINT64_MAX;
if((lack = (112 - (length % 128) ))>0)
{
*(buffer + length) = ('\0'+1 ) << 3;
memset((buffer + length + 1),0x0,lack);
memcpy((void*)(buffer+112),(void *)&mes_size, 64);
}
}
In my test program I run this on the an empty message. Thus length in padbuff is 0. Then when I do *(buffer + length) = ('\0'+1 ) << 3;, I'm trying to pad the message with a 1. In the Netbeans debugger I cast buffer as a uint64_t and it says buffer=8. I was trying to put a 1 bit in the most significant spot of buffer so my cast should have been UINT64_MAX. Its not, so I'm confused about how my padding code works. Can someone tell me what I'm doing and what I'm supposed to do in padbuff? Thanks, and I apologize for the long freaking question.
Just to be clear about what the padding is supposed to be doing, here is the padding excerpt from Wikipedia:
The message is padded so that its length is divisible by 512. The padding works as follows: first a single bit, 1, is appended to the end of the message. This is followed by as many zeros as are required to bring the length of the message up to 64 bits fewer than a multiple of 512. The remaining bits are filled up with 64 bits representing the length of the original message, modulo 264.
I'm mainly looking for help for padbuff, but since I'm trying to learn all comments are appreciated.
The first question is what you did:
length % UINT64_MAX doesn't make sense at all because length is in bytes and MAX is the value you can store in UINT64.
You thought that putting 1 bit in the most significant bit would give the maximum value. In fact, you need to put 1 in all bits to get it.
You shift 1 by 3. It's only half the length of the byte.
The byte pointed by buffer is the least significant in little endian. (I assume you have little endian since the debugger showed 8).
The second question how it should work.
I don't know what exactly padbuff should do but if you want to pad and get UINT64_MAX, you need something like this:
int length = strlen((char *)buffer);
int len_of_padding = sizeof(uint64_t) - length % sizeof(uint64_t);
if(len_of_padding > 0)
{
memset((void*)(buffer + length), 0xFF, len_of_padding);
}
You worked with the length of two uint64 values. May be you wanted to zero the next one:
uint64_t *after = (uint64_t*)(buffer + length + len_of_padding);
*after = 0;