Storing a Binary Value into an unsigned int array - c

I've been having some trouble storing a binary value into an unsigned int array. I was trying to pass through the binary representation as a char array however it's not working as I had hoped. What I was doing was going through the char array using a while loop and assigning each number to an element to the unsigned int array but that is completely wrong. I just pretty much want to know how to store a binary value into an unsigned int. How do I show zeros in front? I've tried putting in the array just the binary value without 0s at the front but that wasn't working. Could I convert the binary to int value and then convert it back at print time?
Here is the basic code for the function
void setstring(unsigned int array[10], char *bitString) {
len=strlen(bitString);
for (int i=1; i<=10; i++) {
for (int p=1; d%32!=0; d++) {
array[10-i]=bitString[len-];
}
}
}
The printing is just meant to print the bitString or the array but at the moment nothing is printing at all. The print is simply a for loop which iterates through the unsigned int array.

You might be looking for a function to set particular bits of an unsigned char variable.
Try using this to set bits
void setBit(unsigned char *target, int pos)
{
//pos must be < sizeof(unsigned char)
unsigned char mask=1<<pos;
*target = *target | mask;
}
And this to unset bits
void unsetBit(unsigned char *target, int pos)
{
unsigned char mask=~(1<<pos);
*target = *target & mask;
}
Note that pos begins from 0.
You could use these functions for displaying the bits:
int getBit(unsigned char target, int pos)
{
target = target>>pos;
return target & 1;
}
void printBits(unsigned char target)
{
int i;
for(i=sizeof(target)*8-1; i>=0; --i)
{
printf("%d", getBit(target, i));
}
}
In these functions the target variable is passed by reference.
Example:
unsigned char a=0;
setBit(&a, 0);
setBit(&a, 1);
setBit(&a, 6);
printf("\nBit pattern is: ");
printBits(a);
printf(". Value is %d.", a);
would print
Bit pattern is: 01000011. Value is 67.
Further
unsetBit(&a, 1);
printf("\nBit pattern is: ");
printBits(a);
printf(". Value is %d.", a);
would give
Bit pattern is: 01000001. Value is 65.
EDIT: This is a good place to learn bit manipulation.

Here is your (set) of functions :
int binary_string_to_integer(const char *str, unsigned int *vl)
{
unsigned int value = 0;
int result = 0;
if (str == NULL || vl == NULL || !strlen(str)) result = -1;
if (!result)
{
while (!result && *str)
{
if (*str != '1' && *str != '0')
{
result = -1;
}
value <<= 1;
value += (*str++ == '1');
}
}
if (!result) *vl = value;
return result;
}
int binary_string_to_integer_array_of_0_or_1(const char *str, int *vl, int skipzeroes)
{
int result = 0;
if (str == NULL || vl == NULL || !strlen(str)) result = -1;
if (!result)
{
while (*str)
{
if (*str != '1' && *str != '0')
{
result = -1;
break;
}
if (skipzeroes && !result && *str == '0')
{
str++;
continue;
}
*(vl + result++) = (*str++ == '1');
}
}
return result;
}
char *reverse(char *str)
{
char tmp;
size_t len;
if (str != NULL)
{
len = strlen(str);
for (size_t i = 0; i < len / 2; i++)
{
tmp = *(str + i);
*(str + i) = *(str + len - i - 1);
*(str + len - i - 1) = tmp;
}
}
return str;
}
char *uint_to_binary_string(unsigned int vl, char *buff)
{
char *ptr = buff;
if (buff != NULL)
{
while (vl)
{
*ptr++ = '0' + (vl & 1);
vl >>= 1;
}
}
*ptr = 0;
return reverse(buff);
}

Related

Decimal to octal converter in c [duplicate]

