Using arrays for BCD conversion in C - c

I'm working on a project where I need to convert some long variables into BCD.
I already have some code that works but I feel that it can be improved...
void main(void){
unsigned long input = 0;
unsigned long convert = 0;
float convert2 = 0;
char buffer[200];
unsigned char Ones, Tens, Hundreds, Thousands, TenThousands, HundredThousands;
printf("Input: ");
scanf("%d", &input);
convert = input*12;
convert2 = input * 0.0001224896;
BCD(convert, &Ones, &Tens, &Hundreds, &Thousands, &TenThousands, &HundredThousands);
sprintf(buffer, "%d%d%dKG", HundredThousands, TenThousands, Thousands);
printf("\n\nInputted: %d", input);
printf("\nADC Conversion: %d", convert);
printf("\nBCD Conversion: %s", buffer);
printf("\nFloat Conversion: %f", convert2);
getchar();
getchar();
}
void BCD (unsigned long Pass, unsigned char *Ones, unsigned char *Tens, unsigned char *Hundreds, unsigned char *Thousands, unsigned char *TenThousands, unsigned char *HundredThousands){
unsigned char temp1, temp2, temp3, temp4, temp5, temp6;
unsigned int count = 0;
*Ones = 0;
*Tens = 0;
*Hundreds = 0;
*Thousands = 0;
*TenThousands = 0;
*HundredThousands = 0;
temp1 = 0;
temp2 = 0;
temp3 = 0;
temp4 = 0;
temp5 = 0;
temp6 = 0;
for(count = 0; count <= 31; count++){
if (*Ones >= 5){
*Ones = (*Ones + 3)&0x0F;
}
if (*Tens >= 5){
*Tens = (*Tens + 3)&0x0F;
}
if (*Hundreds >= 5){
*Hundreds = (*Hundreds + 3)&0x0F;
}
if (*Thousands >= 5){
*Thousands = (*Thousands + 3)&0x0F;
}
if (*TenThousands >= 5){
*TenThousands = (*TenThousands + 3)&0x0F;
}
if (*HundredThousands >= 5){
*HundredThousands = (*HundredThousands + 3)&0x0F;
}
temp1 = (Pass & 2147483648) >> 31;
temp2 = (*Ones & 8) >> 3;
temp3 = (*Tens & 8) >> 3;
temp4 = (*Hundreds & 8) >> 3;
temp5 = (*Thousands & 8) >> 3;
temp6 = (*TenThousands & 8) >> 3;
Pass = Pass << 1;
*Ones = ((*Ones << 1) + temp1) & 15;
*Tens = ((*Tens << 1) + temp2) & 15;
*Hundreds = ((*Hundreds << 1) + temp3) & 15;
*Thousands = ((*Thousands << 1) + temp4) & 15;
*TenThousands = ((*TenThousands << 1) + temp5) & 15;
*HundredThousands = ((*HundredThousands << 1) + temp6) & 15;
printf("\n\nLoop: %d\nOnes: %d\n", count, *Ones);
printf("Tens: %d\n", *Tens);
printf("Hundreds: %d\n", *Hundreds);
printf("Thousands: %d\n", *Thousands);
printf("TenThousands: %d\n", *TenThousands);
printf("HundredThousands: %d\n",*HundredThousands);
}
}
The problem I have with this is that it seems messy and inefficient. I was think that instead of using multiple variable for each BCD unit (Ones, Tens, etc), I could use an arrays to carry out the same process. I have implemented this in code but I'm running into a few problems. The code only seems to display "Ones" equivalent element. I've stepped through the code as well and found that the other elements are not being populated during the conversion process. Any guidance on what is going on?
Array implementation:
void main(void){
unsigned long input = 0;
unsigned long convert = 0;
char buffer[200];
unsigned char BCD_Units[6];
unsigned char temp[6];
unsigned int count = 0;
unsigned int count1 = 0;
unsigned char buff_store = 0;
unsigned char buff_store2 = 0;
printf("Input: ");
scanf("%d", &input);
convert = input;
memset(temp, 0, sizeof(temp));
memset(BCD_Units, 0, sizeof(BCD_Units));
for(count = 0; count <= 31; count++){
for (count1 = 0; count1 < 6; count1++){
if (BCD_Units[count1] >= 5){
buff_store = BCD_Units[count1];
buff_store = ((buff_store + 3) & 15);
BCD_Units[count1] = buff_store;
}
}
temp[0] = (convert & 2147483648) >> 31;
for (count1 = 0; count1 < 5; count1++){
buff_store = BCD_Units[count1];
temp[(count+1)] = (buff_store & 8) >> 3;
}
convert = convert << 1;
for(count1 = 0; count1 < 6; count1++){
buff_store = BCD_Units[count1];
buff_store2 = temp[count1];
buff_store = ((buff_store << 1) + buff_store2) & 15;
BCD_Units[count1] = buff_store;
temp[count1] = buff_store2;
}
printf("\n\nLoop: %d\nOnes: %d\n", count, BCD_Units[0]);
printf("Tens: %d\n", BCD_Units[1]);
printf("Hundreds: %d\n", BCD_Units[2]);
printf("Thousands: %d\n", BCD_Units[3]);
printf("TenThousands: %d\n", BCD_Units[4]);
printf("HundredThousands: %d\n", BCD_Units[5]);
}
sprintf(buffer, "%d%d%dKG", BCD_Units[5], BCD_Units[4], BCD_Units[3]);
printf("\n\nInputted: %d", input);
printf("\nBCD Conversion: %s", buffer);
getchar();
getchar();
}
PS. I'm just playing around, at the moment, with ideas. I plan to compartmentalise the code into functions at a later date.

