C语言库函数源代码】

【本程序在Dev C++ 4.9.9.2 下编译通过】

/*

   这个函数会将参数nptr字符串根据参数base来转换成长整型数。

   参数base范围从2至36,或0。参数base代表采用的进制方式,

   如base值为10则采用10进制,若base值为16则采用16进制等。

   当base值为0时则是采用10进制做转换,但遇到如’0x’前置

   字符则会使用16进制做转换、遇到’0’前置字符而不是’0x’

   的时候会使用8进制做转换。一开始strtol()会扫描参数nptr

   字符串,跳过前面的空格字符,直到遇上数字或正负符号才

   开始做转换,再遇到非数字或字符串结束时('/0')结束转换,

   并将结果返回。若参数endptr不为NULL,则会将遇到不合条件

   而终止的nptr中的字符指针由endptr返回。

*/

#include <stdlib.h>

#define             LONG_MAX     2147483647L  /*0x7FFFFFFF*/

#define             LONG_MIN     (-2147483647L-1L) /*-0x80000000*/

int my_strtol(const char *nptr, char **endptr, int base)

{

   const char *p = nptr;

   unsigned long ret;

   int ch;

   unsigned long Overflow;

   int sign = 0, flag, LimitRemainder;

  

   /*

      跳过前面多余的空格,并判断正负符号。

      如果base是0,允许以0x开头的十六进制数,

      以0开头的8进制数。

      如果base是16,则同时也允许以0x开头。

 

   */

   do

   {

      ch = *p++;

   } while (isspace(ch));

  

   if (ch == '-')

   {

      sign = 1;

      ch = *p++;

   }

   else if (ch == '+')

      ch = *p++;

   if ((base == 0 || base == 16) &&

      ch == '0' && (*p == 'x' || *p == 'X'))

   {

      ch = p[1];

      p += 2;

      base = 16;

   }

   if (base == 0)

      base = ch == '0' ? 8 : 10;

 

   Overflow = sign ? -(unsigned long)LONG_MIN : LONG_MAX;

   LimitRemainder = Overflow % (unsigned long)base;

   Overflow /= (unsigned long)base;

 

   for (ret = 0, flag = 0;; ch = *p++)

   {

      /*把当前字符转换为相应运算中需要的值。*/

      if (isdigit(ch))

        ch -= '0';

      else if (isalpha(ch))

        ch -= isupper(ch) ? 'A' - 10 : 'a' - 10;

      else

        break;

      if (ch >= base)

        break;

 

      /*如果产生溢出,则置标志位,以后不再做计算。*/

      if (flag < 0 || ret > Overflow || (ret == Overflow && ch > LimitRemainder))

        flag = -1;

      else

      {

        flag = 1;

        ret *= base;

        ret += ch;

      }

   }

 

   /*

      如果溢出,则返回相应的Overflow的峰值。

      没有溢出,如是符号位为负,则转换为负数。

   */

   if (flag < 0)

      ret = sign ? LONG_MIN : LONG_MAX;

   else if (sign)

      ret = -ret;

  

   /*

      如字符串不为空,则*endptr等于指向nptr结束

      符的指针值;否则*endptr等于nptr的首地址。

   */

   if (endptr != 0)

      *endptr = (char *)(flag ?(p - 1) : nptr);

 

   return ret;

}

int main()

{

   char * str = "2147483647";

   printf("%d/n",my_strtol(str, NULL, 0));

   str = "-2147483648";

   printf("%d/n",my_strtol(str, NULL, 0));

  

   str = "0x7FFFFFFF";

   printf("%d/n",my_strtol(str, NULL, 0));

   str = "-0x80000000";

   printf("%d/n",my_strtol(str, NULL, 0));

   str = "0x7FFFFFFF";

   printf("%d/n",my_strtol(str, NULL, 16));

   str = "-0x80000000";

   printf("%d/n",my_strtol(str, NULL, 16));

  

   str = "017777777777";

   printf("%d/n",my_strtol(str, NULL, 0));

   str = "-020000000000";

   printf("%d/n",my_strtol(str, NULL, 0));

  

   system("pause");

   return 0;

}

 

转载于:https://www.cnblogs.com/duadu/archive/2007/01/04/6335446.html

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