I can use the strtol function for turning a base36 based value (saved as a string) into a long int:
long int val = strtol("ABCZX123", 0, 36);
Is there a standard function that allows the inversion of this? That is, to convert a long int val variable into a base36 string, to obtain "ABCZX123" again?
There's no standard function for this. You'll need to write your own one.
Usage example: https://godbolt.org/z/MhRcNA
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char *reverse(char *str)
{
char *end = str;
char *start = str;
if(!str || !*str) return str;
while(*(end + 1)) end++;
while(end > start)
{
int ch = *end;
*end-- = *start;
*start++ = ch;
}
return str;
}
char *tostring(char *buff, long long num, int base)
{
int sign = num < 0;
char *savedbuff = buff;
if(base < 2 || base >= sizeof(digits)) return NULL;
if(buff)
{
do
{
*buff++ = digits[abs(num % base)];
num /= base;
}while(num);
if(sign)
{
*buff++ = '-';
}
*buff = 0;
reverse(savedbuff);
}
return savedbuff;
}
One of the missing attributes of this "Convert long integer to base 36 string" is string management.
The below suffers from a potential buffer overflow when destination is too small.
char *long_to_string(char *destination, long num, int base);
(Assuming 32-bit long) Consider the overflow of below as the resultant string should be "-10000000000000000000000000000000", which needs 34 bytes to encode the string.
char buffer[33]; // Too small
long_to_string(buffer, LONG_MIN, 2); // Oops!
An alternative would pass in the buffer size and then provide some sort of error signaling when the buffer is too small.
char* longtostr(char *dest, size_t size, long a, int base)
Since C99, code instead could use a compound literal to provide the needed space - without calling code trying to compute the needed size nor explicitly allocate the buffer.
The returned string pointer from TO_BASE(long x, int base) is valid until the end of the block.
#include <assert.h>
#include <limits.h>
#define TO_BASE_N (sizeof(long)*CHAR_BIT + 2)
// v. compound literal .v
#define TO_BASE(x, b) my_to_base((char [TO_BASE_N]){""}, (x), (b))
char *my_to_base(char *buf, long a, int base) {
assert(base >= 2 && base <= 36);
long i = a < 0 ? a : -a; // use the negative side - this handle _MIN, _MAX nicely
char *s = &buf[TO_BASE_N - 1];
*s = '\0';
do {
s--;
*s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[-(i % base)];
i /= base;
} while (i);
if (a < 0) {
s--;
*s = '-';
}
// Could add memmove here to move the used buffer to the beginning
return s;
}
#include <limits.h>
#include <stdio.h>
int main(void) {
long ip1 = 0x01020304;
long ip2 = 0x05060708;
long ip3 = LONG_MIN;
printf("%s %s\n", TO_BASE(ip1, 16), TO_BASE(ip2, 16), TO_BASE(ip3, 16));
printf("%s %s\n", TO_BASE(ip1, 2), TO_BASE(ip2, 2), TO_BASE(ip3, 2));
puts(TO_BASE(ip1, 8));
puts(TO_BASE(ip1, 36));
puts(TO_BASE(ip3, 10));
}
Here is another option with no need for source array of charaters, but less portable since not all character encodings have contiguous alphabetic characters, for example EBCDIC. Test HERE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
char get_chars(long long value)
{
if (value >= 0 && value <= 9)
return value + '0';
else
return value - 10 + 'A';
}
void reverse_string(char *str)
{
int len = strlen(str);
for (int i = 0; i < len/2; i++)
{
char temp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = temp;
}
}
char* convert_to_base(char *res, int base, long long input)
{
bool flag = 0;
int index = 0;
if(input < 0){
input = llabs(input);
flag = 1;
}
else if(input == 0){
res[index++] = '0';
res[index] = '\0';
return res;
}
while(input > 0)
{
res[index++] = get_chars(input % base);
input /= base;
}
if(flag){
res[index++] = '-';
}
res[index] = '\0';
reverse_string(res);
return res;
}
int main() {
long long input = 0;
printf("** Integer to Base-36 **\n ");
printf("Enter a valid number: ");
scanf("%lld", &input);
if(input >= LLONG_MAX && input <= LLONG_MIN){
printf("Invalid number");
return 0;
}
int base = 36;
char res[100];
printf("%lld -> %s\n", input, convert_to_base(res, base, input));
return 0;
}

Inserting a character into a char array

