C - Convert long int to signed hex string - c

MASSIVE EDIT:
I have a long int variable that I need to convert to a signed 24bit hexadecimal string without the "0x" at the start. The string must be 6 characters followed by a string terminator '\0', so leading zeros need to be added.
Examples:
[-1 -> FFFFFF] ---
[1 -> 000001] ---
[71 -> 000047]
Answer
This seems to do the trick:
long int number = 37;
char string[7];
snprintf (string, 7, "%lX", number);

Because you only want six digits, you are probably going to have to do some masking to make sure that the number is as you require. Something like this:
sprintf(buffer, "%06lx", (unsigned long)val & 0xFFFFFFUL);
Be aware that you are mapping all long integers into a small range of representations. You may want to check the number is in a specific range before printing it (E.g. -2^23 < x < 2^23 - 1)

Look at sprintf. The %lx specifier does what you want.

Use itoa. It takes the desired base as an argument.
Or on second thought, no. Use sprintf, which is standard-compliant.

In the title you say you want a signed hex string, but all your examples are unsigned hex strings. Assuming the examples are what you want, the easiest way is
sprintf(buffer, "%06X", (int)value & 0xffffff);

Related

uint64 to string in C

I have a uint64 value that I want to convert into a string because it has to be inserted as the payload of an HTTP POST request.
I've already tried many solutions (ltoa, this solution ) but my problem still remains.
My function is the following:
void check2(char* fingerprint, guint64 s_id) {
//stuff
char poststr[400] = "action=CheckFingerprint&sessionid=";
//convert s_id to, for example, char* myChar
strcat(poststr, myChar);
}
I want to convert s_id to char*. I've tried:
1) char ses[8]; ltoa(s_id,ses,10) but I have a segmentation fault;
2) char *buf; sprintf(buf, "%" PRIu64, s_id);
I'm working on a APIs, so I have seen that when this guint64 variable is printed, it has the following form:
JANUS_LOG(LOG_INFO, "Creating new session: %"SCNu64"\n", session_id);
sprintf is the right way to go with an unsigned 64 bit format specifier.
You'll need to allocate enough space for 16 hex digits and the null byte. Here I've allocated 20 bytes to accommodate a leading 0x as well and then I rounded it up to 20 for no good reason other than it feels better than 19.
char foo[20];
sprintf(foo, "0x%016" PRIx64, (uint64_t)numberToConvert);
will print the number in hex with leading 0x and leading zeros padded up to 16. You do not need the cast if numberToConvert is already a uint64_t
i have a uint64 value that i want to convert into char* because of it have to be inserted as payload of an HTTP POST request.
What you have is a fundamental misunderstanding.
To insert a text representation of your value into a document, you need to convert it to a sequence of characters, which is quite a different thing from a pointer to a character (char *). One of your options, which seems to be what you're really after, is to convert the value to a sequence of characters in the form of a C string -- that is, a null-terminated array of characters. You would then have or be able to obtain a pointer to the first character in the sequence.
That explains what's wrong with this attempted solution:
char *buf;
sprintf(buf, "%" PRIu64, s_id);
You are trying to write the string representation of your number into the array pointed-to by buf, but it doesn't point to one. Not having been initialized or assigned, its value is indeterminate.
Even if you your buf pointed to an array, it is essential that the array be long enough to accommodate all the digits of the value's decimal representation, plus a terminator. That's probably what's wrong with your other attempt:
char ses[8]; ltoa(s_id,ses,10)
An unsigned, 64-bit binary number may require up to 20 decimal digits, plus you need space for a terminator. The array you're providing is not nearly large enough, unless you can be confident that the actual values you're going to write will not exceed 9,999,999 (which is well within the range of a 32-bit integer).

Why does printf convert large numbers?

Why doesn't this work?
printf("%d \n\n\n\n", atoi("11110010100"));
it outputs -1774891788... I just want it outputted as it is. It seems to work just fine if the number is a bit smaller.
atoi returns an int. You pass a string which contains a number bigger than what int(in your implementation) can hold. So, you have an integer overflow.
To print the maximum value an int can hold, include limits.h and print INT_MAX.
int atoi (const char * str) convert string to integer,and the basic signed integer type capable of containing at least the [−32767,+32767] range,
the 11110010100 is bigger than integer storage capability, so you have an overflow.
you can try this method to parse a String to a Double: atof
http://www.lemoda.net/c/string-to-double/

Converting from long to hex in C?