this code seems enormously complicated. YOu just need to do the following
make a buffer
loop till n = 0
get n % 10 (get digit)
or digit into left or right nibble of curretn buffer byte (need a toggle for left or right)
increment buffer pointer if filled left nibble
n = n / 10
try this Convert integer from (pure) binary to BCD

Related

command gets stuck for some reason

I am trying to input basic ip address from the user, but my command gets stuck here in the scanf and nothing after that is executed.
int ip1,ip2,ip3,ip4;
scanf("%d.%d.%d.%d",&ip1,&ip2,&ip3,&ip4);
printf("Here");
So, basically "Here" is never printed and the command scanf never gets over?
#include <stdio.h>
#include<math.h>
int main(void) {
char input;
char rep = 'r';
char quit = 'q';
char first = '1';
char second = '2';
input = rep;
while( input != quit) {
printf("What type of conversion do you want? \n");
printf("Enter 1 for 32-bit number to dot-decimal conversion, 2 for the inverse of operation: ");
char val;
scanf(" %c", &val);
if( val == first) {
} else if( val == second) {
printf("\nEnter dot-decimal IP address:");
int ip1,ip2,ip3,ip4;
scanf(" %d.%d.%d.%d", &ip1,&ip2,&ip3,&ip4);
printf("Here");
unsigned int ip = 0,c,k,counter = 31;
for(c = 7; c >= 0; c--) {
k = ip1 >> c;
if(k & 1) {
int temp = 2,i;
for(i = 0; i < counter;i++) {
temp *= 2;
}
ip += temp;
counter--;
}
}
for(c = 7; c >= 0; c--) {
k = ip2 >> c;
if(k & 1) {
int temp = 2,i;
for(i = 0; i < counter;i++) {
temp *= 2;
}
ip += temp;
counter--;
}
}
for(c = 7; c >= 0; c--) {
k = ip3 >> c;
if(k & 1) {
int temp = 2,i;
for(i = 0; i < counter;i++) {
temp *= 2;
}
ip += temp;
counter--;
}
}
for(c = 7; c >= 0; c--) {
k = ip4 >> c;
if(k & 1) {
int temp = 2,i;
for(i = 0; i < counter;i++) {
temp *= 2;
}
ip += temp;
counter--;
}
}
printf("%u is the IP Address",ip);
}
printf("\n \n Enter r to repeat, q to quit:");
scanf(" %c",&input);
}
return 0;
}
This is the exactly what i was doing. It gets stuck on when i try to get the IP Address in decimal notation.
I have analyzed your code after update (full code) and found that problem not in the input with scanf but in the for loops that are executed after data is obtained.
Look at that loop:
unsigned int ip = 0,c,k,counter = 31;
for(c = 7; c >= 0; c--) {
k = ip1 >> c;
if(k & 1) {
int temp = 2,i;
for(i = 0; i < counter;i++) {
temp *= 2;
}
ip += temp;
counter--;
}
}
and particularly at for(c = 7; c >= 0; c--) taking into account that c is of type unsigned int... I see that this loop is INFINITE because decrement makes from 0 new positive value UINT_MAX (see limits.h).

Base64 Encoding Padding in C

