converting char array (c string) to _int64 in C - c

I tried this function to convert a string to _int64 but it didn't work :
_int64 lKey = _atoi64("a1234");
lKey value is always zero and doesn't work except the string is only digits like "1234"
I read solutions using C++ string stream but I want to write my application in pure C

The function does indeed work. As the documentation states:
Each function returns the __int64 value produced by interpreting the input characters as a number. The return value is 0 for _atoi64 if the input cannot be converted to a value of that type.
So you have to make sure that a correct string is passed. Otherwise, the return value will always be zero. "a1234" is not a correct string in terms of this function and pretty every "dump" parsing function will fail to parse it.

If you consider your number to be hexadecimal, and C99 is okay, you might want to try strtoull() instead:
const unsigned long long value = strtoull(string, NULL, 16);
Or with auto-detect:
const unsigned long long value = strtoull(string, NULL, 0);

Related

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/

Difference in the values of atoi

I have the following code:
char* input = (char*)malloc(sizeof(char) * BUFFER) // buffer is defined to 100
int digit = atoi(input); // convert char into a digit
int digit_check = 0;
digit_check += digit % 10; // get last value of digit
When I run the input 1234567896 and similarly digit = 1234567896 and digit_check = 6.
However when I run the input 9999999998, digit = 1410065406 and therefore digit_check = 6 when it should be 8.
For the second example, why is there a difference between input and digit when it should be the same value?
Probably because 9999999998 is bigger then the maximum (signed) integer representation, so you get an overflow.
In fact this is the binary representation of 9999999998 and 1410065406:
10 01010100 00001011 11100011 11111110
01010100 00001011 11100011 11111110
As you can see if you see 1410065406 is the 32ed bit value of 9999999998
atoi is limited to an int size (32 bits on most recent plateform).
If you want to handle large numbers, you can use atol or scanf("%ld").
Don't forget to type your variable to long int (or long).
You could also just getting the very last character of your input (gathered as a string rather than as an int) and use atoi on it, so it would never overflow.
On many platforms size of int is limited by 4 bytes, that limits digit in [-2 ** 31, 2**31 - 1].
Use long (or long long) with strtol (or strtoll) depending on platform you build for. For example, GCC on x86 will have 64-bit long long, and for amd64 it will have 64-bit long and long long types.
So:
long long digit = strtoll(input, NULL, 10);
NOTE: strtoll() is popular in Unix-like systems and became standard in C++11, but not all VC++ implementations have it. Use _strtoi64() instead:
__int64 digit = _strtoi64(input, NULL, 10);
You probably want to use the atoll function, which returns a long long int, that is twice as big as int (most likely 64 bits in your case).
It is declared in stdlib.h
http://linux.die.net/man/3/atoll
You should avoid to call atoi on uninitialized string, if there is no \0 on the string, you will invalid read and have a segmentation fault.
You should use strtoimax instead, it's more safe.
9999999998 is bigger then the maximum value that an integer can represent. Either use atol() OR atoll()
You should stop using atoi function or any other functions from ato... group. These functions are not officially deprecated, but they are effectively abandoned since 1995 and exist only for legacy code compatibility purposes. Forget about these functions as if they do not exist. These function provide no usable feedback in case of error or overflow. And overflow is what apparently happens in your example.
In order to convert strings to numbers, C standard library provides strtol function and other functions from strto... group. These are the functions you should use to perform the conversion. And don't forget to check the result for overflow: strto... functions provide this feedback through the return value and errno variable.

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);

strtol using errno