I have this code
char binary[] = "0001001010000011";
long number = strtol(binary, NULL, 16);
printf("%x", number);
I want to convert the string into a hex number. the answer is 1283, but i am getting DF023BCF what am i doing wrong?
The base you specify to strtol is the base to use to parse the input, not the output (which instead is specified by the %x). IOW, that code says to strtol to parse 0001001010000011 as if it were a hexadecimal number (and, by the way, it results in overflow).
The last parameter to strtol is the base that you want to convert from. Since you are providing a binary encoded string you should specify a base 2 conversion.
Here is the correct code:
char binary[] = "0001001010000011";
long number = strtol(binary, NULL, 2);
printf("%x", number);
I would also suggest that binary numbers are not normally signed (especially when 17 digits long), therefore, it seems likely that you may want to use the unsigned version of the function, strtoul() as shown below. Finally, when printf'ing a number into hex format it might be a good idea to indicate hexadecimal with a leading 0x marker. In your case, the answer is 0x1283 but displaying this number as 1283 allows it to be easily confused as a decimal number. Both suggestions are shown below.
const char binary[] = "0001001010000011";
unsigned long number = strtoul(binary, NULL, 2);
printf("0x%x", number);

How to print a unsigned char to a human readable format in c?

I would like to print the unsigned char in this format:
0xff. How can I do so? Thanks.
printf("0x%02X", value & 0xFF);
if you want to values to always be 2 characters. also "& 0xFF" will avoid some values to be printed with a lot of "F" in the front (happens sometimes)
%x is the basic conversion specifier for printing an unsigned int (that's what an unsigned char is converted to when passed to a variadic function, such as printf()) in hexadecimal format with lowercase letters. If you want leading zeroes and at least two digits, use %02x. If, in addition, you want the 0x prefix as well, prepend the # modifier. So your format string will look like
"%#02x"
printf("0x%x\n", variable);
Visit printf documentation page for more details
%x is the format specifier you are looking for.
printf("0x%x\n",your_char);
For chars I use this
printf("0x%hhx\n",your_char);

How do I prevent buffer overflow converting a double to char?

I'm converting a double to a char string:
char txt[10];
double num;
num = 45.344322345
sprintf(txt, "%.1f", num);
and using ".1f" to truncate the decimal places, to the tenths digit.
i.e. - txt contains 45.3
I usually use precision in sprintf to ensure the char buffer is not overflowed.
How can I do that here also truncating the decimal, without using snprintf?
(i.e. if num = 345694876345.3 for some reason)
Thanks
EDIT If num is > buffer the result no longer matters, just do not want to crash. Not sure what would make the most sense in that case.
EDIT2 I should have made it more clear than in just the tag, that this is a C program.
I am having issues using snprintf in a C program. I don't want to add any 3rd party libraries.
Use snprintf() , which will tell you how many bytes were not printed. In general, you should size your array to be large enough to handle the longest string representation of the target integer type. If not known in advance, use malloc() (or asprintf(), which is non-standard, but present on many platforms).
Edit
snprintf() will fail gracefully if the format exceeds the given buffer, it won't overflow. If you don't need to handle that, then simply using it will solve your problem. I can't think of an instance where you would not want to handle that, but then again, I'm not working on whatever you are working on :)
Why not just make your buffer big enough to hold the largest possible string representation of a double?
Assuming a 64-bit double using the IEEE standard for floating point arithmetic, which uses 52 bits for a mantissa: 2^52 = 4,503,599,627,370,500. So we need 16 characters to hold all the digits before and after the decimal point. 19 considering the decimal point, sign character and null terminator.
I would just use a buffer size of at least 20 characters and move on.
If you need to print a double using scientific notation, you will need to add enough space for the exponent. Assuming a 11 bit signed exponent, that's another 4 characters for the exponent plus a sign for the exponent and the letter 'E'. I would just go with 30 characters in that case.
If you absolutely must do it on your own, count the digits in the number before trying to convert:
int whole = num;
int wholeDigits = 0;
do {
++wholeDigits;
}
while (whole /= 10);
double fraction = num - (int) num;
int decimallDigits = 0;
while (fraction > 0) {
++decimalDigits;
fraction *= 10;
fraction = fraction - (int) fraction;
}
int totalLength = decimalDigits ? wholeDigits + decimalDigits + 1 : wholeDigits;
You should probably verify that this ad-hoc code works as advertised before relying on it to guard against crashes. I recommend that you use snprintf or something similar instead of my code, as others have said.
Why do you want to do it without snprintf? You should be using snprintf regardless of whether your format string contains a double, another string or anything else, really. As far as I can see, there's no reason not to.

Resources