📄 stdlib.c
字号:
/**
* Tima Standard ANSI C based Library
*
* Copyright (C) 2008 heiyeluren. All rights reserved.
*
* Open-source ANSI C library powered by TieMa(TIMA) Studio.
*
* Use and distribution licensed under the BSD license. See
* the LICENSE file for full text.
*
* To learn more open-source code, http://heiyeluren.googlecode.com
* My blog: http://blog.csdn.net/heiyeshuwu
*
* $Id: stdlib.c 2008-11-09 23:31 heiyeluren $
*/
#include "stdlib.h"
/***************************************
*
* String conversion function
*
***************************************/
/**
* atof - convert ASCII string to double
*
* @desc The function converts the initial portion of the string pointed to by nptr to double. The behavior is
the same as strtod(nptr, (char **) NULL);
* @return The converted value
*/
double atof(const char *nptr){
double val, power;
int i, sign;
const char *s = nptr;
for (i = 0; isspace(s[i]); i++) /* skip white space */
;
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-')
i++;
for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - '0');
if (s[i] == '.')
i++;
for (power = 1.0; isdigit(s[i]); i++){
val = 10.0 * val + (s[i] - '0');
power *= 10;
}
return sign * val / power;
}
/**
* atoi - convert ASCII string to integer
*
* @desc The function converts the initial portion of the string pointed to by nptr to int. The behavior is the
* same as strtol(nptr, (char **) NULL, 10);
* @return The converted value
*/
int atoi(const char *nptr){
int i, n, sign;
const char *s = nptr;
for (i = 0; isspace(s[i]); i++) ;/* skip white space */
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-') /* skip sign */
i++;
for (n = 0; isdigit(s[i]); i++)
n = 10 * n + (s[i] - '0');
return sign * n;
}
/**
* atol - convert ASCII string to long integer
*
* @desc The function converts the initial portion of the string pointed to by nptr to int. The behavior is the
* same as strtol(nptr, (char **) NULL, 10);
* @return The converted value
*/
long atol(const char *nptr){
long ret = 0L;
int neg = 0;
const char *s = nptr;
while (s && *s && isspace(*s))
s++;
if (*s == '-' || *s == '+'){
neg = *s == '-';
s++;
}
for ( ; s && *s && isdigit (*s); s++)
ret = (ret * 10) + (isdigit (*s) ? *s - '0' : *s);
return (neg ? -ret : ret);
}
/**
* strtod - convert ASCII string to floating point
*
* @desc The functions convert the initial portion of the string pointed to by nptr to double, float, and long double
* representation, respectively.
* @return These functions return the converted value
*/
double strtod(char *str, char **ptr){
char *p;
//const char *str = nptr;
//char **ptr = endptr;
if (ptr == (char **)0)
return atof (str);
p = str;
while (isspace (*p))
++p;
if (*p == '+' || *p == '-')
++p;
/* INF or INFINITY. */
if ((p[0] == 'i' || p[0] == 'I') && (p[1] == 'n' || p[1] == 'N') && (p[2] == 'f' || p[2] == 'F')){
if ((p[3] == 'i' || p[3] == 'I') && (p[4] == 'n' || p[4] == 'N') && (p[5] == 'i' || p[5] == 'I') && (p[6] == 't' || p[6] == 'T') && (p[7] == 'y' || p[7] == 'Y')){
*ptr = p + 7;
return atof (str);
} else {
*ptr = p + 3;
return atof (str);
}
}
/* NAN or NAN(foo). */
if ((p[0] == 'n' || p[0] == 'N') && (p[1] == 'a' || p[1] == 'A') && (p[2] == 'n' || p[2] == 'N')){
p += 3;
if (*p == '('){
++p;
while (*p != '\0' && *p != ')')
++p;
if (*p == ')')
++p;
}
*ptr = p;
return atof (str);
}
/* digits, with 0 or 1 periods in it. */
if (isdigit (*p) || *p == '.'){
int got_dot = 0;
while (isdigit (*p) || (!got_dot && *p == '.')){
if (*p == '.')
got_dot = 1;
++p;
}
/* Exponent. */
if (*p == 'e' || *p == 'E'){
int i;
i = 1;
if (p[i] == '+' || p[i] == '-')
++i;
if (isdigit (p[i])){
while (isdigit (p[i]))
++i;
*ptr = p + i;
return atof (str);
}
}
*ptr = p;
return atof (str);
}
/* Didn't find any digits. Doesn't look like a number. */
*ptr = str;
return 0.0;
}
/**
* strtol - convert a string to a long integer
*
* @desc The function converts the initial part of the string in nptr to a long integer value according to the
* given base, which must be between 2 and 36 inclusive, or be the special value 0.
* @return The function returns the result of the conversion, unless the value would underflow or overflow. If
* an underflow occurs, strtol() returns LONG_MIN. If an overflow occurs, strtol() returns LONG_MAX. In both
* cases, errno is set to ERANGE. Precisely the same holds for strtoll() (with LLONG_MIN and LLONG_MAX instead of
* LONG_MIN and LONG_MAX).
*/
long int strtol(const char *nptr, char **endptr, int base){
const char *s = nptr;
unsigned long acc;
int c;
unsigned long cutoff;
int neg = 0, any, cutlim;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, or equal but the next digit is > 7 (or 8),
* the number is too big, and we will return a range error.
*
* Set any if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}
/**
* strtoul - convert a string to an unsigned long integer
*
* @desc The function converts the initial part of the string in nptr to an unsigned long integer value
* according to the given base, which must be between 2 and 36 inclusive, or be the special value 0
* @return The function returns either the result of the conversion or, if there was a leading minus sign, the
* negation of the result of the conversion represented as an unsigned value, unless the original (non-negated)
* value would overflow; in the latter case, strtoul() returns ULONG_MAX and sets the global variable errno to
* ERANGE. Precisely the same holds for strtoull() (with ULLONG_MAX instead of ULONG_MAX).
*/
unsigned long int strtoul(const char *nptr, char **endptr, int base){
const char *s = nptr;
unsigned long acc;
int c;
unsigned long cutoff;
int neg = 0, any, cutlim;
/*
* See strtol for comments as to the logic used.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -