converting decimal to exponent and mantissa - c

I am trying to convert a decimal number (329.39062) to binary (exponent, mentissa). I keep getting segmentation fault. on running the gdb test, It shows me feof. I have changed alot but it keeps showing me the segmentation fault at the same point. Where am i going wrong? Thank you for all the help.
#include <stdio.h>
#include <stdlib.h>
char* valueToConvert(int value);
int main(int argc, char *argv[])
{
FILE* input;
FILE* output;
input = fopen(argv[1],"r");
output = fopen(argv[2],"w");
float value;
unsigned char *charValue = (unsigned char *) &value;
int exponentValue;
long mantissaValue;
while(!feof(input))
{
fread(&charValue, sizeof(float),1, input);
exponentValue = ((charValue[0] & 0x7F) << 1)|((charValue[1] & 0x80) >> 7);
mantissaValue = ((charValue[1] & 0x7F) << 8)|((charValue[2] & 0xFF) <<8) | (charValue[3] & 0xFF);
fprintf(output,"%d %s %s\n",(charValue[0] & 0x80 >> 7),valueToConvert(exponentValue - 127),valueToConvert(mantissaValue));
}
}
char* valueToConvert(int value)
{
int counter = 0;
char* conversion = calloc(32,sizeof(int));
while(value>0)
{
if((value%2 == 1) && (value%2 != 0))
{
conversion[31 - counter++] = '1';
}
if((value%2 == 0) && (value%2 != 1))
{
conversion[31 - counter++] = '0';
}
value = value/2;
}
return conversion;
}

The problem is here:
fread(&charValue, sizeof(float),1, input);
That should be
fread(charValue, sizeof(float),1, input);
Because charValue is a pointer.
To address your problems with the output, you're filling the buffer backwards after initializing it completely with 0 via calloc, so fprintf is hitting 0 (a char used to signify the end of a string) and stopping "prematurely".
Here's a fast binary string function:
void fast_d2b(int x, char* c) {
int i;
for (i = 31; i >= 0; --i) {
*(c++) = '0' + ((x >> i) & 0x1);
}
}
It's based on the one shown here.
Only differences are that my variation doesn't write to the buffer backwards and it writes '0' and '1' instead of integral values 0 and 1.

Related

I am not getting the byte values?

