⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stdlib.c

📁 一款标准c类库.Tima(TM-Tiny&Miny) Standard ANSI C based Library
💻 C
📖 第 1 页 / 共 2 页
字号:
/**
 * 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 + -