I know I could have found the code page on the Internet easily enough for that function, but I want to know why, after passing the 10 digit array, the expected result doesn't act like the previous ones.
#include <stdio.h>
int xstraylen(char *arr) {
int len;
for (len = 0; *(arr len) != '\0'; len ) {
//printf("%c ", *(arr len));
}
return len;
}
int str_into_int(char *str) {
int power = 10, len, number;
long int value = 0;
len = xstraylen(str);
printf("\n%d\n", len);
for (int index = 0; index < len; index ) {
number = (int)(*(str index) - 48);
value = number;
value *= power;
printf("-%d- %d %d ", index, number, value);
}
value /= power;
return value;
}
int main() {
char *str = "1234567890";
int value;
value = str_into_int(str);
printf("\n\n%d", value);
return 0;
}
Output
10
-0- 1 10 -1- 2 120 -2- 3 1230 -3- 4 12340 -4- 5 123450 -5- 6 1234560 -6- 7 12345670 -7- 8 123456780 -8- 9 1234567890 -9- 0 -539222988
-53922298
CodePudding user response:
Your code does not work for 10 digit numbers because you always multiply value
by 10 in the loop after adding the digit and divide it at the end. For a 10 digit number, the last multiplication causes an arithmetic overflow on your platform where both int
and long
probably have 32 bits.
You should multiply value
before adding the digit and remove the final division:
int str_into_int(char *str) {
int power = 10, len, number;
long int value = 0;
len = xstraylen(str);
printf("\n%d\n", len);
for (int index = 0; index < len; index ) {
value *= power;
number = (int)(*(str index) - 48);
value = number;
printf("-%d- %d %ld ", index, number, value);
}
return value;
}
Note that the code can be further simplified and modified to handle larger values and detect overflow:
#include <limits.h>
#include <stdio.h>
unsigned long long int str_into_int(const char *str) {
unsigned long long int value = 0;
for (int i = 0; str[i] >= '0' && str[i] <= '9'; i ) {
unsigned int digit = str[i] - '0';
if (value > ULLONG_MAX / 10 ||
(value == ULLONG_MAX / 10 && digit > ULLONG_MAX % 10)) {
printf("conversion exceeds range of unsigned long long\n");
return ULLONG_MAX;
}
value = value * 10 digit;
}
return value;
}
void test(const char *str) {
printf("%s -> %llu\n", str, str_into_int(str));
}
int main() {
test("1234567890");
test("12345678901234567890");
test("18446744073709551615");
test("18446744073709551616");
test("123456789012345678901234567890");
return 0;
}
Output:
1234567890 -> 1234567890
12345678901234567890 -> 12345678901234567890
18446744073709551615 -> 18446744073709551615
conversion exceeds range of unsigned long long
18446744073709551616 -> 18446744073709551615
conversion exceeds range of unsigned long long
123456789012345678901234567890 -> 18446744073709551615
CodePudding user response:
Your compiler considers the type long int
as having the same range of values as the type int
.
In this expression statement
value *= power;
there an overflow occurs when value is equal to 1234567890
.
Change the logic of the for loop the following way
for (int index = 0; index < len; index ) {
value *= power;
number = *(str index) - '0';
value = number;
printf("-%d- %d %ld ", index, number, value);
}
and remove this statement
value /= power;
Bear in mind that your function does not process a sign mark.
Take into account the function xstraylen
should be declared the following way
size_t xstraylen( const char *arr ) {
size_t len = 0;
while ( *( arr len ) ) len;
return len;
}
CodePudding user response:
I would use the Horner's rule to compute the value of an integer, like this.
#include <stdio.h>
int main(void)
{
char *ns="328327", *p=ns;
int valn = 0;
while(*p) valn=valn*10 (*p -'0');
printf("%d\n", valn);
return 0;
}
Depending on what you want to do, you must take care and check not to produce overflow, the input to be correct, etc. But this is the simplest idea I can imagine for your problem.