I have a char array containing a number.
char number[] = "12000000"
I need to have a function to insert a divider in every 3 digits. Like:
char result[] = "12,000,000"
My function accepts the number as a char pointer and it needs to return result as a char pointer too.
char* insert_divider(char* number) {
some magic;
return result;
}
I have no idea of working with pointers. Thanks.
Here you have a function that adds char c every num characters starting from the end. You need to make sure that the string buffer is long enough to accommodate the amended string.
char *addEvery(char *str, char c, unsigned num)
{
char *end = str;
if(str && *str && num)
{
size_t count = 1;
while(*(end)) end++;
while(end != str)
{
end--;
count++;
if(!(count % (num + 1)) && str != end)
{
memmove(end + 1, end, count);
*end = c;
count++;
}
}
}
return str;
}
int main(void)
{
char str[100] = "120000000000";
printf("%s", addEvery(str,',',3));
}
I came up with this piece of code:
char *result;
result = (char*) malloc(15);
int len= strlen(input);
uint8_t cursor= 0;
for(int i = 0; i < len; i++) {
if ((len- i) > 0 && (len- i) % 3 == 0) {
result[i + cursor] = ',';
cursor++;
}
result[i + cursor] = input[i];
}
result[len+ cursor] = '\0';
Thanks everyone for help and advice.
Here is another way to do it:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* insert_divider(char* number, size_t length) {
int j = length + length/3; // every 3 digits a ',' will be inserted
char *out = (char*)malloc(j + 1);
out[j--] = '\0';
for (int i = length - 1, k = 1; i >= 0; i--, k++) {
out[j--] = number[i];
if ((k%3) == 0) {
out[j--] = ',';
}
}
return out;
}
int main(){
char number[] = "12000000";
char *outNumber = insert_divider(number, strlen(number));
printf("%s", outNumber);
free(outNumber);
return 0;
}

I can not use free() on char pointer returned from a function

I cannot clear the str variable that is allocated in the ft_itoa_base() function.
Error pointer being freed was not allocated.
void work_ptr_accuracy(t_args *args, char **return_str, \
va_list *arg)
{
int size_accuracy;
char *str_tmp;
char *str;
unsigned long long int n;
str_tmp = NULL;
str = NULL;
if (args->accuracy != -1)
{
size_accuracy = args->accuracy;
n = va_arg(*arg, unsigned long long int);
str = ft_itoa_base(n, 16, LOWERCASE);
*return_str = ft_substr(str, 0, size_accuracy);
free(str);
str_tmp = ft_strjoin("0x", *return_str);
free(*return_str);
*return_str = str_tmp;
}
}
this is ft_itoa_base()
char *ft_itoa_base(unsigned long long int value, \
unsigned long long int base, int regist)
{
int len;
unsigned long long int digit;
char *return_str;
char *base_tmp;
base_tmp = get_register(regist);
if (value == 0)
return ("0");
len = 0;
digit = value;
ft_baselen(digit, base, &len);
if (!(return_str = (char *)malloc(sizeof(char) * (len + 1))))
return (NULL);
return_str[len] = '\0';
while (digit)
{
return_str[--len] = base_tmp[digit % base];
digit /= base;
}
if (value < 0 && base == 10)
return_str[0] = '-';
return (return_str);
}
this is my ft_substr()
/*
** Function: char *ft_substr
**
** Description: Allocates (with malloc(3)) and returns a substring
** from the string ’s’.
** The substring begins at index ’start’ and is of
** maximum size ’len’.
*/
char *ft_substr(const char *s, unsigned int start, size_t len)
{
unsigned int i;
unsigned int j;
char *str;
i = 0;
j = 0;
if (!s)
return (NULL);
if (start >= ft_strlen(s))
{
if (!(str = (char *)malloc(1)))
return (NULL);
str[0] = '\0';
return (str);
}
while (s[i] != s[start])
i++;
if (!(str = (char *)malloc((len * sizeof(char)) + 1)))
return (NULL);
while (j < len && s[i])
str[j++] = s[i++];
str[j] = '\0';
return (str);
}
Bad design of ft_itoa_base. return ("0") returns a pointer to statically allocated array consisting of two chars ( '0' and '\0'). That one cannot be free-ed.
Compare to this implementation by lwang <marvin#42.fr>
#include <stdlib.h>
#include <stdio.h>
int ft_abs(int nb)
{
if (nb < 0)
nb = -nb;
return (nb);
}
char *ft_itoa_base(int value, int base)
{
char *str;
int size;
char *tab;
int flag;
int tmp;
flag = 0;
size = 0;
tab = "0123456789ABCDEF";
if (base < 2 || base > 16)
return (0);
if (value < 0 && base == 10)
flag = 1;
tmp = value;
while (tmp /= base)
size++;
size = size + flag + 1;
str = (char *)malloc(sizeof(char) * size + 1);
str[size] = '\0';
if (flag == 1)
str[0] = '-';
while (size > flag)
{
str[size - 1] = tab[ft_abs(value % base)];
size--;
value /=base;
}
return (str);
}

Convert long integer(decimal) to base 36 string (strtol inverted function in C)