I'm not able to get the right output when I do the following code. look at the comments for what I'm trying to print.
I did the code based on what I've been learning so far, but I'm still not getting the right output.
So any suggestions? What have I done, so I'm able to fix the problem.
When I print(A), I'm not getting 0100 0001, but it prints 49d or 49 sometimes
#include <stdio.h>
unsigned char getBit(unsigned char c, int n)
{
return ((c & (1 << n)) >> n);
}
unsigned char setBit(unsigned char c, int n)
{
c = c | (1 << n);
return c;
}
unsigned char clearBit(unsigned char c, int n)
{
c = c & (~(1 << n));
return c;
}
void printBits(unsigned char c)
{
printf("The bit of the character you inputed is %x \n", c);
}
int main(void)
{
unsigned char a = 'A';
printBits(a);
putchar('\n');
a = setBit(a, 2);
a = setBit(a, 3);
printBits(a); //should print 0100 0001, but it prints 49
putchar('\n');
a = clearBit(a, 2);
printBits(a);
putchar('\n');
}
Your current solution prints the value of c as a hexadecimal number using printf(). Since there is no printf format specifier to print a number in binary representation, we'll have to write our own solution.
#include <limits.h>
#include <stdio.h>
void printBits(byte c)
{
for (unsigned i = CHAR_BIT; i;) { // count from the with of a char
// in bits down to 1
putchar(c & 1 << --i // test the i-th bit (1-based)
? '1' // if true (different form 0) evaluates to '1'
: '0' // else evaluates to '0'
);
if (CHAR_BIT == 8 && i % 4 == 0) // if we use 8-bit-bytes and just
// finished printing the higher nibble
putchar(' '); // insert a seperator between the nibbles
}
}
... ftw!
No-nonsense version:
void printBits(byte c)
{
for (unsigned i = CHAR_BIT; i;) {
putchar(c & 1 << --i ? '1' : '0');
if (CHAR_BIT == 8 && !(i % 4))
putchar(' ');
}
}
`
unsigned char a = 'A';
printBits(a); // should print 0100 0001
putchar('\n');
a = setBit(a, 2);
a = setBit(a, 3);
printBits(a); // should print 0100 1101
putchar('\n');
a = clearBit(a, 2);
printBits(a); // should print 0100 1001
putchar('\n'

Convert int to byte for GPIO

I'm trying to convert a int to a 4 bit array, so that I can output them using the GPIOs of a raspberry pi. I'm programming in C. My current function is:
#include <stdio.h>
char *binaryToAbits(unsigned int answer, char *result) {
if(answer>1)
{
result=binaryToAbits(answer-1,result);
}
*result='0'+(answer & 0x01);
return result+1;
};
int main(void) {
unsigned int numToConvert=2;
char ascResult[]={0,0,0,0};
int i;
*binaryToAbits(numToConvert,ascResult)='\0';
for(i=0;i<4;i++)
{
if(ascResult[i]!='1') ascResult[i]='0';
}
for(i=3;i>=0;i--)
{
printf("%c\n",ascResult[i]);
}
printf("\n");
return 0;
}
The problem is that the signal for the array isn't calculated correctly.
Using recursion is making it more complicated than necessary.
You can simply do:
void binaryToAbits(unsigned int input, char *result)
{
result[0] = (input & 0x1) ? '1' : '0';
result[1] = (input & 0x2) ? '1' : '0';
result[2] = (input & 0x4) ? '1' : '0';
result[3] = (input & 0x8) ? '1' : '0';
}

Read Hex from a file and convert 2 Bytes into Signed int

I have a file in this format:
F2,80,FF,CF,0F,00,A2,XXXX,XXXX,XXXX,01FE,00
I need to take bytes 3 and 4 and combine them into a signed integer.
For example I should extract FF and CF and combine them to 0xFFCF. This should give me a signed value of -49.
The code that I have is here:
int main()
{
char buffer[1024] ;
char *record,*line;
uint8_t val;
uint8_t msb, lsb;
int16_t rate;
int i=0,j=0;
int mat[100][100];
FILE *fstream = fopen("log1.txt","r");
if(fstream == NULL)
{
printf("\n file opening failed ");
return -1 ;
}
while((line=fgets(buffer,sizeof(buffer),fstream))!=NULL)
{
record = strtok(line,",");
int count = 0;
while(record != NULL)
{
count++;
if (count == 3)
{
printf("string:%s\n", record);
sscanf(record, "%02X", &msb);
printf("MSB: %01X\n",msb) ;
}
if (count == 4)
{
printf("string:%s\n", record);
sscanf(record, "%02X", &lsb);
printf("lsb: %01X\n",lsb);
}
if (count == 5)
{
int16_t value = (short)(((msb) & 0xFF) << 8 | (lsb) & 0xFF);
printf("rate: %.2f\n", value*0.03125);
getchar();
}
record = strtok(NULL,",");
}
++i ;
}
return 0;
}
The exact output I see from my code is:
string:FF
MSB: FF
string:CD
lsb: CD
HEX: 00CD
rate: 6.41
I would expect rate to come out as: -1.59
I never seem to see negative numbers, and the values I get are too small.
Rather than using different variable types to try and get the behaviour that you want, how about just being explicit about it? Like so:
#include <stdio.h>
int main(int argc, char *argv[])
{
int msb = 0xff;
int lsb = 0xcf;
int value = (((msb & 0xff) << 8) | (lsb & 0xff));
if (value >= 0x8000) value = -(0x10000 - value);
printf("%d\n", value);
return 0;
}
Here is how I got the code to work:
int16_t hexToInt(char* msb, char* lsb)
{
char toparse[50];
strcpy(toparse, msb);
strcat(toparse,lsb);
int16_t number = (int16_t)strtol(toparse, NULL, 16);
return number;
}
int main()
{
char buffer[1024] ;
char *record,*line;
uint8_t val;
char msb[16], lsb[16];
int16_t rate;
FILE *fstream = fopen("log1.txt","r");
if(fstream == NULL)
{
printf("\n file opening failed ");
return -1 ;
}
while((line=fgets(buffer,sizeof(buffer),fstream))!=NULL)
{
record = strtok(line,",");
int count = 0;
while(record != NULL)
{
count++;
if (count == 3)
{
printf("string:%s\n", record);
strcpy(msb, record);
}
if (count == 4)
{
printf("string:%s\n", record);
strcpy(lsb,record);
}
if (count == 5)
{
int16_t value = hexToInt(msb,lsb);
printf("rate: %.2f\n", value*0.03125);
getchar();
}
record = strtok(NULL,",");
}
++i ;
}
return 0;
}
The value is indeed 0xFFCF, but when multiplying with 0.03125 it is promoted to higher datatype because of which value looses its signedness.
Just change
printf("rate: %.2f\n", value*0.03125);
to
printf("rate: %.2f\n", ((short)value*0.03125));
With value being -49 or 0xFFCF the output will be
rate: -1.53
Code has undefined behavior. OP's code attempts to save an int sized result into 1-byte locations. A good compiler or one with warnings enabled would warn of this issue.
uint8_t msb, lsb;
...
sscanf(record, "%02X", &msb);
sscanf(record, "%02X", &lsb);
Code could use the correct scanf() specifier
#include <inttypes.h>
sscanf(record, "%02" SCNx8, &msb);
sscanf(record, "%02" SCNx8, &lsb);
or simply a different type
unsigned msb, lsb;
...
sscanf(record, "%02X", &msb);
sscanf(record, "%02X", &lsb);
OP's conversion is suspect:
uint8_t msb, lsb;
int16_t value = (short)(((msb) & 0xFF) << 8 | (lsb) & 0xFF);
printf("rate: %.2f\n", value*0.03125);
Suggest something like #John Bickers The following works even if int is 16-bit.
long value = msb;
value <<= 8;
value += lsb;
if (value >= 0x8000) value -= 0x10000;
printf("value %ld\n", value);
// -49 * 0.03125 --> "-1.53"
printf("rate: %.2f\n", value * 0.03125);
Since OP expects a scaled out of -15.6 from -49, perhaps scaling by 1/pi is needed rather than * 0.03125?

Printing signbit

I feel like I am nearing an end on this assignment, but do not understand why it only works correctly every other time. If I enter "FFFFFFFF" my program prints out:
0xFFFFFFFF
signBit 1, expBits 255, fractBits 0x007FFFFF
QNaN
but if I enter "FFFFFFFF" again my program prints out:
0xFFFFFFFF
my program will not print out the correct output every time but yet every other time.
Is there anyone who can help me identify where the error occurs in my code?
Any help is greatly appreciated!
Thanks!
// do not change this code except in the following ways:
// * write code for the following functions:
// * bigOrSmallEndian()
// * getNextHexInt()
// * printLinesForNumber()
// * change studentName by changing "I. Forgot" to your actual name
#include <stdio.h>
#include <stdlib.h>
static char *studentName = "Tenzin Shakya";
// report whether machine is big or small endian
void bigOrSmallEndian()
{
int num = 1;
if(*(char *)&num == 1)
{
printf("\nbyte order: little-endian\n\n");
}
else
{
printf("\nbyte order: big-endian\n\n");
}
}
// get next int (entered in hex) using scanf()
// returns 1 (success) or 0 (failure)
// if call succeeded, return int value via i pointer
int getNextHexInt(int *i)
{
// replace this code with the call to scanf()
//*i = 0;
//return 1;
scanf ("%x", i);
return 1;
}
// print requested data for the given number
void printNumberData(int i)
{
//printf("%x %0#10x\n",i,*(int *)&i);
int tru_exp =0;
//int stored_exp;
int negative;
int exponent;
int mantissa;
printf("\n>");
scanf("%x", &i);
printf("\n0x%08X",i);
negative = !!(i & 0x80000000);
exponent = (i & 0x7f800000) >> 23;
mantissa = (i & 0x007FFFFF);
printf("\nsignBit %d, ", negative);
printf("expbits %d, ", exponent);
printf("fractbits 0x%08X", mantissa);
// "%#010x, ", mantissa);
if(exponent == 0)
{
if(mantissa != 0)
{
printf("\ndenormalized ");
}
}
else{
printf("\nnormalized: ");
tru_exp = exponent - 127;
printf("exp = %d", tru_exp);
}
if(exponent == 0 && mantissa == 0 && negative == 1)
{
printf("\n-zero");
}
if(exponent ==0 && mantissa == 0 && negative == 0)
{
printf("\n+zero");
}
if(exponent == 255 && mantissa != 0 && negative == 1)
{
printf("\nQNaN");
}
if(exponent == 255 && mantissa != 0 && negative == 0)
{
printf("\nSNaN");
}
if(exponent == 0xff && mantissa == 0 && negative == 1)
{
printf("\n-infinity");
}
if(exponent == 0xff && mantissa == 0 && negative == 0)
{
printf("\n+infinity");
}
printf("\n");
while(i != 0)
break;
}
// do not change this function in any way
int main(int argc, char **argv)
{
int i; // number currently being analyzed
int nValues; // number of values successfully parsed by scanf
printf("CS201 - A01p - %s\n\n", studentName);
bigOrSmallEndian();
for (;;) {
if (argc == 1) // allow grading script to control ...
printf("> "); // ... whether prompt character is printed
nValues = getNextHexInt(&i);
printf("0x%08X\n", i);
if (! nValues) { // encountered bad input
printf("bad input\n");
while (getchar() != '\n') ; // flush bad line from input buffer
continue;
}
printNumberData(i);
if (i == 0)
break;
}
printf("\n");
return 0;
}
You are inputting the user's number in getNextHexInt, but printNumberData asks for the input again with another scanf. You don't need the second scanf because the input i is already set to the user's input from getNextHexInt.
here's the code for doing that
float myFloat;
int myInt;
memcpy(&myInt, &myFloat, 4);
int signBit = ((1 << 31) & myInt) >> 31;
printf("%i\n", signBit)
I typed it up in a rush, hopefully it works, ill check it in a sec
Heres a program, but it displays -1 for some reason for sign
#include <string.h>
#include <stdio.h>
int main()
{
float a = 1337;
int* b = (int*)&a;
int signbit = ((1 << 31) & *b) >> 31;
printf("%i\n", signbit);
a *= -1;
signbit = ((1 << 31) & *b) >> 31;
printf("%i\n", signbit);
return 0;
}

Compare part of sha1 digest with hex string in C

I have a string for which I compute a sha1 digest like this:
SHA1(sn, snLength, sha1Bin);
If I'm correct this results in a 20 byte char (with binary data). I want to compare the last 3 bytes of this char with another char. This char contains the string "6451E6". 64, 51 & E6 are hex values. How do I convert "6451E6" so that I can compare it via:
if(memcmp(&sha1Bin[(20 - 3)], theVarWithHexValues, 3) == 0)
{
}
I have this function:
/*
* convert hexadecimal ssid string to binary
* return 0 on error or binary length of string
*
*/
u32 str2ssid(u8 ssid[],u8 *str) {
u8 *p,*q = ssid;
u32 len = strlen(str);
if( (len % 2) || (len > MAX_SSID_OCTETS) )
return(0);
for(p = str;(*p = toupper(*p)) && (strchr(hexTable,*p)) != 0;) {
if(--len % 2) {
*q = ((u8*)strchr(hexTable,*p++) - hexTable);
*q <<= 4;
} else {
*q++ |= ((u8*)strchr(hexTable,*p++) - hexTable);
}
}
return( (len) ? 0 : (p - str) / 2);
}
which does the same but I'm new to C and don't understand it :-(
It's easier to go the other way — convert the binary data to a hex string for comparison:
char suffix[7];
sprintf(suffix, "%02x%02x%02x", sha1Bin[17], sha1Bin[18], sha1Bin[19]);
return stricmp(suffix, theVarWithHexValues) == 0;
Even if you prefer converting to binary, sscanf(...%2x...) is better than manually parsing hex numbers.
Fix for AShelly's code:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int hashequal(const unsigned char *sha1Bin, const char *hexstr) {
unsigned long hexvar = strtoul(hexstr, NULL, 16);
unsigned char theVarWithHexValues[] = { hexvar >> 16, hexvar >> 8, hexvar };
return memcmp(sha1Bin + 17, theVarWithHexValues, 3) == 0;
}
int main() {
unsigned char sha1Bin[20];
sha1Bin[17] = 0x64;
sha1Bin[18] = 0x51;
sha1Bin[19] = 0xE6;
printf("%d\n", hashequal(sha1Bin, "6451E6"));
printf("%d\n", hashequal(sha1Bin, "6451E7"));
}
If theVarWithHexValues is indeed a constant of some sort, then the easiest thing would be to put it into binary form directly. Instead of:
const char *theVarWithHexValues = "6451E6";
use:
const char *theVarWithHexValues = "\x64\x51\xE6";
...then you can just memcmp() directly.
char* hexstr = "6451E6";
unsigned long hexvar = strtoul(hexstr, NULL, 16);
hexvar = htonl(hexvar)<<8; //convert to big-endian and get rid of zero byte.
memcmp(&sha1Bin[(20 - 3)], (char*)hexvar, 3)

Resources