I am writting a base64 encoder and decoder and have it almost completly functional, I just need to be able to pad the encoded data with equal signs if the number of input bytes does not round out to a multiple of 3. I am relativly new to C and am not sure how I would detect the number of bytes or pad the output accordingly. This is what I have so far
void encode(char* src, char* dest) {
char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char first = (src[0] >> 2);
unsigned char second = (src[0] << 4) | (src[1] >> 4);
second = (second << 2);
second = (second >> 2);
unsigned char third = (src[1] << 2) | (src[2] >> 6);
third = (third << 2);
third = (third >> 2);
unsigned char fourth = (src[2]);
fourth = (fourth << 2);
fourth = (fourth >> 2);
dest[0] = base64[first];
dest[1] = base64[second];
dest[2] = base64[third];
dest[3] = base64[fourth];
}
And my decoder method...
void decode(char* src, char* dest) {
char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int i;
int j;
int index;
for(i = 0; i < 4; i++) {
index = 0;
for(j = 0; j < 64; j++) {
if (src[i] == base64[j]) {
src[i] = index;
} else {
index++;
}
}
}
char first = (src[0] << 2) | (src[1] >> 4);
char second = (src[1] << 4) | (src[2] >> 2);
char third = (src[2] << 6) | (src[3]);
dest[0] = first;
dest[1] = second;
dest[2] = third;
}
If this is not enough and I need to also provide the rest of my code I can do so.

Fixed point square root function wrong results for big numbers

Hello friends and enemies
I have this square root function from a library called libfixmath which works great, however from 32767.0f and above it starts returning wrong and negative results. The numbers I need square root of are rather big, up to 999999.0f. Any of you know what I could do to fix the problem?
#include <iostream>
float into_float(const int value) {
return ((float)value / 65536.0f);
}
int from_float(const float value) {
return (int)(value * 65536.0f);
}
int fp_sqrt(int value) {
unsigned char neg = (value < 0);
unsigned int num = (neg ? -value : value);
unsigned int result = 0;
unsigned int bit;
unsigned char n;
if (num & 0xFFF00000) {
bit = (unsigned int)1 << 30;
} else {
bit = (unsigned int)1 << 18;
}
while (bit > num) bit >>= 2;
for (n = 0; n < 2; n++) {
while (bit) {
if (num >= result + bit) {
num -= result + bit;
result = (result >> 1) + bit;
} else {
result = (result >> 1);
}
bit >>= 2;
}
if (n == 0) {
if (num > 65535) {
num -= result;
num = (num << 16) - 0x8000;
result = (result << 16) + 0x8000;
} else {
num <<= 16;
result <<= 16;
}
bit = 1 << 14;
}
}
if (num > result) {
result++;
}
return (neg ? -result : result);
}
void main() {
float flt_value = 32767.0f;
int int_value = from_float(flt_value);
float flt_root = sqrt(flt_value);
int int_root = fp_sqrt(int_value);
float flt_root2 = into_float(int_root);
printf("sqrt: %f fp_sqrt: %f", flt_root, flt_root2);
getchar();
}
Thank you leppie, I changed some stuff around and it works with big numbers now, I am not sure if what I did is totally right though but here it is:
#include <iostream>
float into_float(const int value) {
return ((float)value / 65536.0f);
}
long long from_float(const float value) {
return (long long)(value * 65536.0f);
}
long long fp_sqrt(long long value) {
unsigned char neg = (value < 0);
long long num = (neg ? -value : value);
long long result = 0;
long long bit;
unsigned char n;
if (num & 0xFFF00000) {
bit = (long long)1 << 60;
} else {
bit = (long long)1 << 36;
}
while (bit > num) bit >>= 2;
for (n = 0; n < 2; n++) {
while (bit) {
if (num >= result + bit) {
num -= result + bit;
result = (result >> 1) + bit;
} else {
result = (result >> 1);
}
bit >>= 2;
}
if (n == 0) {
if (num > 65535) {
num -= result;
num = (num << 16) - 0x8000;
result = (result << 16) + 0x8000;
} else {
num <<= 16;
result <<= 16;
}
bit = 1 << 14;
}
}
if (num > result) {
result++;
}
return (neg ? -result : result);
}
void main() {
float flt_value = 11932767.0f;
long long ll_value = from_float(flt_value);
float flt_root = sqrt(flt_value);
int int_root = (int)fp_sqrt(ll_value);
float flt_root2 = into_float(int_root);
printf("sqrt: %f fp_sqrt: %f", flt_root, flt_root2);
getchar();
}

Unique file name using UUID

