string to long, not giving me the correct answer - c

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

Related

A different result came out during the square of every number digit

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

Casting Long to Unsigned Short Int / Strtol

There is no compile error. However, the results are not expected. My suspicion is that the casting long to unsigned short int is causing the error. How can I safely cast long to a short for Hex?
[Requiriments: Convert a row of string (which has numbers) to unsigned short int] Thanks!
unsigned short int str_to_bin (char* instr_bin_str) {
unsigned short int i = 0;
long j;
char* ptr;
j = strtol (instr_bin_str, &ptr, 10);
if (j == 0) {
fprintf (stderr, "error6: str_to_bin() failed");
return 6;
}
i = (unsigned short) j;
printf("State: 0x%X \n", i);
return i;
}
The string you're passing in is the binary representation of a number. However, when you're calling strtol you pass in 10 for the third parameter, which means it expects a string in decimal representation.
If you're expecting binary, you need to tell strtol to expect that:
j = strtol (instr_bin_str, &ptr, 2);

Converting char hex string to unsigned int using strtoul function in C

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

Problem with big numbers in C

why should a code like this should provide a so high result when I give it the number 4293974227 (or higher)
int main (int argc, char *argv[])
{
unsigned long long int i;
unsigned long long int z = atoi(argv[1]);
unsigned long long int tmp1 = z;
unsigned long long int *numbers = malloc (sizeof (unsigned long long int) * 1000);
for (i=0; tmp1<=tmp1+1000; i++, tmp1++) {
numbers[i] = tmp1;
printf("\n%llu - %llu", numbers[i], tmp1);
}
}
Result should start with the provided number but starts like this:
18446744073708558547 - 18446744073708558547
18446744073708558548 - 18446744073708558548
18446744073708558549 - 18446744073708558549
18446744073708558550 - 18446744073708558550
18446744073708558551 - 18446744073708558551
ecc...
What's this crap??
Thanks!
atoi() returns int. If you need larger numbers, try strtol(), strtoll(), or their relatives.
atoi() returns (int), and can't deal with (long long). Try atoll(), or failing that atol() (the former is preferred).
You are printing signed integers as unsigned.

How do I split up a long long integer into 3 char sets?

I have a long long integer variable which holds data like 20101201
I need to split it up as 2010, 12 and 01.
Note: I need to do this in C program in my linux machine.
You can divide by powers of 10 to get rid of numbers on the right:
(20101201/100/100)==2010
And the modulo of powers of 10 to get rid of numbers on the left:
(20101201%100)==01
And combine them to get the part in the middle:
(20101201/100)%100==12
This one should be ok with longs, and puts the answers into strings.
long long int lWholeThing = 20101201LL;
long long int lDate = lWholeThing % 100LL;
lWholeThing /= 100LL;
long long int lMonth = lWholeThing % 100LL;
lWholeThing /= 100LL;
long long int lYear = lWholeThing;
char sDate [3];
char sMonth [3];
char sYear [5];
sprintf (sDate, "%02d", (int) lDate);
sprintf (sMonth, "%02d", (int) lMonth);
sprintf (sYear, "%d", (int) lYear);
Try something like:
#include <stdlib.h> // for itoa() call -- built in to convert integer to string
#include <stdio.h> // for printf() call
int main() {
int num = 123;
char buf[5];
// convert 123 to string [buf]
itoa(num, buf, 10);
// print our string
printf("%s\n", buf);
return 0;
}
Then you can just complete your program by using index to split the numbers into different strings.
For the example you have given, you wanted to divide the number in to three sets:
Pass your input as an argument to the executable.
int main( int argc, char **argv)
{
long long int x;
x=atoll(argv[1]);
printf("\n %d", x%100);
x=x/100;
printf("\n %d", x%100);
x=x/100;
printf("\n %d", x);
}

Resources