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.
Related
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;
}
I have to make a program in which I have to add the result of x dices with n faces plus or minus a constant(C). The input should be a string like this: "xDn+-C" (x, n and C must be a decimal number). For example: "4D5+6" or "6D9-5". The D just means "Dice".
I used a function to randomize the rolls but I don't know how to continue...
void initD6(void) {
srand((unsigned)time( NULL ) );
}
int D6(void) {
return ((rand()%6)+1);
}
int main(){
char Dice[4];
for(i=0; i<5; i++){
Dice[i] = D6();
return 0;
}
I don't know how should I take that input as a string and the adding or substracting, and also don't know what should I do next.
Add a struct:
struct rules
{
int dices;
int facesPerDice;
int offset;
};
Solve the dice problem:
int throwDice(int faces)
{
return (rand() % faces) + 1;
}
int playGame(struct rules rules)
{
int result = 0;
for (int i = 0; i < rules.dices; i++)
result += throwDice(rules.facesPerDice);
return result + rules.offset;
}
Solve the parsing problem:
/**
Converts a string to a unsigned int until an invalid character is found or a null character is found.
You should replace this with the function you normally use to convert a string to a integer.
*/
unsigned int stringToUInt(char *str)
{
unsigned int result = 0;
int charindex = 0;
char currentchar;
while ((currentchar = str[charindex++]) != '\0')
{
if (currentchar < '0' || currentchar > '9')
break;
result *= 10;
result += currentchar - '0';
}
return result;
}
/**
Reads a string and generates a struct rules based on it.
The string is expected to be given in the following format:
[uint]'D'[uint]['+' or '-'][uint]
where:
the first uint is the number of dices to roll
the second uint is the number of faces per dice
the third uint is the offset
Terminates the program if something goes wrong.
*/
struct rules parse(char *str)
{
struct rules result;
result.dices = stringToUInt(str);
while (*(str++) != 'D')
if (*str == '\0')
exit(1);
result.facesPerDice = stringToUInt(str);
while (*(str++) != '+' && *(str-1) != '-')
if (*str == '\0')
exit(1);
result.offset = stringToUInt(str);
result.offset *= (*(str-1) == '+' ? 1 : -1);
return result;
}
Put everything together:
int main(int argc, char *argv[])
{
srand(time(NULL));
char input[] = "3D6+9"; //You could use console input if you want
struct rules rules = parse(input);
int gameResult = playGame(rules);
printf("Game result: %d\n", gameResult);
return 0;
}
Assuming no errors in the input, a function which solves your task is:
int throw_dice(const char* s)
{
int num, sides, res;
sscanf(s,"%iD%i%i", &num, &sides, &res);
for (int i = 0; i < num; ++i) {
res += rand() % sides + 1;
}
return res;
}
For simple string parsing sscanf() is a pretty good function. For more complex tasks it's better to use a regular expression library.
As usual, don't relay on rand() for anything but the most simple dice games, with no money involved.
You can try it with the following full example:
#include <stdio.h>
int throw_dice(const char* s)
{
int num, sides, res;
sscanf(s,"%iD%i%i", &num, &sides, &res);
for (int i = 0; i < num; ++i) {
res += rand() % sides + 1;
}
return res;
}
void throw_multiple_times(const char* s, int times)
{
printf("%s: ", s);
for (int i = 0; i < times; ++i) {
printf("%i ", throw_dice(s));
}
printf("\n");
}
int main(void)
{
srand((unsigned)time(NULL));
const char* s;
throw_multiple_times("4D5+6", 100);
throw_multiple_times("6D9-5", 100);
return 0;
}
Test it here.
# include <stdio.h>
int main(){
int a,b;
scanf("%d %d",&a,&b);
while (a > 0) {
int digit = a % 10;
//printf("%d ",digit); for testing
a = a - digit;
a /= 10;
}
while (b > 0) {
int digit = b % 10;
//printf("%d ",digit); for testing
b = b - digit;
b /= 10;
}
}
This code takes two integers with the same lengths(a,b), splits them into their characters, now the question is how to print it like this for example(a=123 , b= 798 --> result = 17-29-38
Save the digits in arrays. Then you can loop over the arrays to print the digits at the end.
Also, you don't need to subtract digit before dividing by 10, since division discards the remainder.
# include <stdio.h>
#define MAXDIGITS 20
int main(){
int a,b;
int adigits[MAXDIGITS], bdigits[MAXDIGITS];
int digits = 0;
scanf("%d %d",&a,&b);
while (a > 0) {
int digit = a % 10;
//printf("%d ",digit); for testing
adigits[digits++] = digit;
a /= 10;
}
digits = 0;
while (b > 0) {
int digit = b % 10;
//printf("%d ",digit); for testing
bdigits[digits++] = digit;
b /= 10;
}
while (--digits >= 0) {
printf("%d%d", adigits[digits], bdigits[digits]);
if (digits != 0) {
putchar('-');
}
}
putchar('\n');
}
Your input is strings, and there is no point in converting those strings to integers just to change them back. Just work on the data directly. eg:
#include <stdio.h>
#include <stddef.h>
#include <ctype.h>
#include <stdlib.h>
struct buffer {
char *start;
char *end;
size_t cap;
};
void push(int c, struct buffer *);
int pop(struct buffer *);
void * xrealloc(void *buf, size_t num, size_t siz, void *offsetp);
int
main(void)
{
struct buffer a = {0};
struct buffer b = {0};
int c;
while( (c = getchar()) != EOF && !isspace(c) ) {
push(c, &a);
}
while(isspace(c = getchar())) {
;
}
ungetc(c, stdin);
while( (c = getchar()) != EOF ) {
push(c, &b);
}
while( (c = pop(&a)) != EOF ) {
putchar(c);
if( (c = pop(&b)) != EOF ) {
putchar(c);
}
}
while( (c = pop(&b)) != EOF ) {
putchar(c);
}
return 0;
}
int
pop(struct buffer *a)
{
return (a->start < a->end) ? *a->start++ : EOF;
}
void
push(int c, struct buffer *b)
{
if( b->start == NULL ) {
b->end = b->start = xrealloc(NULL, b->cap = 8, 1, NULL);
} else if( b->end >= b->start + b->cap ) {
b->start = xrealloc(b->start, b->cap *= 2, 1, &b->end);
}
*b->end++ = c;
}
void *
xrealloc(void *buf, size_t num, size_t siz, void *offsetp)
{
ptrdiff_t offset;
void **iterator = offsetp;
if( iterator != NULL ) {
offset = *iterator - buf;
}
buf = realloc(buf, num * siz);
if( buf == NULL ) {
perror("realloc");
exit(EXIT_FAILURE);
}
if( iterator != NULL ) {
*iterator = buf + offset;
}
return buf;
}
This code is supposed to take a user's input and convert it to binary. The input is grouped into an integer array to store character codes and/or adjacent digits, then each item in the integer array is converted to binary. When the user types "c357", "c" should be converted to 99, then converted to binary. Then, "357" should be converted to binary as well. In the main() function, strlen(convert) does not accurately represent the number of items in array convert, thus only iterating over the first array item.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#define EIGHT_BITS 255
#define SIXTEEN_BITS 65535
#define THIRTY_TWO_BITS 4294967295UL
// DETERMINE NUMBER OF BITS TO OUTPUT
int getBitLength(unsigned long d) {
int l;
if (d <= EIGHT_BITS) {
l = 8;
}
else if (d > EIGHT_BITS && d <= SIXTEEN_BITS) {
l = 16;
}
else if (d > SIXTEEN_BITS && d <= THIRTY_TWO_BITS) {
l = 32;
}
return l;
}
// CONVERT INPUT TO BINARY VALUE
char* convertToBinary(unsigned long int decimal) {
int l = getBitLength(decimal);
static char b[33];
char bin[33];
int i, j, k = 0, r;
b[33] = '\0';
bin[33] = '\0';
printf("Bits................ %ld\n", l);
// creates array
for (i = 0; i < l; i++) {
r = decimal % 2;
decimal /= 2;
b[i] = r;
}
// reverses array for binary value
for (j = l - 1; j >= 0; j--) {
bin[k] = b[j];
strncpy(&bin[k], &b[j], l);
snprintf(&bin[k], l, "%d", b[j]);
k++;
}
printf("Binary Value: %s\n", bin);
return bin;
}
unsigned long int* numbersToConvert(char* input) {
const int MAX_INPUT = 20;
int i, k = 0, z = 0;
char numbers[MAX_INPUT];
unsigned long int *toConvert = malloc(MAX_INPUT * sizeof(int));
numbers[MAX_INPUT] = '\0';
for (i = 0; i < strlen(input); i++) {
if (isdigit(input[i])) {
numbers[z] = input[i];
if (!isdigit(input[i + 1])) {
toConvert[k] = strtol(numbers, NULL, 10);
printf("----- %ld -----\n", toConvert[k]);
z = 0;
}
else {
z++;
}
}
else {
printf("----- %c -----\n", input[i]);
printf("Character Code: %d\n", input[i]);
toConvert[k] = (unsigned long int) input[i];
}
k++;
}
return toConvert;
}
int main(void) {
const int MAX_INPUT = 20;
int i, p;
char input[MAX_INPUT];
unsigned long int* convert;
printf("------- Input --------\n");
scanf("%s", input);
input[MAX_INPUT] = '\0';
// PRINT INPUT AND SIZE
printf("\nInput: %s\n", input);
convert = numbersToConvert(input);
convert[MAX_INPUT] = '\0';
printf("strlen: %ld\n", strlen(convert));
for (i = 0; i < strlen(convert); i++) {
printf("num array: %ld\n", convert[i]);
convertToBinary(convert[i]);
}
return 0;
}
I have attempted to null terminate each string to prevent undefined behavior. I am unsure if certain variables, if any, are meant to be static.
It is hard to read your code.
Here you have something working (converting the number to binary):
static char *reverse(char *str)
{
char *end = str + strlen(str) - 1;
char *saved = str;
int ch;
while(end > str)
{
ch = *end;
*end-- = *str;
*str++ = ch;
}
return saved;
}
char *tostr(char *buff, unsigned long long val)
{
if(buff)
{
char *cpos = buff;
while(val)
{
*cpos++ = (val & 1) + '0';
val >>= 1;
}
*cpos = 0;
reverse(buff);
}
return buff;
}
int main()
{
char buff[128];
printf("%s\n", tostr(buff, 128));
}
https://godbolt.org/z/6sRC4C
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);
}