I have the following code:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
void main(void)
{
int data;
char * tmp;
data = strtol("23ef23",&tmp,10);
printf("%d",errno);
getchar();
}
output is 0 ...
why?
i am using visual studio 2010 C++
code must be C89 compatible.
strtol only sets errno for overflow conditions, not to indicate parsing failures. For that purpose, you have to check the value of the end pointer, but you need to store a pointer to the original string:
char const * const str = "blah";
char const * endptr;
int n = strtol(str, &endptr, 0);
if (endptr == str) { /* no conversion was performed */ }
else if (*endptr == '\0') { /* the entire string was converted */ }
else { /* the unconverted rest of the string starts at endptr */ }
I think the only required error values are for underflow and overflow.
Conversely, if the entire string has been consumed in the conversion, you have *endptr = '\0', which may be an additional thing you might want to check.
Your logic does not fit with the 'spec'.
see this
An invalid value does not necessarily set 'errno'.
(copy follows)
long int strtol ( const char * str, char ** endptr, int base );
Convert string to long integer
Parses the C string str interpreting its content as an integral number of the specified base, which is returned as a long int value.
The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes as many characters as possible that are valid following a syntax that depends on the base parameter, and interprets them as a numerical value. Finally, a pointer to the first character following the integer representation in str is stored in the object pointed by endptr.
If the value of base is zero, the syntax expected is similar to that of integer constants, which is formed by a succession of:
An optional plus or minus sign
An optional prefix indicating octal or hexadecimal base ("0" or "0x" respectively)
A sequence of decimal digits (if no base prefix was specified) or either octal orhexadecimal digits if a specific prefix is present
If the base value is between 2 and 36, the format expected for the integral number is a succession of the valid digits and/or letters needed to represent integers of the specified radix (starting from '0' and up to 'z'/'Z' for radix 36). The sequence may optionally be preceded by a plus or minus sign and, if base is 16, an optional "0x" or "0X" prefix.
If the first sequence of non-whitespace characters in str is not a valid integral number as defined above, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
Parameters
str
C string containing the representation of an integral number.
endptr
Reference to an object of type char*, whose value is set by the function to the next character in str after the numerical value.
This parameter can also be a null pointer, in which case it is not used.
Return Value
On success, the function returns the converted integral number as a long int value.
If no valid conversion could be performed, a zero value is returned.
If the correct value is out of the range of representable values, LONG_MAX or
LONG_MIN is returned, and the global variable errno is set to ERANGE.
It has been 10 years since the question was first posted, but the problem does not age. The answers given are either out of date (yet true for their time) or a bit confusing because I had to search more.
I have seen this in a book and met this post while searching for its meaning, and while checking the page for strtol, I ended up in this page on cplusplus.com of errno macro.
Your question has 2 parts to answer here:
First lets make a note of these 2 things about errno:
1- errno can be anything during the execution of a program for no function resets it (unless your own function does so)
errno is set to zero at program startup ...
any function ... can modify its value ...
no ... function sets its value back to zero
2- one has to reset it before calling a function that may use it.
should be reset ... to zero before the call ... since ... previous ... function may have altered its value
your program is pretty small, so no function seems to be there to change it. The sole visitors of errno are main program to set it to zero, and strtol in case of any error.
Yet, your program shows errno is 0, and this is confusing because one expects 23ef23 would not be converted to a number since it includes letters in it. However, this expectation is wrong, and actually, you get a number from this string thus there is really no error here, so no change is made to errno. and this makes the second part of the answer.
you will find this definition in strtol page
... takes as many characters as possible that are valid following a
syntax that depends on the base parameter, and interprets them as a
numerical value ... a pointer to the first character following is
stored.
instead of a long explanation, this following print statement and its output will suffice to visualize that above definition:
printf("%d %d %s",data,errno,tmp);
23 0 ef23
if you set the base to 16, output would be 2354979 0 . And base 2 would give 0 0 23ef23, showing that strtol will not freak if it does not find a number. The only error it will give will be ERANGE for breaching limits:
If the value read is out of the range of representable values by a
long int, the function returns LONG_MAX or LONG_MIN (defined in
), and errno is set to ERANGE.
You have to set errno to 0 before you call strtol. Otherwise you overwrite whatever value strtol set errno to.
You have to check tmp is not the same as "blablabla" pointer.
If data == 0 and tmp == "blablabla", then the input data is in the incorrect format. errno needs not to be set by the implementation if the input data is not in the expected format.
On strtol, strtoll, strtoul, and strtoull functions C says:
(C99, 7.20.1.4p7) If the subject sequence is empty or does not have the expected form, no conversion is performed; the value of nptr is stored in the object pointed to by endptr, provided that endptr is not a null pointer.
(C99, 7.20.1.4p9) The strtol, strtoll, strtoul, and strtoull functions return the converted
value, if any. If no conversion could be performed, zero is returned.

Parse a string as a (long long) integer

I am writing a code in which I need to parse a string to a "long long int"
I used to use atoi when changing from string to int, I dont think it still work. What Can I use now?
--Thanks
Use strtoll() (man page):
#include <stdlib.h>
long long int n = strtoll(s, NULL, 0);
(This is only available in C99 and C11, not in C89.) The third argument is the number base for the conversion, and 0 means "automatic", i.e. decimal, octal or hexadecimal are selected depending on the usual conventions (10, 010, 0x10). Just be mindful of that in case your string starts with 0.

Resources