I am tring to convert hex to unsigned int from strtoul function. But I am getting output as ffffffff.
I have used stdlib.h library.
Can someone tell me at what part I am wrong?
void main()
{
char str1[33] = "88CC6069E4EDF969773369F988CC969F";
unsigned int hex_int;
hex_int = strtoul(str1, NULL, 16); //converting to unsigned int
printf("%x\n", hex_int);
}
C11 7.22.1.4p8:
The strtol, strtoll, strtoul, and strtoull functions return the converted value, if any. If no conversion could be performed, zero is returned. If the correct value is outside the range of representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, or ULLONG_MAX is returned (according to the return type and sign of the value, if any), and the value of the macro ERANGE is stored in errno.
Try the following code:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char str1[] = "88CC6069E4EDF969773369F988CC969F";
errno = 0; // must reset errno first, otherwise it can retain an old value
unsigned long int hex_int = strtoul(str1, NULL, 16);
if (errno != 0) {
perror("strtoul failed:");
}
}
On my machine it will output
strtoul failed: Numerical result out of range
You make 2 mistakes: the value returned by strtoul is an unsignedlong; and even then, your value is 128 bits which is larger than the unsigned long on any common platform.
And also, do not bound the length of str1 - it should be at least 33 characters; or use a pointer-to-char instead:
char *str1 = "88CC6069E4EDF969773369F988CC969F";
And, int main(void).
Another manual version :
#include <ctype.h> // To use isdigit(), this function is not necessary if you can use ASCII table
const int asciiNumberBetweenDigitAndAlpha = 7; // see ASCII table
int str2[32];
const int size = sizeof(str1);
for (int i = 0; i < size - 1; i++)
{
if (isdigit(readLine[i]))
str2[i] = str1[i] - '0'; // In ASCII '0' = 48; '1' = 49..
else
str2[i] = str1[i] - '0' - asciiNumberBetweenDigitAndAlpha;
}
You could use, as an alternative to the ugly elsepart :
if (str1[i] == 'A')
str2[i] = 10;
else if (str1[i] == 'B')
str2[i] = 11;
...
use strtoull for larger numbers.
https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/com.ibm.zos.v2r3.bpxbd00/strtoull.htm
Related
I'm trying to square every digit of a number, concatenate them and return the result as an integer.
For example, if I run 9191 through the function, 811181 will come out, because 9^2 is 81 and 1^2 is 1.
I made a function (don't even know if it's the most optimal, I'm quite new with the programming) so that the number gets converted into a string, then I loop through it, convert the single digit from a char back to a number and make the square of it. Then I save the new result in the form of a string, and concatenate it to another string that will be the final result.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 128
unsigned long long square_digits (unsigned n)
{
char n_str[MAX];
char c_str[MAX];
char s_result[MAX];
unsigned long long converted, result;
int i, len;
sprintf(n_str, "%u", n);
len = strlen(n_str);
s_result[0] = '\0';
for (i = 0; i < len; ++i)
{
converted = n_str[i] - '0';
converted = converted * converted;
sprintf(c_str, "%llu", converted);
strcat(s_result, c_str);
}
result = strtol(s_result, NULL, 10);
return result;
}
The tests are made through the following sequence of numbers:
unsigned long long square_digits (unsigned n);
#define do_test(n, expected) \
do { \
unsigned long long actual = square_digits(n); \
cr_assert_eq(actual, expected, "for n = %u, expected %llu, but got %llu", n, expected, actual);\
} while (false)
Test(test_suite, sample_tests)
{
do_test( 3212u, 9414ull);
do_test( 2112u, 4114ull);
do_test( 0u, 0ull);
do_test( 999u, 818181ull);
do_test( 10001u, 10001ull);
do_test(3210987654u, 9410816449362516ull);
do_test(3999999999u, 9818181818181818181ull); // :p
do_test( UINT_MAX, 164811681364948125ull);
}
First 6 tests are passed correctly, but then I got an unexpected result (the one with the ":p" comment).
sample_tests
Test Passed
Test Passed
Test Passed
Test Passed
Test Passed
Test Passed
for n = 3999999999, expected 9818181818181818181, but got 9223372036854775807
What is happening and how can I fix that? Is there another way to make this work?
9818181818181818181 is a 64-bit unsigned number with its most significant bit set.
OP's strtol(s_result, NULL, 10) is for signed conversion and 9818181818181818181 is outside its range. strtol() did the best it could and returned LONG_MAX, 9223372036854775807 or 0x7FFF_FFFF_FFFF_FFFF.
Use a matching conversion function: strtoull().
unsigned long long result;
...
// result = strtol(s_result, NULL, 10);
result = strtoull(s_result, NULL, 10);
More advanced code would check the conversion:
char *endptr;
errno = 0;
result = strtoull(s_result, &endptr, 10);
if (s_result == endptr || errno) {
puts("Trouble in conversion");
}
Right now I am trying to convert an int to a char in C programming. After doing research, I found that I should be able to do it like this:
int value = 10;
char result = (char) value;
What I would like is for this to return 'A' (and for 0-9 to return '0'-'9') but this returns a new line character I think.
My whole function looks like this:
char int2char (int radix, int value) {
if (value < 0 || value >= radix) {
return '?';
}
char result = (char) value;
return result;
}
to convert int to char you do not have to do anything
char x;
int y;
/* do something */
x = y;
only one int to char value as the printable (usually ASCII) digit like in your example:
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int inttochar(int val, int base)
{
return digits[val % base];
}
if you want to convert to the string (char *) then you need to use any of the stansdard functions like sprintf, itoa, ltoa, utoa, ultoa .... or write one yourself:
char *reverse(char *str);
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *convert(int number, char *buff, int base)
{
char *result = (buff == NULL || base > strlen(digits) || base < 2) ? NULL : buff;
char sign = 0;
if (number < 0)
{
sign = '-';
}
if (result != NULL)
{
do
{
*buff++ = digits[abs(number % (base ))];
number /= base;
} while (number);
if(sign) *buff++ = sign;
if (!*result) *buff++ = '0';
*buff = 0;
reverse(result);
}
return result;
}
A portable way of doing this would be to define a
const char* foo = "0123456789ABC...";
where ... are the rest of the characters that you want to consider.
Then and foo[value] will evaluate to a particular char. For example foo[0] will be '0', and foo[10] will be 'A'.
If you assume a particular encoding (such as the common but by no means ubiquitous ASCII) then your code is not strictly portable.
Characters use an encoding (typically ASCII) to map numbers to a particular character. The codes for the characters '0' to '9' are consecutive, so for values less than 10 you add the value to the character constant '0'. For values 10 or more, you add the value minus 10 to the character constant 'A':
char result;
if (value >= 10) {
result = 'A' + value - 10;
} else {
result = '0' + value;
}
Converting Int to Char
I take it that OP wants more that just a 1 digit conversion as radix was supplied.
To convert an int into a string, (not just 1 char) there is the sprintf(buf, "%d", value) approach.
To do so to any radix, string management becomes an issue as well as dealing the corner case of INT_MIN
The following C99 solution returns a char* whose lifetime is valid to the end of the block. It does so by providing a compound literal via the macro.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// Maximum buffer size needed
#define ITOA_BASE_N (sizeof(unsigned)*CHAR_BIT + 2)
char *itoa_base(char *s, int x, int base) {
s += ITOA_BASE_N - 1;
*s = '\0';
if (base >= 2 && base <= 36) {
int x0 = x;
do {
*(--s) = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[abs(x % base)];
x /= base;
} while (x);
if (x0 < 0) {
*(--s) = '-';
}
}
return s;
}
#define TO_BASE(x,b) itoa_base((char [ITOA_BASE_N]){0} , (x), (b))
Sample usage and tests
void test(int x) {
printf("base10:% 11d base2:%35s base36:%7s ", x, TO_BASE(x, 2), TO_BASE(x, 36));
printf("%ld\n", strtol(TO_BASE(x, 36), NULL, 36));
}
int main(void) {
test(0);
test(-1);
test(42);
test(INT_MAX);
test(-INT_MAX);
test(INT_MIN);
}
Output
base10: 0 base2: 0 base36: 0 0
base10: -1 base2: -1 base36: -1 -1
base10: 42 base2: 101010 base36: 16 42
base10: 2147483647 base2: 1111111111111111111111111111111 base36: ZIK0ZJ 2147483647
base10:-2147483647 base2: -1111111111111111111111111111111 base36:-ZIK0ZJ -2147483647
base10:-2147483648 base2: -10000000000000000000000000000000 base36:-ZIK0ZK -2147483648
Ref How to use compound literals to fprintf() multiple formatted numbers with arbitrary bases?
Check out the ascii table
The values stored in a char are interpreted as the characters corresponding to that table. The value of 10 is a newline
So characters in C are based on ASCII (or UTF-8 which is backwards-compatible with ascii codes). This means that under the hood, "A" is actually the number "65" (except in binary rather than decimal). All a "char" is in C is an integer with enough bytes to represent every ASCII character. If you want to convert an int to a char, you'll need to instruct the computer to interpret the bytes of an int as ASCII values - and it's been a while since I've done C, but I believe the compiler will complain since char holds fewer bytes than int. This means we need a function, as you've written. Thus,
if(value < 10) return '0'+value;
return 'A'+value-10;
will be what you want to return from your function. Keep your bounds checks with "radix" as you've done, imho that is good practice in C.
1. Converting int to char by type casting
Source File charConvertByCasting.c
#include <stdio.h>
int main(){
int i = 66; // ~~Type Casting Syntax~~
printf("%c", (char) i); // (type_name) expression
return 0;
}
Executable charConvertByCasting.exe command line output:
C:\Users\boqsc\Desktop\tcc>tcc -run charconvert.c
B
Additional resources:
https://www.tutorialspoint.com/cprogramming/c_type_casting.htm
https://www.tutorialspoint.com/cprogramming/c_data_types.htm
2. Convert int to char by assignment
Source File charConvertByAssignment.c
#include <stdio.h>
int main(){
int i = 66;
char c = i;
printf("%c", c);
return 0;
}
Executable charConvertByAssignment.exe command line output:
C:\Users\boqsc\Desktop\tcc>tcc -run charconvert.c
B
You can do
char a;
a = '0' + 5;
You will get character representation of that number.
Borrowing the idea from the existing answers, i.e. making use of array index.
Here is a "just works" simple demo for "integer to char[]" conversion in base 10, without any of <stdio.h>'s printf family interfaces.
Test:
$ cc -o testint2str testint2str.c && ./testint2str
Result: 234789
Code:
#include <stdio.h>
#include <string.h>
static char digits[] = "0123456789";
void int2str (char *buf, size_t sz, int num);
/*
Test:
cc -o testint2str testint2str.c && ./testint2str
*/
int
main ()
{
int num = 234789;
char buf[1024] = { 0 };
int2str (buf, sizeof buf, num);
printf ("Result: %s\n", buf);
}
void
int2str (char *buf, size_t sz, int num)
{
/*
Convert integer type to char*, in base-10 form.
*/
char *bufp = buf;
int i = 0;
// NOTE-1
void __reverse (char *__buf, int __start, int __end)
{
char __bufclone[__end - __start];
int i = 0;
int __nchars = sizeof __bufclone;
for (i = 0; i < __nchars; i++)
{
__bufclone[i] = __buf[__end - 1 - i];
}
memmove (__buf, __bufclone, __nchars);
}
while (num > 0)
{
bufp[i++] = digits[num % 10]; // NOTE-2
num /= 10;
}
__reverse (buf, 0, i);
// NOTE-3
bufp[i] = '\0';
}
// NOTE-1:
// "Nested function" is GNU's C Extension. Put it outside if not
// compiled by GCC.
// NOTE-2:
// 10 can be replaced by any radix, like 16 for hexidecimal outputs.
//
// NOTE-3:
// Make sure inserting trailing "null-terminator" after all things
// done.
NOTE-1:
"Nested function" is GNU's C Extension. Put it outside if not
compiled by GCC.
NOTE-2:
10 can be replaced by any radix, like 16 for hexidecimal outputs.
NOTE-3:
Make sure inserting trailing "null-terminator" after all things
done.
I am trying to convert number stored in the c string to long int. But I am not getting the expected output:
char str[] = "987654321012345";
long int num ;
num = 0;
//num = atol(str);
num = strtol(str, (char **) NULL, 10);
printf("%ld", num);
Output : 821493369
gcc version 4.4.7 20120313 (Red Hat 4.4.7-16)
Can you please advise what am I doing wrong here? Thanks.
In addition to using long long, you can use exact width types from stdint.h. For instance, to guarantee and 64-bit signed number you can use the int64_t type. Regardless what you do, do not cast NULL to char ** and always validate your conversions. E.g.,
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main (void) {
char str[] = "987654321012345";
long num = 0;
errno = 0;
num = strtol (str, NULL, 10);
if (errno) { /* validate strtol conversion */
perror ("strtol conversion failed.");
return 1;
}
printf ("%ld\n", num);
return 0;
}
Example Use/Output
$ ./bin/strtoltst
987654321012345
There are additional error checks you can do on the conversion, but at minimum, make sure errno is not set following your call to strtol or strtoll.
If you would like to use the guaranteed width types, then you can make the following changes:
...
#include <stdint.h>
...
int64_t num = 0;
...
num = strtoll (str, NULL, 10);
The result is the same.
I could reproduce and fix.
Code reproducing the problem
#include <stdio.h>
//#include <stdlib.h>
int main()
{
char str[] = "987654321012345";
long int num ;
char *ix;
num = 0;
//num = atol(str);
num = strtol(str, &ix, 10);
printf("%ld\n", num);
printf("%lu\n", sizeof(long));
return 0;
}
Gives as expected:
821493369
8
After a compilation warning
warning: implicit declaration of strtoll
Reason: as strtoll is undeclared, it is assumed to return an int, so the long value is first truncate to an int and than promoted back to a long.
Fix: just uncomment the #include <stdlib.h> line...
Conclusion: warnings are not meant to be ignored!
You should use long long as datatype for your number.
char str[] = "987654321012345";
long long num = strtoll(str, (char **)NULL, 10);
printf("%lld", num);
According to the C data type:
Long signed integer type. Capable of containing at least the [−2,147,483,647, +2,147,483,647] range; thus, it is at least 32 bits in size.
Long unsigned integer type. Capable of containing at least the [0, 4,294,967,295] range;
Is not enough, so you need a long long or unsigned long long and use %lli or %llu
"987654321012345" is too large.
Strol is outputing long type variable.
Long value is –2,147,483,648 to 2,147,483,647.
try
char str[] = "987654321012345";
char *pEnd;
long long num;
num = 0;
num = strtoull(str,&pEnd, 10);
printf("%lld", num);
return 0;
long long instead of long
strtoull instead of strtol
%lld instead of %ld
I have a 4 byte string of hex characters and I want to convert them into a 2 byte integer in c.
I cannot use strtol, fprintf or fscanf.
I want this:-
unsigned char *hexstring = "12FF";
To be converted to this:-
unsigned int hexInt = 0x12FF
EDIT: Doh, just read azmuhak's suggested link. This is definitely a duplicate of that question. The answer in azmuhak's link is also more complete because it deals with "0x" prefixes...
The following will work with out using the standard library...
See it on ideone here
#include <stdio.h>
#define ASCII_0_VALU 48
#define ASCII_9_VALU 57
#define ASCII_A_VALU 65
#define ASCII_F_VALU 70
unsigned int HexStringToUInt(char const* hexstring)
{
unsigned int result = 0;
char const *c = hexstring;
char thisC;
while( (thisC = *c) != NULL )
{
unsigned int add;
thisC = toupper(thisC);
result <<= 4;
if( thisC >= ASCII_0_VALU && thisC <= ASCII_9_VALU )
add = thisC - ASCII_0_VALU;
else if( thisC >= ASCII_A_VALU && thisC <= ASCII_F_VALU)
add = thisC - ASCII_A_VALU + 10;
else
{
printf("Unrecognised hex character \"%c\"\n", thisC);
exit(-1);
}
result += add;
++c;
}
return result;
}
int main(void)
{
printf("\nANSWER(\"12FF\"): %d\n", HexStringToUInt("12FF"));
printf("\nANSWER(\"abcd\"): %d\n", HexStringToUInt("abcd"));
return 0;
}
The code could be made more efficient and I use the toupper library function, but you could easily implement that yourself...
Also, this won't parse strings beginning with "0x"... but you could add a quick check for that at the beginning of the function and just chew up those characters...
You could use strtol() from stdlib.h
http://www.tutorialspoint.com/c_standard_library/c_function_strtol.htm
char str[30] = "0x12FF";
char **ptr;
long val;
val = strtol(str, ptr, 16);
Is there any API to check if any number exceeds it's range?
My number is stored as string. char *ptr = "123456789"
API should do: int a = api(ptr, long) if a==-1 suppose value exceeds.
Please note: We can't parse the string and check because it will automatically wrap it to the other side, and make it within the range.
Thanks in advance
Please checkout strtol and strtoul.
See this example:
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
int main (int argc, char const* argv[])
{
char a[] = "123";
char c[] = "123134123412341234";
long b, d;
errno = 0;
b = strtol(a, NULL, 10);
if((b == LONG_MAX || b == LONG_MIN) && errno == ERANGE ){
printf("%s Out of range\n", a);
}
errno = 0;
d = strtol(c, NULL, 10);
if((d == LONG_MAX || d == LONG_MIN) && errno == ERANGE ){
printf("%s Out of range\n", c);
}
return 0;
}
Edits:
Changed int to long for b and d.
Setting errno to 0 before calling into c library.
Checking for LONG_MIN also for errors.
Changed the order for checks (according to comment below)
Well, you can still check. Just build up the number and check to see if the number indeed became bigger or smaller.
int i = 0; // pos indicator
int r = 0; // result
int c = 0; // check
while(ptr[i])
{
c = r;
r = r * 10 + (ptr[i++] - '0');
if(r < c)
print("overflow happened!\n");
}
Edit: Note that this won't work with unsigned datatypes as it's too easy to overflow far enough to still pass the check.
Just use strol() or strtoll() and check errno. For smaller datatypes you need to make a very simple function that compares against USHRT_MAX, UINT_MAX etc from limits.h.
man strol and man limits.h for more information.