I have different hexadecimal data are coming and stored into an integer type register.
When I use fprint I can see the following:
0x3076
0x307c
.
.
.
However, I would like to show a Decimal version of above-mention Hex data as follows.
12406
12412
.
.
.
In theory, let's say for the first value you do the following to convert it to decimal.
(6* 16^0)+(7 * 16^1)+(0*16^2)+(3*16^3)=6 + 112+ 0 + 12288 = 12406
So IF I have the character-based version of "0x3076" and also, IF I am able to get each single characters 6 - 7 - 0 - 3, I can calculate the decimal amount!
So, I decided to divide "3076" by 1000. I was expected to get 3, but I got TWO characters instead! however, if I was able to get 3 for the remainder of "307c" I am not able to get "C". If it was decimal this might work not hex!
Also, I tried "strtol" command. As I use Cygwin to compile my code, I am not sure where the error is! What did I do wrong?
So, I just need to find a way to get EACH SINGLE character out of the HEX data!
Any idea please?
P.S.
Here is my code in order to help you to give me an idea.
int get_readings(int source, int phase, int max_tries)
{
uint8_t buf[MAX_IEC1107_MSG_BODY];
uint8_t inbuf[MAX_IEC1107_MSG_BODY];
int inlen;
uint8_t *s;
int32_t value;
int status;
double voltage;
double current;
double active_power;
double reactive_power;
double apparent_power;
double power_factor;
double frequency;
s = buf;
*s++ = HOST_CMD_GET_READINGS_PHASE_1 + phase;
*s++ = 0x00;
if (max_tries != 1)
meter_set_max_tries(&emeter[source].meter_msg, max_tries);
if (meter_exchange(&emeter[source].meter_msg, buf, 2, inbuf, &inlen)
&&
inbuf[1] != 0xFF)
{
emeter[source].no_response = FALSE;
s = inbuf;
/* Get current readings */
value = (s[3] << 8) | s[2];
fprint(stderr, "value:" %p\n, value); // this give me HEX code
.
.
.
When reading in a string representing a number in hexadecimal, use strtol() to convert it to a long. Then if you want to print the number in decimal, use printf() with a %d format specifier.
char num[]="0x3076";
long n = strtol(num, NULL, 16);
printf("n=%ld\n", n); // prints 12406
Once you read in the strings as longs using strtol and operate on the longs, the math should work itself out.
unsigned n;
sscanf("0x3076", "%x", &n);
printf("%u\n", n);
Only with the following line I could solve the issue!
fprintf(stderr, "Voltage: %.2f\n", value/100.00);
value was shown as HEX as I used to use %p! Then I changed to x! and as I need to have 124.06 not 12406, in other words 2 decimal points, I added .2f!
Thank you all!
1) for printing only:
#include <stdio.h>
#include <stdlib.h>
int main(){
int a=0;
scanf("%x",&a);
printf("%d\n",a);
system("pause");
return 0;
}
2) for calculation use:
#include<stdio.h>
#include<stdlib.h>
int CharToDec(char c){
if(c>='0' && c<='9') return c-'0';
if(c>='a' && c<='f') return c-'a'+10;
if(c>='A' && c<='F') return c-'A'+10;
return 0;
}
int main(int argc, char *argv[]){
char H[10];
char *P;
int p=1,d=0;
printf("Entrez Hexadecimale nombre:");
scanf("%s",H);
for(P=H;*P;P++);
for(P--;P>=H;P--){
d = d + (CharToDec(*P) * p);
p = p*16;
}
printf("%d\n",d);
system("pause");
return 0
}
You are confusing "integer" and "decimal" -- an "integer" is a number stored in a register or variable, while a "decimal" is a string of characters that represent a number in base 10.
So converting from hexadecimal to decimal is a two-step process. You first convert the hexadecimal to integer (which you appear to have done, with your "In theory" equation). You then convert the integer to decimal.
There are lots of ways to do either of these tasks, strtol and scanf will convert either hexadecimal or decimal to integer. printf can convert integer to either hexedecimal or decimal. Or you can write your own routines that manipulate characters to do either of these things.
Related
I am learning C in school, and I am having a little difficulty on my project.
Basically, I am writing a function that gets a string containing a positive integer. The function subtracts 1 from that integer and puts the obtained value in the string.
So , if I have this ;
char nums[] = "2462";
how do I write a function that will subtract 1 from the integer, so that the result is "2461"??
First, convert the character array into an integer.
You can use atoi (ASCII to Integer), but because it returns 0 on error there's no way to tell the difference between successfully converting "0" and an error.
Instead use strtol (STRing TO Long integer).
// end stores where parsing stopped.
char *end;
// Convert nums as a base 10 integer.
// Store where the parsing stopped in end.
long as_long = strtol(nums, &end, 10);
// If parsing failed, end will point to the start of the string.
if (nums == end) {
perror("Parsing nums failed");
}
Now you can subtract, turn the integer back into a string with sprintf, and put it in nums.
sprintf(nums, "%ld", as_long - 1);
This is not entirely safe. Consider if nums is "0". It only has 1 byte of space. If we subtract 1 then we have "-1" and we're storing 2 characters where we only have memory for 1.
For the full explanation of how to do this safely, see How to convert an int to string in C?.
Alternatively, don't store it, just print it.
printf("%ld", as_long - 1);
One way is to convert string -> int -> string.
You can do this by using atoi and sprintf.
Simple implementation (far from perfect):
#include <stdlib.h>
#include <stdio.h>
int main()
{
int a;
char b[5];
a = atoi("2462");
a--;
sprintf(b, "%d", a);
printf("%s\n", b);
return 1;
}
I try to print a negative number in hex and I want it to be in 6 char.
For example, -132 in hex is ffffff7c and the wanted output should be ffff7c.
For positive number this line work:
fprintf(fd,"%07d \t%06x \n",i+100,instruction_data[i]);
for negative numbers, I get two more f.
Based on the solution provided by #pmg in comments:
#include <stdio.h>
void print_hex (int val, size_t digits)
{
char tmp[100];
size_t length = sprintf(tmp, "%X", (unsigned int)val);
if(digits > length)
{
digits = length;
}
printf("%.*s\n", digits, tmp+length-digits);
}
int main (void)
{
print_hex(-132,6); // FFFF7C
print_hex(-132,3); // F7C
print_hex(-132,666); // FFFFFF7C
print_hex(132,2); // 84
}
Explanation:
The sprintf call converts the passed number to ASCII hex and stores it in a temporary buffer.
The cast to unsigned int is necessary for the %X specifier.
sprintf returns the number of characters written.
if(digits > length) { digits = length; } is some simple error handling to ensure that the function doesn't attempt to print more digits than present.
The %.*s trick in printf allows the first parameter to specify how many characters to write, variably.
tmp+length-digits is pointer arithmetic ensuring to print digits number of characters from the end of the string, rather than from the beginning, which we would have gotten if we just wrote tmp.
To only print 6 hex digits for negative numbers on 32-bit architectures, you can simply mark the value with 0xffffff:
fprintf(fd, "%07d \t%.6x \n", i + 100, instruction_data[i] & 0xffffffU);
To specify the number of digits as an int variable:
int digits = 6;
...
fprintf(fd, "%07d \t%.*x \n", i + 100, digits,
instruction_data[i] & ~(~0U << (digits * 2) << (digits * 2)));
When I try and convert my binary string to int I am receiving a couple of mistakes that I can not figure out. First I am reading from a file and the leading zeros are not showing up when I convert and the new line is showing zero.
This code I am using from this questions: Convert binary string to hexadecimal string C
char* binaryString[100];
// convert binary string to integer
int value = (int)strtol(binaryString, NULL, 2);
//output string as int
printf("%i \n",value)
My txt file and what I am expecting as an output:
00000000
000000010001001000111010
00000000000000000000000000000001
101010111100110100110001001001000101
What I get:
0
0
70202
1
-1127017915
This line:
char* binaryString[100];
Is declaring an array of 100 char pointers (or 100 strings). You probably meant this to declare a buffer of 100 characters to be interpreted as a single string:
char binaryString[100];
char *binaryString[100];
// You are creating an array of pointers in this scenario, use char binaryString[100] instead;
int value = (int)strtol(binaryString, NULL, 2);
// 101010111100110100110001001001000101 Is a 36 bit number, int (in most implementations) is 32 bit. use long long (64 bit in visual c++) as type and strtoll as function instead.
printf("%i \n",value)
Must be printf("%lld \n", value).
In summary:
#include "stdio.h"
#include "stdlib.h" // required for strtoll
int main(void)
{
char str[100] = "101010111100110100110001001001000101";
long long val = 0;
val = strtoll(str, NULL, 2);
//output string as int
printf("%lld \n", val);
return 0;
}
if im understanding this correctly you want to take a binary string so ones and zeros and convert it to a Hex string so 0-F, if so the problem is with the Write not the Convert, you specified '%i' as the written value format, what you need to do for hex is specify '%x'
Change this "printf("%i \n",value)" to "printf("%x\n",value)"
So I have an assignment to figure out whether a number on the command line is either an integer or a double.
I have it mostly figured it out by doing:
sscanf(argv[x], "%lf", &d)
Where "d" is a double. I then cast it to an int and then subtract "d" with itself to check to see if it is 0.0 as such.
d - (int)d == 0.0
My problem is if the command line arguments contains doubles that can be technically classified as ints.
I need to classify 3.0 as a double whereas my solution considers it an int.
For example initializing the program.
a.out 3.0
I need it to print out
"3.0 is a double"
However right now it becomes
"3 is an int."
What would be a way to check for this? I did look around for similar problems which led me to the current solution but just this one edge case I do not know how to account for.
Thank you.
For example, a way like this:
#include <stdio.h>
int main(int argc, char *argv[]){
if(argc != 2){
puts("Need an argument!");
return -1;
}
int int_v, read_len = 0;
double double_v;
printf("'%s' is ", argv[1]);
//==1 : It was able to read normally.
//!argv[1][read_len] : It used all the argument strings.
if(sscanf(argv[1], "%d%n", &int_v, &read_len) == 1 && !argv[1][read_len])
puts("an int.");
else if(sscanf(argv[1], "%lf%n", &double_v, &read_len) == 1 && !argv[1][read_len])
puts("a double.");
else
puts("isn't the expected input.");
}
To test if a string will covert to a int and/or double (completely, without integer overflow, without undefined behavior), call strtol()/strtod(). #Tom Karzes
The trouble with a sscanf() approach is that the result is undefined behavior (UB) on overflow. To properly detect, use strtol()/strtod().
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
bool is_int(const char *src) {
char *endptr;
// Clear, so it may be tested after strtol().
errno = 0;
// Using 0 here allows 0x1234, octal 0123 and decimal 1234.
// or use 10 to allow only decimal text.
long num = strtol(src, &endptr, 0 /* or 10 */);
#if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
if (num < INT_MIN || num > INT_MAX) {
errno = ERANGE;
}
#endif
return !errno && endptr > src && *endptr == '\0';
}
bool is_double(const char *src) {
char *endptr;
// Clear, so it may be tested after strtod().
strtod(src, &endptr);
// In this case, detecting over/underflow IMO is not a concern.
return endptr > src && *endptr == '\0';
}
It is not entirely clear what the specific expectations are for your program, but it has at least something to do with the form of the input, since "3.0" must be classified as a double. If the form is all it should care about, then you should not try to convert the argument strings to numbers at all, for then you will run into trouble with unrepresentable values. In that case, you should analyze the character sequence of the argument to see whether it matches the pattern of an integer, and if not, whether it matches the pattern of a floating-point number.
For example:
int main(int argc, char *argv[]) {
for (int arg_num = 1; arg_num < argc; arg_num++) {
char *arg = argv[arg_num];
int i = (arg[0] == '-' || arg[0] == '+') ? 1 : 0; // skip any leading sign
// scan through all the decimal digits
while(isdigit(arg[i])) {
++i;
}
printf("Argument %d is %s.\n", arg_num, arg[i] ? "floating-point" : "integer");
}
}
That makes several assumptions, chief among them:
the question is strictly about form, so that the properties of your system's built-in data types (such as int and double) are not relevant.
each argument will have the form of either an integer or a floating-point number, so that eliminating "integer" as a possibility leaves "floating-point" as the only alternative. If "neither" is a possibility that must also be accommodated, then you'll also need to compare the inputs that do not have integer form to a pattern for floating-point numbers, too.
only decimal (or smaller radix) integers need be accommodated -- not, for example, hexadecimal inputs.
Under those assumptions, particularly the first, it is not just unnecessary but counterproductive to attempt to convert the arguments to one of the built-in numeric data types, because you would then come to the wrong conclusion about arguments that, say, are not within the bounds of representable values for those types.
For example, consider how the program should classify "9000000000". It has the form of an integer, but supposing that your system's int type has 31 value bits, that type cannot accommodate a value as large as the one the string represents.
int main (int argc,char *argv[])
{
if(argc==2)
{
int i;
double d;
d=atof(argv[1]);
i=atoi(argv[1]);
if(d!=i)
printf("%s is a double.",argv[1]);
else if(d==i)
printf("%s is an int.",argv[1]);
}
else
printf("Invalid input\n");
return 0;
}
You must add #include <stdlib.h>
I'm writing a small command-line program that reads two floats, an int, and a small string (4 chars max) from stdin. I'm trying to figure out the buffer size I should create and pass to fgets. I figured I could calculate this based on how many digits should be included in the maximum values of float and int respectively, like so:
#include <float.h>
#include <limits.h>
...
int fmax = log10(FLOAT_MAX) + 2; // Digits plus - and .
int imax = log10(INT_MAX) + 1; // Digits plus -
int buflen = 4 + 2*fmax + imax + 4; // 4 chars, 2 floats, 1 int, 3 spaces and \n
...
fgets(inbuf, buflen + 1, stdin);
But it's occurred to me that this might not actually be correct. imax ends up being 10 on my system, which seems a bit low, while fmax if 40. (Which I'm thinking is a bit high, given that longer values may be represented with e notation.)
So my question is: is this the best way to work this out? Is this even necessary? It just feels more elegant than assigning a buffer of 256 and assuming it'll be enough. Call it a matter of pride ;P.
This type of thing is a place where I would actually use fscanf rather than reading into a fixed-size buffer first. If you need to make sure you don't skip a newline or other meaningful whitespace, you can use fgetc to process character-by-character until you get the the beginning of the number, then ungetc before calling fscanf.
If you want to be lazy though, just pick a big number like 1000...
This is defined for base 10 floating point numbers (#include <float.h> or the equivalent member of std::numeric_limits<float_type>):
FLT_MAX_10_EXP // for float
DBL_MAX_10_EXP // for double
LDBL_MAX_10_EXP // for long double
As is the maximum precision for decimals in base 10:
FLT_DIG // for float
DBL_DIG // for double
LDBL_DIG // for long double
Although it really depends on what you define to be a valid floating point number. You could imagine someone expecting:
00000000000000000000000000000000000000000000000000.00000000000000000000
to be read in as zero.
I'm sure there's a good way to determine the maximum length of a float string algorithmically, but what fun is that? Let's figure it out by brute force!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int, char **)
{
float f;
unsigned int i = -1;
if (sizeof(f) != sizeof(i))
{
printf("Oops, wrong size! Change i to a long or whatnot so the sizes match.\n");
return 0;
}
printf("sizeof(float)=%li\n", sizeof(float));
char maxBuf[256] = "";
int maxChars = 0;
while(i != 0)
{
char buf[256];
memcpy(&f, &i, sizeof(f));
sprintf(buf, "%f", f);
if ((i%1000000)==0) printf("Calclating # %u: buf=[%s] maxChars=%i (maxBuf=[%s])\n", i, buf, maxChars, maxBuf);
int numChars = strlen(buf);
if (numChars > maxChars)
{
maxChars = numChars;
strcpy(maxBuf, buf);
}
i--;
}
printf("Max string length was [%s] at %i chars!\n", maxBuf, maxChars);
}
Looks like the answer might be 47 characters per float (at least on my machine), but I'm not going to let it run to completion so it's possibly more.
Following the answer from #MSN, you can't really know your buffer is large enough.
Consider:
const int size = 4096;
char buf[size] = "1.";
buf[size -1 ] = '\0';
for(int i = 2; i != size - 1; ++i)
buf[i] = '0';
double val = atof(buf);
std::cout << buf << std::endl;
std::cout << val << std::endl;
Here atof() handles (as it is supposed to), a thousand character representation of 1.
So really, you can do one or more of:
Handle the case of not having a large enough buffer
Have better control over the input file
Use fscanf directly, to make the buffer size someone else's problem