I can use the strtol function for turning a base36 based value (saved as a string) into a long int:
long int val = strtol("ABCZX123", 0, 36);
Is there a standard function that allows the inversion of this? That is, to convert a long int val variable into a base36 string, to obtain "ABCZX123" again?
There's no standard function for this. You'll need to write your own one.
Usage example: https://godbolt.org/z/MhRcNA
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char *reverse(char *str)
{
char *end = str;
char *start = str;
if(!str || !*str) return str;
while(*(end + 1)) end++;
while(end > start)
{
int ch = *end;
*end-- = *start;
*start++ = ch;
}
return str;
}
char *tostring(char *buff, long long num, int base)
{
int sign = num < 0;
char *savedbuff = buff;
if(base < 2 || base >= sizeof(digits)) return NULL;
if(buff)
{
do
{
*buff++ = digits[abs(num % base)];
num /= base;
}while(num);
if(sign)
{
*buff++ = '-';
}
*buff = 0;
reverse(savedbuff);
}
return savedbuff;
}
One of the missing attributes of this "Convert long integer to base 36 string" is string management.
The below suffers from a potential buffer overflow when destination is too small.
char *long_to_string(char *destination, long num, int base);
(Assuming 32-bit long) Consider the overflow of below as the resultant string should be "-10000000000000000000000000000000", which needs 34 bytes to encode the string.
char buffer[33]; // Too small
long_to_string(buffer, LONG_MIN, 2); // Oops!
An alternative would pass in the buffer size and then provide some sort of error signaling when the buffer is too small.
char* longtostr(char *dest, size_t size, long a, int base)
Since C99, code instead could use a compound literal to provide the needed space - without calling code trying to compute the needed size nor explicitly allocate the buffer.
The returned string pointer from TO_BASE(long x, int base) is valid until the end of the block.
#include <assert.h>
#include <limits.h>
#define TO_BASE_N (sizeof(long)*CHAR_BIT + 2)
// v. compound literal .v
#define TO_BASE(x, b) my_to_base((char [TO_BASE_N]){""}, (x), (b))
char *my_to_base(char *buf, long a, int base) {
assert(base >= 2 && base <= 36);
long i = a < 0 ? a : -a; // use the negative side - this handle _MIN, _MAX nicely
char *s = &buf[TO_BASE_N - 1];
*s = '\0';
do {
s--;
*s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[-(i % base)];
i /= base;
} while (i);
if (a < 0) {
s--;
*s = '-';
}
// Could add memmove here to move the used buffer to the beginning
return s;
}
#include <limits.h>
#include <stdio.h>
int main(void) {
long ip1 = 0x01020304;
long ip2 = 0x05060708;
long ip3 = LONG_MIN;
printf("%s %s\n", TO_BASE(ip1, 16), TO_BASE(ip2, 16), TO_BASE(ip3, 16));
printf("%s %s\n", TO_BASE(ip1, 2), TO_BASE(ip2, 2), TO_BASE(ip3, 2));
puts(TO_BASE(ip1, 8));
puts(TO_BASE(ip1, 36));
puts(TO_BASE(ip3, 10));
}
Here is another option with no need for source array of charaters, but less portable since not all character encodings have contiguous alphabetic characters, for example EBCDIC. Test HERE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
char get_chars(long long value)
{
if (value >= 0 && value <= 9)
return value + '0';
else
return value - 10 + 'A';
}
void reverse_string(char *str)
{
int len = strlen(str);
for (int i = 0; i < len/2; i++)
{
char temp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = temp;
}
}
char* convert_to_base(char *res, int base, long long input)
{
bool flag = 0;
int index = 0;
if(input < 0){
input = llabs(input);
flag = 1;
}
else if(input == 0){
res[index++] = '0';
res[index] = '\0';
return res;
}
while(input > 0)
{
res[index++] = get_chars(input % base);
input /= base;
}
if(flag){
res[index++] = '-';
}
res[index] = '\0';
reverse_string(res);
return res;
}
int main() {
long long input = 0;
printf("** Integer to Base-36 **\n ");
printf("Enter a valid number: ");
scanf("%lld", &input);
if(input >= LLONG_MAX && input <= LLONG_MIN){
printf("Invalid number");
return 0;
}
int base = 36;
char res[100];
printf("%lld -> %s\n", input, convert_to_base(res, base, input));
return 0;
}

Binary to Text File Conversion in C