I need to create some binary data files from Object Identifiers, which is a variable-length binary void* buffer, upto 64 bytes and can contain any bytes corresponding to non-printable characters as well. I can't use Object Identifier as my file name as it contains non-printable letters.
Any suggestions to create the unique filename. How can the UUID be derived or used in this case ?
You can convert the bytes into a hexadecimal string.
#define tohex(x) ("0123456789abcdef"[(x) & 0x0f])
char buf[129];
assert(objid_len <= 64);
for (int i = 0; i < objid_len; ++i) {
buf[2*i] = tohex(objid[i] >> 4);
buf[2*i+1] = tohex(objid[i]);
}
buf[2*objid_len] = '\0';
You can make the filenames have universal length by using a padding character that is outside the alphabet used to to represent the object id. If a shorter filename is desired, then a higher base could be used. For example, Base64.
const char * const base64str =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define tob64(x) base64str[(x) & 0x3f]
void objid_to_filename (const unsigned char *objid, int objid_len,
char *buf) {
memset(buf, '-', 88);
buf[88] = '\0';
int i = 0, j = 0;
int buflen = 4 * ((objid_len + 2)/3);
while (i < objid_len) {
unsigned x = 0;
x |= (i < objid_len) ? objid[i++] << 16 : 0;
x |= (i < objid_len) ? objid[i++] << 8 : 0;
x |= (i < objid_len) ? objid[i++] << 0 : 0;
buf[j++] = tob64(x >> 18);
buf[j++] = tob64(x >> 12);
buf[j++] = tob64(x >> 6);
buf[j++] = tob64(x >> 0);
}
int pad = (3 - (objid_len % 3)) % 3;
for (i = 0; i < pad; ++i) buf[buflen - 1 - i] = '=';
}

How to generate all possible subsequences including Non-continuous subsequences of a string using C

For example,
char str[20];
str="ABCD";
Output :
1 - A, B, C,D
2 - AB,AC, AD BC, BD, CD.
3 - ABC, ABD, BCD.
4 - ABCD.
The sub-sequences are generated only in left to right fashion. Thanks :)
#include<stdio.h>
#include <conio.h>
#include<string.h>
int sub[10];
void next(int max, int length) {
int pos = length - 1,a;
//find first digit that can be increased
while(pos >= 0)
{
if(sub[pos] == max - (length - 1 - pos))
pos--;
else
break;
}
sub[pos]++; //increase digit
//update other digits
for( a = pos+1; a < length; a++)
sub[a] = sub[a-1] + 1;
}
int main()
{
char word[100];
printf("Enter a word = ");
scanf("%s",word);
int max = strlen(word) - 1,n,i,a,b;
for(n=1; n <= max+1; n++)
{
printf("\n");
for(i = 0; i < n; i++)
{
sub[i] = i;
}
for(a = 0; ; a++)
{
for(b=0; b < max+1; b++)
printf("%c",word[sub[b]]);
printf("\n");
if(sub[0] == max - (n - 1))
break;
else
next(max, n);
}
printf("\n");
}
return 0;
}
This code only produces sub-sequences of the length equal to the length of the string and it also repeats a particular character.
not the cleanest, most effective code, but this'll do :D
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
char *printForMask(int mask, char *str)
{
int i = 0;
int j = 0;
char *maskedString = (char *)malloc(sizeof(char) * strlen(str) + 1);
for (; mask > 0; mask >>= 1, j++) {
if (mask & 1)
maskedString[i++] = str[j];
}
maskedString[i] = '\0';
return maskedString;
}
int main()
{
char str[20] = "ABCD";
int mask = 1;
int maskLen = 1;
int stringLen = strlen(str);
for (maskLen = 1; maskLen <= stringLen; maskLen++) {
printf("%d ", maskLen);
for (mask = (int)pow(2,maskLen) - 1; mask <= (int) pow(2, stringLen) - 1; mask <<= 1) {
char *temp = printForMask(mask, str);
printf ("%s%s", temp, (mask << 1 <= (int) pow(2, stringLen) - 1) ? ", " : "\n");
free(temp);
}
}
return 0;
}
EDIT
for the string ABCD
str[0] = 'A'
str[1] = 'B'
str[2] = 'C'
str[3] = 'D'
right?
So What I'm doing is using the binary representation of a integer 2^strlen(str) - 1
which in this case would be 2^4 - 1 = 15 = 0b1111
In the first for-loop of the main function, I increase the mask, meaning
start off with a mask = 0b0001, for each iteration of the loop, increase the mask to mask = 0b1111
And in the inner for loop, I shift the mask so that something like this happens
mask = 0b0001 //A
mask = 0b0010 //B
mask = 0b0100 //C
mask = 0b1000 //D
//The inner loop will finish here, and the mask length will become 2
mask = 0b0011 //AB
mask = 0b0110 //BC
mask = 0b1100 //CD
//etc. The string representation is made by the function printForMask()

Resources