• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            今天微薄上看到 http://weibo.com/1401880315/AaNkykg6J#_rnd1379945435634

            左耳朵耗子:
            現(xiàn)在的程序員,連atoi()都不知道是什么了,沒事,那我改,不叫atoi()改叫StrToInt(),卻發(fā)現(xiàn),好些人連ASCII碼都不知道是怎么一回事,沒事,我教會你。但最終卻發(fā)現(xiàn)怎么有這么多人連這樣簡單的程序都寫不好(包括有多年工作經(jīng)驗(yàn)的人)。“比技術(shù)更恐怖的是有一群不合格的程序員在使用這這些技術(shù)”。


            好久沒寫這么基本的代碼了,簡單嘗試寫了下, 結(jié)果花了半個(gè)小時(shí),只寫了一個(gè)最基本功能的,通過后面的測試用例還花了不少時(shí)間進(jìn)行調(diào)試修改。 
            INT StrToInt(const TCHAR* lpszValue)
            {
                assert(lpszValue != NULL);

                INT nLen = lstrlen(lpszValue);
                const TCHAR* pEnd = lpszValue + nLen;

                TCHAR* pCurrent = (TCHAR*)lpszValue;
                BOOL bNegative(FALSE);
                if(nLen >= 1)
                {
                    if(*pCurrent == _T('+'))
                    {
                        bNegative = FALSE;
                        pCurrent += 1;
                    }
                    else if(*pCurrent == _T('-'))
                    {
                        bNegative = TRUE;
                        pCurrent += 1;
                    }
                    else
                    {
                        bNegative = FALSE;
                    }
                }

                INT nBase(10);
                if(pEnd - pCurrent >= 2)
                {
                    if(pCurrent[0] == _T('0')
                        && ::toupper(pCurrent[1]) == _T('X'))
                    {
                        pCurrent += 2;
                        nBase = 16;
                    }
                }

                INT nRet(0);
                INT nValue(0);
                while(pCurrent != pEnd)
                {
                    TCHAR ch(*pCurrent);
                    if(ch >= _T('0') && ch <= _T('9'))
                    {
                        nValue = ch - _T('0');
                    }
                    else if(nBase == 16)
                    {
                        if(::toupper(ch) >= _T('A') && ::toupper(ch) <= _T('F'))
                        {
                            nValue = 10 + (::toupper(ch) - _T('A'));
                        }
                        else
                        {
                            assert(FALSE);
                            break;
                        }
                    }
                    else
                    {
                        assert(FALSE);
                        break;
                    }

                    nRet += nValue * pow((double)nBase, pEnd - pCurrent - 1);
                    pCurrent += 1;
                }

                return bNegative ?  -nRet : nRet;
            }

            void test
            {
                assert(StrToInt(_T("11")) == 11);
                assert(StrToInt(_T("+12")) == 12); 
                assert(StrToInt(_T("-123")) == -123); 
                assert(StrToInt(_T("-0x1CF")) == -0x1CF); 
                assert(StrToInt(_T("-0X123")) == -0x123); 
                assert(StrToInt(_T("0X123")) == 0x123);
            }

            感慨用慣了Windows API和STL, 對于最基本的字符串處理代碼反而寫不好了。細(xì)想一下這個(gè)基本的東西確實(shí)不好寫, 實(shí)際上我是上面只是考慮了10進(jìn)制和16進(jìn)制, 沒有考慮其他進(jìn)制,也沒有考慮小數(shù),非法的字符串或是溢出等情況, 而真正工業(yè)級的庫要考慮所有的情況, 另外還要考慮轉(zhuǎn)換效率等問題。

            實(shí)際上CRT源碼中有這個(gè)函數(shù)的實(shí)現(xiàn):
            /***
            *wcstol, wcstoul(nptr,endptr,ibase) - Convert ascii string to long un/signed
            *       int.
            *
            *Purpose:
            *       Convert an ascii string to a long 32-bit value.  The base
            *       used for the caculations is supplied by the caller.  The base
            *       must be in the range 0, 2-36.  If a base of 0 is supplied, the
            *       ascii string must be examined to determine the base of the
            *       number:
            *           (a) First char = '0', second char = 'x' or 'X',
            *               use base 16.
            *           (b) First char = '0', use base 8
            *           (c) First char in range '1' - '9', use base 10.
            *
            *       If the 'endptr' value is non-NULL, then wcstol/wcstoul places
            *       a pointer to the terminating character in this value.
            *       See ANSI standard for details
            *
            *Entry:
            *       nptr == NEAR/FAR pointer to the start of string.
            *       endptr == NEAR/FAR pointer to the end of the string.
            *       ibase == integer base to use for the calculations.
            *
            *       string format: [whitespace] [sign] [0] [x] [digits/letters]
            *
            *Exit:
            *       Good return:
            *           result
            *
            *       Overflow return:
            *           wcstol -- LONG_MAX or LONG_MIN
            *           wcstoul -- ULONG_MAX
            *           wcstol/wcstoul -- errno == ERANGE
            *
            *       No digits or bad base return:
            *           0
            *           endptr = nptr*
            *
            *Exceptions:
            *       Input parameters are validated. Refer to the validation section of the function.
            *
            *******************************************************************************/

            /* flag values */
            #define FL_UNSIGNED   1       /* wcstoul called */
            #define FL_NEG        2       /* negative sign found */
            #define FL_OVERFLOW   4       /* overflow occured */
            #define FL_READDIGIT  8       /* we've read at least one correct digit */


            static unsigned long __cdecl wcstoxl (
                    _locale_t plocinfo,
                    const wchar_t *nptr,
                    const wchar_t **endptr,
                    int ibase,
                    int flags
                    )
            {
                const wchar_t *p;
                wchar_t c;
                unsigned long number;
                unsigned digval;
                unsigned long maxval;
                _LocaleUpdate _loc_update(plocinfo);


                /* validation section */
                if (endptr != NULL)
                {
                    /* store beginning of string in endptr */
                    *endptr = nptr;
                }
                _VALIDATE_RETURN(nptr != NULL, EINVAL, 0L);
                _VALIDATE_RETURN(ibase == 0 || (2 <= ibase && ibase <= 36), EINVAL, 0L);

                p = nptr;           /* p is our scanning pointer */
                number = 0;         /* start with zero */

                c = *p++;           /* read char */

                while ( _iswspace_l(c, _loc_update.GetLocaleT()) )
                    c = *p++;       /* skip whitespace */

                if (c == '-') {
                    flags |= FL_NEG;    /* remember minus sign */
                    c = *p++;
                }
                else if (c == '+')
                    c = *p++;       /* skip sign */

                if (ibase == 0) {
                    /* determine base free-lance, based on first two chars of
                       string */
                    if (_wchartodigit(c) != 0)
                        ibase = 10;
                    else if (*p == L'x' || *p == L'X')
                        ibase = 16;
                    else
                        ibase = 8;
                }

                if (ibase == 16) {
                    /* we might have 0x in front of number; remove if there */
                    if (_wchartodigit(c) == 0 && (*p == L'x' || *p == L'X')) {
                        ++p;
                        c = *p++;   /* advance past prefix */
                    }
                }

                /* if our number exceeds this, we will overflow on multiply */
                maxval = ULONG_MAX / ibase;


                for (;;) {  /* exit in middle of loop */

                    /* convert c to value */
                    if ( (digval = _wchartodigit(c)) != -1 )
                        ;
                    else if ( __ascii_iswalpha(c))
                        digval = __ascii_towupper(c) - L'A' + 10;
                    else
                        break;

                    if (digval >= (unsigned)ibase)
                        break;      /* exit loop if bad digit found */

                    /* record the fact we have read one digit */
                    flags |= FL_READDIGIT;

                    /* we now need to compute number = number * base + digval,
                       but we need to know if overflow occured.  This requires
                       a tricky pre-check. */

                    if (number < maxval || (number == maxval &&
                    (unsigned long)digval <= ULONG_MAX % ibase)) {
                        /* we won't overflow, go ahead and multiply */
                        number = number * ibase + digval;
                    }
                    else {
                        /* we would have overflowed -- set the overflow flag */
                        flags |= FL_OVERFLOW;
                        if (endptr == NULL) {
                            /* no need to keep on parsing if we
                               don't have to return the endptr. */
                            break;
                        }
                    }

                    c = *p++;       /* read next digit */
                }

                --p;                /* point to place that stopped scan */

                if (!(flags & FL_READDIGIT)) {
                    /* no number there; return 0 and point to beginning of
                       string */
                    if (endptr)
                        /* store beginning of string in endptr later on */
                        p = nptr;
                    number = 0L;        /* return 0 */
                }
                else if ( (flags & FL_OVERFLOW) ||
                      ( !(flags & FL_UNSIGNED) &&
                        ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) ||
                          ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) )
                {
                    /* overflow or signed overflow occurred */
                    errno = ERANGE;
                    if ( flags & FL_UNSIGNED )
                        number = ULONG_MAX;
                    else if ( flags & FL_NEG )
                        number = (unsigned long)(-LONG_MIN);
                    else
                        number = LONG_MAX;
                }

                if (endptr != NULL)
                    /* store pointer to char that stopped the scan */
                    *endptr = p;

                if (flags & FL_NEG)
                    /* negate result if there was a neg sign */
                    number = (unsigned long)(-(long)number);

                return number;          /* done. */
            }

            透過這道題確實(shí)可以投射出一個(gè)程序員的計(jì)算機(jī)基本功, 大家可以自己嘗試下實(shí)現(xiàn)這個(gè)函數(shù), 看看自己的計(jì)算機(jī)基本功。
            posted on 2013-09-23 22:39 Richard Wei 閱讀(2750) 評論(0)  編輯 收藏 引用 所屬分類: C++
            欧美午夜精品久久久久免费视 | 91性高湖久久久久| 亚洲伊人久久成综合人影院 | 国产三级精品久久| 国产精品久久久久久影院| 久久久久av无码免费网| 亚洲国产小视频精品久久久三级| 国产A三级久久精品| 久久久久亚洲AV无码观看| av无码久久久久久不卡网站| 久久精品人成免费| 国产午夜福利精品久久2021| 久久青青草原精品国产软件| 久久天天躁狠狠躁夜夜2020| 久久精品人人做人人爽97| 欧美一级久久久久久久大| 蜜桃麻豆www久久国产精品| 7777久久亚洲中文字幕| 久久久久久久久久久| 久久久久国产| 97久久婷婷五月综合色d啪蜜芽| 日本免费一区二区久久人人澡 | 欧美丰满熟妇BBB久久久| 九九热久久免费视频| 狠狠色丁香婷婷久久综合| 亚洲AV乱码久久精品蜜桃| 国产精品久久久久久久| 亚洲中文字幕无码久久综合网| 午夜福利91久久福利| 久久久精品久久久久久| 97精品伊人久久久大香线蕉| 久久夜色精品国产噜噜麻豆| 国产亚洲美女精品久久久2020| 中文字幕亚洲综合久久菠萝蜜| 久久一区二区三区免费| 久久伊人亚洲AV无码网站| 久久国产视频99电影| 久久久久亚洲AV成人网| 久久99精品久久久久久野外| 狠狠人妻久久久久久综合| 久久久久国色AV免费观看|