<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Change Dir

    先知cd——熱愛(ài)生活是一切藝術(shù)的開(kāi)始

    統(tǒng)計(jì)

    留言簿(18)

    積分與排名

    “牛”們的博客

    各個(gè)公司技術(shù)

    我的鏈接

    淘寶技術(shù)

    閱讀排行榜

    評(píng)論排行榜

    分享代碼系列——parseInt(包含java和c語(yǔ)言的atoi方法)

    jdk中的Integer類(lèi)是int對(duì)象的包裝類(lèi),正常的Integer占用內(nèi)存開(kāi)銷(xiāo)要比int大,比例大概是1:4 。今天分享的代碼是Integer類(lèi)中的靜態(tài)方法parseInt(String, int)。這個(gè)方法眾所周知,甚至在我們一開(kāi)始學(xué)習(xí)編程時(shí)就嘗試的寫(xiě)過(guò)這樣的代碼,一個(gè)正常的思路:遍歷輸入的字符數(shù)組(java的字符串就是一個(gè)字符數(shù)組),然后parse每個(gè)char,依據(jù)參數(shù)給定的進(jìn)制,判斷每個(gè)char是否滿(mǎn)足,滿(mǎn)足則繼續(xù),否則拋出異常或中斷,直到處理完畢所有字符,返回結(jié)果。

    那么我們看看jdk給出的實(shí)現(xiàn):

        public static int parseInt(String s, int radix)
            throws NumberFormatException
        {
            if (s == null) {
                throw new NumberFormatException("null");
            }

        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                            " less than Character.MIN_RADIX");
        }

        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                            " greater than Character.MAX_RADIX");
        }

        int result = 0;
        boolean negative = false;
        int i = 0, max = s.length();
        int limit;
        int multmin;
        int digit;

        if (max > 0) {
            if (s.charAt(0) == '-') {
            negative = true;
            limit = Integer.MIN_VALUE;
            i++;
            } else {
            limit = -Integer.MAX_VALUE;
            }
            multmin = limit / radix;
            if (i < max) {
            digit = Character.digit(s.charAt(i++),radix);
            if (digit < 0) {
                throw NumberFormatException.forInputString(s);
            } else {
                result = -digit;
            }
            }
            while (i < max) {
            // Accumulating negatively avoids surprises near MAX_VALUE
            digit = Character.digit(s.charAt(i++),radix);
            if (digit < 0) {
                throw NumberFormatException.forInputString(s);
            }
            if (result < multmin) {
                throw NumberFormatException.forInputString(s);
            }
            result *= radix;
            if (result < limit + digit) {
                throw NumberFormatException.forInputString(s);
            }
            result -= digit;
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
        if (negative) {
            if (i > 1) {
            return result;
            } else {    /* Only got "-" */
            throw NumberFormatException.forInputString(s);
            }
        } else {
            return -result;
        }
        }

    過(guò)程就是按照思路來(lái)的,但是更全面一些,首先做一些參數(shù)檢查,然后定義了局部變量用于計(jì)算:result是對(duì)應(yīng)的int結(jié)果,negative對(duì)應(yīng)是否是負(fù)數(shù)的判斷,i是遍歷用的索引指針,max代表字符串的長(zhǎng)度,limit是合法數(shù)字的上限(下限),digit是當(dāng)前掃描到的字符對(duì)應(yīng)的數(shù)字,multmin是在做乘法計(jì)算時(shí)能走到的合法下限。

    嚴(yán)謹(jǐn)是這段程序最大的特點(diǎn),因?yàn)橛蟹?hào)int的上下限是-2147483648~2147483647,可見(jiàn)負(fù)數(shù)表達(dá)的范圍比正數(shù)多一個(gè),這樣就好理解為什么在開(kāi)頭要把limit全部表達(dá)為負(fù)數(shù)(下限),這樣的操作減少了后續(xù)的判斷,可以一步到位,相當(dāng)于二者選擇取其大一樣,大的包含了小的。同理,那么multmin也就是負(fù)數(shù)了,而且可以認(rèn)為是只和進(jìn)制參數(shù)radix有關(guān)系。接著每個(gè)char的掃描計(jì)算digit利用到了Character.digit(char,int) 方法,這個(gè)方法就是在調(diào)用CharacterDataLatin1.digit(codePoint, radix) 方法,而這個(gè)新的方法其實(shí)只是去靜態(tài)數(shù)組中取個(gè)映射而已。最后當(dāng)順利的執(zhí)行完while循環(huán)后,result結(jié)果也就計(jì)算好了。

    作為程序設(shè)計(jì)人員,我最初接觸的語(yǔ)言是C++,當(dāng)初用到的庫(kù)函數(shù)是atoi,那么我們看看atoi的庫(kù)標(biāo)準(zhǔn)實(shí)現(xiàn):

    int
    atoi(str)
    	const char *str;
    {
    	_DIAGASSERT(str != NULL);
    
    	return((int)strtol(str, (char **)NULL, 10));
    }
    其中調(diào)用了strtol方法,參數(shù)傳遞的radix是10,也就是說(shuō)我們常用的atoi是默認(rèn)轉(zhuǎn)化字符串到10進(jìn)制的。其中開(kāi)始時(shí)還進(jìn)行了一個(gè)trim的操作,而且支持16進(jìn)制的0x開(kāi)頭,可謂完全的盡善盡美啊。
    strtol方法:
    #define	_FUNCNAME	strtol
    #define	__INT		long
    #define	__INT_MIN	LONG_MIN
    #define	__INT_MAX	LONG_MAX
    __INT
    _FUNCNAME(const char *nptr, char **endptr, int base)
    {
    	const char *s;
    	__INT acc, cutoff;
    	char c;
    	int i, neg, any, cutlim;
    
    	_DIAGASSERT(nptr != NULL);
    	/* endptr may be NULL */
    
    	/* check base value */
    	if (base && (base < 2 || base > 36)) {
    		errno = EINVAL;
    		return(0);
    	}
    
    	/*
    	 * 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.
    	 */
    	s = nptr;
    	do {
    		c = *s++;
    	} while (isspace(c));
    	if (c == '-') {
    		neg = 1;
    		c = *s++;
    	} else {
    		neg = 0;
    		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 ? __INT_MIN : __INT_MAX;
    	cutlim = (int)(cutoff % base);
    	cutoff /= base;
    	if (neg) {
    		if (cutlim > 0) {
    			cutlim -= base;
    			cutoff += 1;
    		}
    		cutlim = -cutlim;
    	}
    	for (acc = 0, any = 0;; c = *s++) {
    		if (!isascii(c))
    			break;
    		if (isdigit(c))
    			i = c - '0';
    		else if (isalpha(c))
    			i = c - (isupper(c) ? 'A' - 10 : 'a' - 10);
    		else
    			break;
    		if (i >= base)
    			break;
    		if (any < 0)
    			continue;
    		if (neg) {
    			if (acc < cutoff || (acc == cutoff && i > cutlim)) {
    				any = -1;
    				acc = __INT_MIN;
    				errno = ERANGE;
    			} else {
    				any = 1;
    				acc *= base;
    				acc -= i;
    			}
    		} else {
    			if (acc > cutoff || (acc == cutoff && i > cutlim)) {
    				any = -1;
    				acc = __INT_MAX;
    				errno = ERANGE;
    			} else {
    				any = 1;
    				acc *= base;
    				acc += i;
    			}
    		}
    	}
    	if (endptr != 0)
    		/* LINTED interface specification */
    		*endptr = __DECONST(char *, (any ? s - 1 : nptr));
    	return(acc);
    }
     
    當(dāng)然,類(lèi)似的代碼還有很多,這里只列出了兩大語(yǔ)言的庫(kù)實(shí)現(xiàn),總體思路是一致的,當(dāng)我們?cè)O(shè)計(jì)api時(shí),這種編程思路和風(fēng)格以及功能的考慮是我們需要學(xué)習(xí)的。
    下面這兩篇stackoverflow的問(wèn)答給出了一些比較全面的c風(fēng)格代碼,可以參考,這里不貼全文只給link:
    http://stackoverflow.com/questions/194465/how-to-parse-a-string-to-an-int-in-c
    http://stackoverflow.com/questions/4442658/c-parse-int-from-string
    參考文獻(xiàn):
    jdk文檔及源碼
    c庫(kù)函數(shù)源碼及文檔

    posted on 2012-04-06 12:20 changedi 閱讀(2679) 評(píng)論(2)  編輯  收藏 所屬分類(lèi): 好代碼分享

    評(píng)論

    # re: 分享代碼系列&mdash;&mdash;parseInt(包含java和c語(yǔ)言的atoi方法) 2014-04-29 22:46 zuidaima

    最代碼 www.zuidaima.com 提供最全面,最專(zhuān)業(yè)的代碼分享站,近萬(wàn)名用戶(hù)分享超過(guò)1萬(wàn)份高質(zhì)量的代碼  回復(fù)  更多評(píng)論   

    主站蜘蛛池模板: 亚洲AV无码一区二区乱子伦 | 99久久免费观看| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 亚洲AV无码AV男人的天堂| 中文字幕亚洲精品无码| 免费特级黄毛片在线成人观看| 亚洲视频在线观看不卡| 亚洲一区二区影视| 嘿嘿嘿视频免费网站在线观看| 久久国产亚洲高清观看| 成人在线免费看片| 亚洲无吗在线视频| 拔擦拔擦8x华人免费久久| 青青视频免费在线| 久久精品国产精品亚洲艾草网美妙| 91av免费在线视频| 亚洲乱码国产一区三区| 3d动漫精品啪啪一区二区免费 | 久久亚洲国产中v天仙www| 国产精品免费福利久久| 亚洲黄色在线观看网站| 无码人妻久久一区二区三区免费丨| 亚洲色欲色欲www在线播放| 日本免费一区二区三区最新| 日韩在线观看免费| 亚洲AV永久无码精品一百度影院| 亚洲精品在线免费观看| 亚洲国产精品无码久久| 国产亚洲人成网站在线观看| 亚洲免费在线播放| 亚洲经典千人经典日产| 亚洲中文字幕在线观看| 精品无码免费专区毛片| 亚洲Aⅴ在线无码播放毛片一线天| 精品国产亚洲男女在线线电影| 久久久久久久久久国产精品免费 | 一区二区三区免费在线视频| 亚洲综合婷婷久久| 免费人成网站7777视频| 99re热精品视频国产免费| 亚洲精品色在线网站|