Briefly: Question is related to bitwise operations on hex - language C ; O.S: linux
I would simply like to do some bitwise operations on a "long" hex string.
I tried the following:
First try:
I cannot use the following because of overflow:
long t1 = 0xabefffcccaadddddffff;
and t2 = 0xdeeefffffccccaaadacd;
Second try: Does not work because abcdef are interpreted as string instead of hex
char* t1 = "abefffcccaadddddffff";
char* t2 = "deeefffffccccaaadacd";
int len = strlen(t1);
for (int i = 0; i < len; i++ )
{
char exor = *(t1 + i) ^ *(t2 + i);
printf("%x", exor);
}
Could someone please let me know how to do this? thx
Bitwise operations are usually very easily extended to larger numbers.
The best way to do this is to split them up into 4 or 8 byte sequences, and store them as an array of uints. In this case you need at least 80 bits for those particular strings.
For AND it is pretty simple, something like:
unsigned int A[3] = { 0xabef, 0xffcccaad, 0xddddffff };
unsigned int B[3] = { 0xdeee, 0xfffffccc, 0xcaaadacd };
unsigned int R[3] = { 0 };
for (int b = 0; b < 3; b++) {
R[b] = A[b] & B[b];
}
A more full example including scanning hex strings and printing them:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef unsigned int uint;
void long_Print(int size, const uint a[]) {
printf("0x");
for (int i = 0; i < size; i++) {
printf("%x", a[i]);
}
}
void long_AND(int size, const uint a[], const uint b[], uint r[]) {
for (int i = 0; i < size; i++) {
r[i] = a[i] & b[i];
}
}
// Reads a long hex string and fills an array. Returns the number of elements filled.
int long_Scan(int size, const char* str, uint r[]) {
int len = strlen(str);
int ri = size;
for (const char* here = &str[len]; here != str; here -= 8) {
if (here < str) {
char* tmp = (char*)malloc(4);
tmp[0] = '%';
tmp[1] = (char)(str - here + '0');
tmp[2] = 'x';
tmp[3] = '\0';
sscanf(str, tmp, &r[ri--]);
free(tmp);
break;
}
else {
sscanf(here, "%8x", &r[ri--]);
}
}
for (; ri >= 0; ri--) {
r[ri] == 0;
}
return size - ri;
}
int main(int argc, char* argv[])
{
uint A[3] = { 0 };
uint B[3] = { 0 };
uint R[3] = { 0 };
long_Scan(3, "abefffcccaadddddffff", A);
long_Scan(3, "deeefffffccccaaadacd", B);
long_Print(3, A);
puts("\nAND");
long_Print(3, B);
puts("\n=");
long_AND(3, A, B, R);
long_Print(3, R);
getchar();
return 0;
}
You'll certainly need to use a library that can handle arbitrarily long integers. Consider using libgmp: http://gmplib.org/
Before you can do any sort of bitwise operations, you need to be working with integers. "abeffccc" is not an integer. It is a string. You need to use something like strtol
to first convert the string to an integer.
If your values are too big to fit into a 64-bit long long int (0xFFFFFFFF,FFFFFFFF) then you'll need to use a Big Integer library, or something similar, to support arbitrarily large values. As H2CO3 mentioned, libgmp is an excellent choice for large numbers in C.
Instead of using unsigned long directly, you could try using an array of unsigned int. Each unsigned int holds 32 bits, or 8 hex digits. You would therefore have to chop-up your constant into chunks of 8 hex digits each:
unsigned int t1[3] = { 0xabef , 0xffcccaad , 0xddddffff };
Note that for sanity, you should store them in reverse order so that the first entry of t1 contains the lowest-order bits.
Related
I would like to convert a very long (arbitrary length, possibly 1000 characters long; university assignment) string into binary. How should I approach this problem? I have thought about it for a while, but I just can't seem to think of anything viable.
The string will be passed to me as const char *str. I want to read the number, which will be in Base 10, and convert it into binary.
Should I read certain number of least significant numbers and store them in unsigned long long int, and then work from there? Is there a better solution? I don't know how the method I suggested would pan out. I wanted to know if there's a better/easier way to do it.
Thank you.
Assuming your input is too large for the biggest integer type, you have to convert it to a unlimited size integer. For this purpose you can use gmplib. If you are not allowed to use external libraries, you can use a different approach:
is your string divisible by two (look at the last digit)?
if yes, write 0 to left side of your output
else, write 1 to left side of your output
divide the string by 2 (every digit)
repeat while string is not filled with 0
I am going to edit this answer, as soon as I wrote the code.
Here you go:
#include<stdbool.h>
#include<stdlib.h>
#include<memory.h>
#include<stdio.h>
typedef struct char_queue {
unsigned int len;
unsigned int capacity;
char* data;
} char_queue;
char_queue init_char_queue() {
return (char_queue) {
0,
4096,
malloc(4096)
};
}
void enqueue(char_queue* queue, char val) {
if (queue->len == queue->capacity) {
char* new_queue_data = malloc(queue->capacity + 4096);
memmove(new_queue_data, queue->data, queue->capacity);
free(queue->data);
queue->data = new_queue_data;
}
queue->len++;
queue->data[queue->capacity - queue->len] = val;
}
char* queue_get_arr(char_queue* queue) {
char* output = malloc(queue->len);
memcpy(output, &queue->data[queue->capacity - queue->len], queue->len);
return output;
}
void free_char_queue(char_queue* queue) {
if (queue->data) free(queue->data);
}
void convert_to_digit_arr(char* input, unsigned int len) {
for (unsigned int i = 0; i < len; i++) {
input[i] = input[i] - '0'; // '5' - '0' = 5
}
}
bool is_null(char* input, unsigned int len) {
for (unsigned int i = 0; i < len; i++) {
if (input[i] != 0) return false;
}
return true;
}
bool divisible_by_two(char* digit_arr, unsigned int len) {
return digit_arr[len - 1] % 2 == 0;
}
void divide_by_two(char* digit_arr, unsigned int len) {
for (unsigned int i = 0; i < len; i++) {
bool is_odd = digit_arr[i] % 2 == 1;
digit_arr[i] /= 2;
if (is_odd && i + 1 < len) { // and is not last (right) digit
digit_arr[i + 1] += 10;
}
}
}
int main(int argc, char** argv) {
for (int i = 1; i < argc; i++) {
unsigned int input_len = strlen(argv[i]);
char* input = malloc(input_len + 1);
strcpy(input, argv[i]);
convert_to_digit_arr(input, input_len);
char_queue queue = init_char_queue();
enqueue(&queue, 0); // null terminator to use the queue content as a string
while (!is_null(input, input_len)) {
enqueue(&queue, divisible_by_two(input, input_len) ? '0' : '1');
divide_by_two(input, input_len);
}
free(input);
char* output = queue_get_arr(&queue);
printf("%s\n", output);
free(output);
free_char_queue(&queue);
}
}
This is not the fastest approach, but it is very simple. Also feel free to optimize it.
How do I convert a really long string (as decimal characters) to binary?
Let us look at printing this.
print2(s)
If the decimal string is at least "2",
__ Divide the decimal string by 2 and notice its remainder.
__ Recursively call print2(s)
__ Print the remainder.
Else print the string.
Example code:
#include <stdio.h>
unsigned decimal_string_divide(char *dividend, unsigned divisor) {
// Remove a potential leading '0'
if (*dividend == '0') {
memmove(dividend, dividend+1, strlen(dividend));
}
// "divide", like we learned in grade school.
unsigned remainder = 0;
while (*dividend) {
unsigned sum = remainder*10 + (*dividend - '0');
remainder = sum%divisor;
*dividend = sum/divisor + '0';
dividend++;
}
return remainder;
}
void decimal_string_print_binary(char *dividend) {
//printf("<%s>\n", dividend); fflush(stdout);
if (dividend[0]) {
// If at least 2 digits or at least "2"
if (dividend[1] || (dividend[0] >= '2')) {
unsigned bit = decimal_string_divide(dividend, 2);
decimal_string_print_binary(dividend);
printf("%c", bit + '0');
} else {
printf("%c", *dividend);
}
}
}
void decimal_string_print_2(const char *dividend) {
printf("%-25s", dividend);
size_t sz = strlen(dividend) + 1;
char buf[sz]; // Use a VLA or allocate memory
strcpy(buf, dividend);
decimal_string_print_binary(buf);
printf("\n");
}
Test
int main(void) {
decimal_string_print_2("0");
decimal_string_print_2("1");
decimal_string_print_2("42");
decimal_string_print_2("8675309");
decimal_string_print_2("18446744073709551615");
}
Output
0 0
1 1
42 101010
8675309 100001000101111111101101
18446744073709551615 1111111111111111111111111111111111111111111111111111111111111111
To instead convert the string from decimal form into a binary string, allocate sufficient buffer (about log10(2) times string length) and instead of printing above, save to the buffer. Left for OP to do.
I am suggesting a better approach. whereby any arguments passed to a function that is not intended to be mutated, be received as a "const", and a local pointer be used to access the data of this "const".
IE:
void to_binary(const char *str) {
char *ptr = str;
...
Then use ptr.
I know that in this case, my argument is purely trivial and academic, but it is a good practice to get used to and may save you many headaches in the future.
Also, when dealing with binary data, use "unsigned char", to ensure that no type conversions are used. You will need bit 7 if the data is not ASCII or alike.
unsigned long long int power(int base, unsigned int exponent)
{
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
I am working on a program where I need to take in a string of 8 characters (e.g. "I want t") then convert this into a long long int in the pack function. I have the pack function working fine.
unsigned long long int pack(char unpack[])
{
/*converting string to long long int here
didn't post code because its large*/
}
After I enter "I want t" I get "Value in Decimal = 5269342824372117620" and then I send the decimal to the unpack function. So I need to convert 5269342824372117620 back into "I want t". I tried bit manipulation which was unsuccessful any help would be greatly appreciated.
void unpack(long long int pack)
{
long long int bin;
char convert[100];
for(int i = 63, j = 0, k = 0; i >= 0; i--,j++)
{
if((pack & (1 << i)) != 0)
bin += power(2,j);
if(j % 8 == 0)
{
convert[k] = (char)bin;
bin = 0;
k++;
j = -1;
}
}
printf("String: %s\n", convert);
}
A simple solution for your problem is to consider the characters in the string to be digits in a large base that encompasses all possible values. For example base64 encoding can convert strings of 8 characters to 48-bit numbers, but you can only use a subset of at most 64 different characters in the source string.
To convert any 8 byte string into a number, you must use a base of at least 256.
Given your extra input, After I enter "I want t" I get "Value in Decimal = 5269342824372117620", and since 5269342824372117620 == 0x492077616e742074, you do indeed use base 256, big-endian order and ASCII encoding for the characters.
Here is a simple portable pack function for this method:
unsigned long long pack(const char *s) {
unsigned long long x = 0;
int i;
for (i = 0; i < 8; i++) {
x = x * 256 + (unsigned char)s[i];
}
return x;
}
The unpack function is easy to derive: compute the remainders of divisions in the reverse order:
char *unpack(char *dest, unsigned long long x) {
/* dest is assumed to have a length of at least 9 */
int i;
for (i = 8; i-- > 0; ) {
s[i] = x % 256;
x = x / 256;
}
s[8] = '\0'; /* set the null terminator */
return s;
}
For a potentially faster but less portable solution, you could use this, but you would get a different conversion on little-endian systems such as current Macs and PCs:
#include <string.h>
unsigned long long pack(const char *s) {
unsigned long long x;
memcpy(&x, s, 8);
return x;
}
char *unpack(char *s, unsigned long long x) {
memcpy(s, &x, 8);
s[8] = '\0';
return s;
}
This question already has answers here:
Conversion of Char to Binary in C
(3 answers)
Closed 9 years ago.
I want a really basic way to print out the binary representation of a char. I can't seem to find any example code anywhere.
I assumed you could do it in a few lines but everything I find is overly long and complex using lots of functions I haven't used before. atoi comes up a lot but it's not standard.
Is there a simple function or simple way of writing a function to take a char variable and then print out a binary representation?
Eg: char 'x' is the argument taken in by the function and "x is 0111 1000" is printed out.
It's for a school assignment where I must take user input of a string and print out the string in binary. I just need to get the basics of converting a char to binary but i'm struggling at the moment.
What you'd want to do is use bitwise operators to mask the bits one by one and print them to the standard output.
A char in C is guaranteed to be 1 byte, so loop to 8.
Within each iteration, mask off the highest order bit.
Once you have it, just print it to standard output.
Here is a quick stab which hopefully makes sense...
main() {
char a = 10;
int i;
for (i = 0; i < 8; i++) {
printf("%d", !!((a << i) & 0x80));
}
printf("\n");
return 0;
}
CodePad.
In order to get the bit, I shift to the left to get the numbered bit (highest to lowest so printing it is easy) and then mask it off. I then translate it to 0 or 1 with !!.
you can use this method
const char *byte_to_binary(int x)
{
static char b[9];
b[0] = '\0';
int z;
for (z = 128; z > 0; z >>= 1)
{
strcat(b, ((x & z) == z) ? "1" : "0");
}
return b;
}
to get the binary representation and print with it
for example
printf("%s\n", byte_to_binary(15));
void printBits(size_t const size, void const * const ptr)
{
unsigned char *b = (unsigned char*) ptr;
unsigned char byte;
int i, j;
for (i=size-1;i>=0;i--)
{
for (j=7;j>=0;j--)
{
byte = b[i] & (1<<j);
byte >>= j;
printf("%u", byte);
}
}
puts("");
}
int main(int argv, char* argc[])
{
int i = 23;
uint ui = UINT_MAX;
float f = 23.45f;
printBits(sizeof(i), &i);
printBits(sizeof(ui), &ui);
printBits(sizeof(f), &f);
return 0;
}
Try this:-
#include <limits.h>
char *chartobin ( unsigned char c )
{
static char bin[CHAR_BIT + 1] = {0};
int i;
for( i = CHAR_BIT - 1; i >= 0; i-- )
{
bin[i] = (c % 2) + '0';
c /= 2;
}
return bin;
}
I have a string (unsigned char) and i want to fill it with only hex characters.
my code is
unsigned char str[STR_LEN] = {0};
for(i = 0;i<STR_LEN;i++) {
sprintf(str[i],"%x",rand()%16);
}
Of course, when running this I get segfaulted
string is an array of char-s not unsigned char-s
you are using str[i] (which is of type unsigned char) as a 1st argument to sprintf, but it requires type char * (pointer).
This should be a little better:
char str[STR_LEN + 1];
for(i = 0; i < STR_LEN; i++) {
sprintf(str + i, "%x", rand() % 16);
}
The first argument to sprintf() should be a char*, but str[i] is a char: this is the cause of the segmentation fault. The compiler should have emitted a warning about this. gcc main.c, without specifying a high warning level, emitted the following:
warning: passing argument 1 of sprintf makes pointer from integer without a cast
A hex representation of a character can be 1 or 2 characters (9 or AB for example). For formatting, set the precision to 2 and the fill character to 0. Also need to add one character for the terminating null to str and set the step of the for loop to 2 instead of 1 (to prevent overwriting previous value):
unsigned char str[STR_LEN + 1] = {0};
int i;
for (i = 0; i < STR_LEN; i += 2)
{
sprintf(&str[i], "%02X", rand() % 16);
}
You could try something like this:
#include <stdio.h>
#include <stdlib.h>
#define STR_LEN 20
int main(void)
{
unsigned char str[STR_LEN + 1] = {0};
const char *hex_digits = "0123456789ABCDEF";
int i;
for( i = 0 ; i < STR_LEN; i++ ) {
str[i] = hex_digits[ ( rand() % 16 ) ];
}
printf( "%s\n", str );
return 0;
}
There are several unclarities and problems in your code. I interpret "hex character" to mean "hex digit", i.e. a symbol from {0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}, not "the hexadecimal value of an ascii character's code point". This might or might not be what you meant.
This should do it:
void hex_fill(char *buf, size_t max)
{
static const char hexdigit[16] = "0123456789abcdef";
if(max < 1)
return;
--max;
for(i = 0; i < max; ++i)
buf[i] = hexdigit[rand() % sizeof hexdigit];
buf[max] = '\0';
}
The above will always 0-terminate the string, so there's no requirement that you do so in advance. It will properly handle all buffer sizes.
My variation on some of answers below; note the time seeded rand function and instead of a char using a const size, I use a vector that is then converted to a string array.
Boost variate generator docs
std::string GetRandomHexString(unsigned int count)
{
std::vector<char> charVect = std::vector<char>(count);
//Rand generator
typedef boost::random::mt19937 RNGType;
RNGType rng(std::time(nullptr) + (unsigned int)clock());
//seeding rng
uniform_int<> range(0, 15); //Setting min max
boost::variate_generator<RNGType, boost::uniform_int<> >generate(rng, range); //Creating our generator
//Explicit chars to sample from
const char hexChars[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
//
for (int i = 0; i < count; i++)
{
charVect[i] = hexChars[generate()];
}
//
return std::string(charVect.begin(), charVect.end());;
}
Examples (count = 32):
1B62C49C416A623398B89A55EBD3E9AC
26CFD2D1C14B9F475BF99E4D537E2283
B8709C1E87F673957927A7F752D0B82A
DFED20E9C957C4EEBF4661E7F7A58460
4F86A631AE5A05467BA416C4854609F8
I'm representing an infinitely precise integer as an array of unsigned ints for processing on a GPU. For debugging purposes I'd like to print the base 10 representation of one of these numbers, but am having difficulty wrapping my head around it. Here's what I'd like to do:
//the number 4*(2^32)^2+5*(2^32)^1+6*(2^32)^0
unsigned int aNumber[3] = {4,5,6};
char base10TextRepresentation[50];
convertBase2To32ToBase10Text(aNumber,base10TextRepresentation);
Any suggestions on how to approach this problem?
Edit: Here's a complete implementation thanks to drhirsch
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#define SIZE 4
uint32_t divideBy10(uint32_t * number) {
uint32_t r = 0;
uint32_t d;
for (int i=0; i<SIZE; ++i) {
d = (number[i] + r*0x100000000) / 10;
r = (number[i] + r*0x100000000) % 10;
number[i] = d;
}
return r;
}
int zero(uint32_t* number) {
for (int i=0; i<SIZE; ++i) {
if (number[i] != 0) {
return 0;
}
}
return 1;
}
void swap(char *a, char *b) {
char tmp = *a;
*a = *b;
*b = tmp;
}
void reverse(char *str) {
int x = strlen(str);
for (int y = 0; y < x/2; y++) {
swap(&str[y],&str[x-y-1]);
}
}
void convertTo10Text(uint32_t* number, char* buf) {
int n = 0;
do {
int digit = divideBy10(number);
buf[n++] = digit + '0';
} while(!zero(number));
buf[n] = '\0';
reverse(buf);
}
int main(int argc, char** argv) {
uint32_t aNumber[SIZE] = {0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
uint32_t bNumber[4] = {1,0,0,0};
char base10TextRepresentation[50];
convertTo10Text(aNumber, base10TextRepresentation);
printf("%s\n",base10TextRepresentation);
convertTo10Text(bNumber, base10TextRepresentation);
printf("%s\n",base10TextRepresentation);
}
If you have access to 64 bit arithmetic, it is easier. I would do something along the line of:
int32_t divideBy10(int32_t* number) {
uint32_t r = 0;
uint32_t d;
for (int i=0; i<SIZE; ++i) {
d = (number[i] + r*0x100000000) / 10;
r = (number[i] + r*0x100000000) % 10;
number[i] = d;
number[i] = r;
}
void convertTo10Text(int32_t* number, char* buf) {
do {
digit = divideBy10(number);
*buf++ = digit + '0';
} while (!isEqual(number, zero));
reverse(buf);
}
isEqual() and reverse() left to be implemented. divideBy10 divides by 10 and returns the remainder.
Fundamentally you need classic decimal printing using digit production by dividing your number by ten (in your base 2^32) repeatedly and using the remainder as digits. You may not have a divide by (anything, let alone) 10 routine, which is probably the key source of your problem.
If you are working in C or C++, you can get a complete infinite precision arithmetic package from GNU Bignum package. Most other widely used languages have similar packages available.
Of course, if you have too much free time, you can always implement multiprecision division yourself. You're already borrowing terminology from Knuth; he also supplies the multiprecision algorithms in Seminumerical Algorithms.
If it is .NET, take a look at this implementation of a BigInteger class.
How about using long doubles? Then you get 80bits in the mantissa, but I guess that the accuracy is lost when using floating point numbers.