This is the code I have so far for the binary conversion:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
unsigned long binaryToDecimal(char *binary, int length);
void binaryToText(char *binary, int binaryLength, char *text, int symbolCount);
void formatBinary(char *input, int length, char *output);
int validate(char *binary);
int main(void)
{
char binary[8063];
int binaryLength;
scanf("%8063[^\n]s", binary);
binaryLength = strlen(binary);
if(validate(binary))
{
int symbolCount = binaryLength / 8 + 1;
char *text = malloc(symbolCount + 1);
char *formattedBinary = malloc(binaryLength + 1);
if(text == NULL || formattedBinary == NULL)
exit(1);
if(binaryLength % 8 == 0)
--symbolCount;
formatBinary(binary, binaryLength, formattedBinary);
binaryToText(formattedBinary, strlen(formattedBinary), text, symbolCount);
printf("%s in binary is the following text:\n%s\n", binary, text);
free(text);
free(formattedBinary);
}
else
{
printf("The input should be a binary number, containing only zeros(0) and ones(1).\n");
}
return 0;
}
void binaryToText(char *binary, int binaryLength, char *text, int symbolCount)
{
int i;
for(i = 0; i < binaryLength; i+=8, binary += 8)
{
char *byte = binary;
byte[8] = '\0';
*text++ = binaryToDecimal(byte, 8);
}
text -= symbolCount;
}
unsigned long binaryToDecimal(char *binary, int length)
{
int i;
unsigned long decimal = 0;
unsigned long weight = 1;
binary += length - 1;
weight = 1;
for(i = 0; i < length; ++i, --binary)
{
if(*binary == '1')
decimal += weight;
weight *= 2;
}
return decimal;
}
void formatBinary(char *input, int length, char *output)
{
while(*input)
{
if(*input == '0' || *input == '1')
{
*output++ = *input++;
}
else
{
++input;
--length;
}
}
output -= length;
}
int validate(char *binary)
{
while(*binary)
{
if((*binary != '0') && (*binary != '1') && (*binary != ' '))
return 0;
++binary;
}
return 1;
}
Binary File:
010000010100000100110100001100110010000001000100010001100101011100100000010001000101010001010111001000000011001000110000001100010011011000101101001100000011000100101101001100000011011000100000001100010011000100111010001100000011000000001101000010100100000101000001001101000011001100100000010001000100011001010111001000000100010001010100010101110010000000110010001100000011000100110110001011010011000000110001001011010011000100110111001000000011000100110001001110100011000000110000000011010000101001000001010000010011010000110100001000000101001101000101010000010010000001001010010001100100101100100000001100100011000000110001001101010010110100110000001100100010110100110000001101010010000000110111001110100011010000110101000011010000101001000001010000010011000100111001001101110010000001001111010100100100010000100000010000100100111101010011001000000011001000110000001100010011001000101101001100000011001100101101001100010011001000100000001100010011000100111010001101010011000000100000000011010000101001000001010000010011000100100000010010100100011001001011001000000100110001000001010110000010000000110010001100000011000100110110001011010011000000110111001011010011000000110010001000000011100100111010001100000011000000001101000010100100111101001111001101110011010000110011001101010010000001000100010101000101011100100000010100000100110001001110001000000011001000110000001100010011011000101101001100010011000100101101001100100011001000100000001100100011000100111010001101010011010100001101000010100100011000111001001101100011000100110010001000000100010001000101010011100010000001001101010010010100000100100000001100100011000000110001001101000010110100110001001100100010110100110001001110010010000000110010001100100011101000110001001101010000110100001010010001000100110000111000001100000011000100100000010001110100010101000111001000000100110101010011010100000010000000110010001100000011000100110110001011010011000000111000001011010011001100110001001000000011100100111010001100000011000000001101000010100100010001001100001100010011000000111000001101110010000001000001010101000100110000100000010001000100000101000010001000000011001000110000001100010011011000101101001100000011010000101101001100010011000000100000001100010011001000111010001100000011010100001101000010100100010001001100001110000011001000111000001000000100100101000001010010000010000001010011010011000100001100100000001100100011000000110001001100100010110100110000001101100010110100110000001100100010000000110111001110100011010000110101
The conversion algorithm itself works perfectly fine. My main question is how would you be able to apply that conversion to files themselves. Where the first file is a bin file and using the conversion will bring out a text file with all the binary numbers fully converted.

Resources