• <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>

            woaidongmao

            文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
            隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
            數據加載中……

            對字符串類型和數值類型間進行轉換問題的處理之Boost組件lexical_cast

            在CSDN論壇上經常看到詢問如何在字符串類型和數值類型間進行轉換的問題,也看到了許多不同的答案。下面先討論一下從字符串類型到數值類型的轉換。

            1. 如何將字符串"123"轉換為int類型整數123?答案是,用標準C的庫函數atoi;
            2. 如果要轉換為long類型呢?標準C的庫函數atol;
            3. 如何將"123.12"轉換為double類型呢?標準C的庫函數atod;
            4. 如果要轉換為long double類型呢?標準C的庫函數atold;
            5. ……

            后來有朋友開始使用標準庫中的string類,問這個如何轉換為數值?有朋友答曰,請先轉換為const char*。我很佩服作答者有數學家的思維:把陌生的問題轉化成熟悉的問題。(曾經有一則笑話,好事者問數學家:知道如何燒水嗎?答:知道。把水壺加滿水,點火燒。又問:如果水壺里已經有水了呢?答:先倒掉,就轉化為我熟悉的問題了……)

            不,不,這樣是C的做法,不是C++。那么,C++該怎么做呢?使用Boost Conversion Library所提供的函數lexical_cast(需要引入頭文件boost/lexical_cast.hpp)無疑是最簡單方便的。如:

            #include <boost/lexical_cast.hpp>
            #include <iostream>
            int main()
            {
                    using boost::lexical_cast;
                    int a = lexical_cast<int>("123");
                    double b = lexical_cast<double>("123.12");
                    std::cout<<a<<std::endl
                    std::cout<<b<<std::endl;
                    return 0;
            }

            一個函數就簡潔地解決了所有的問題。

            3.2 數值→字符串

            那么從數值類型到字符串類型呢?

            用itoa?不對吧,標準C/C++里根本沒有這個函數。即使在Windows平臺下某些編譯器提供了該函數3,沒有任何移植性不說,還只能解決int類型(也許其他函數還可以解決long、unsigned long等類型),浮點類型又怎么辦?當然,辦法還是有,那就是:sprintf。

            char s[100];
            sprintf(s, "%f", 123.123456);

            不知道諸位對C里的scanf/printf系列印象如何,總之阿炯我肯定記不住那些稀奇古怪的參數,而且如果寫錯了參數,就會得到莫名其妙的輸出結果,調試起來可就要命了(我更討厭的是字符數組,空間開100呢,又怕太小裝不下;開100000呢,總覺得太浪費,心里憋氣,好在C++標準為我們提供了string這樣的字符串類)。這時候,lexical_cast就出來幫忙啦。

            #include <boost/lexical_cast.hpp>
            #include <string>
            #include <iostream>
            int main()
            {
                    using std::string;
                    const double d = 123.12;
                    string s = boost::lexical_cast<string>(d);
                    std::cout<<s<<std::endl;
                    return 0;
            }

            跟前面一樣簡單。

            3.3 異常

            如果轉換失敗,則會有異常bad_lexical_cast拋出。該異常類是標準異常類bad_cast的子類。

            #include <boost/lexical_cast.hpp>
            #include <iostream>
            int main()
            {
                    using std::cout;
                    using std::endl;
                    int i;
                    try{
                            i = boost::lexical_cast<int>("abcd");
                    }
                    catch(boost::bad_lexical_cast& e)
                    {
                            cout<<e.what()<<endl;
                            return 1;
                    }
                    cout<<i<<endl;
                    return 0;
            }

            顯然“abcd”并不能轉換為一個int類型的數值,于是拋出異常,捕捉后輸出“bad lexical cast: source type value could not be interpreted as target”這樣的信息。

            3.4 注意事項

            lexical_cast依賴于字符流std::stringstream(會自動引入頭文件4),其原理相當簡單:把源類型讀入到字符流中,再寫到目標類型中,就大功告成。例如

            int d = boost::lexical_cast<int>("123");

            就相當于

            int d;
            std::stringstream s;
            s<<"123";
            s>>d;

            既然是使用了字符流,當然就有些隨之而來的問題,需要特別指出5

            • 由于Visual C++ 6的本地化(locale)部分實現有問題,因此如果使用了非默認的locale,可能會莫名其妙地拋出異常。當然,一般情況下我們并不需要去改變默認的locale,所以問題不是很大。
            • 輸入數據必須“完整”地轉換,否則拋出bad_lexical_cast異常。例如
            int i = boost::lexical_cast<int>("123.123"); // this will throw 

            便會拋出異常。因為“123.123”只能“部分”地轉換為123,不能“完整”地轉換為123.123。

            • 浮點數的精度問題。
            std::string s = boost::lexical_cast<std::string>(123.1234567);

            以上語句預想的結果是得到“123.1234567”,但是實際上我們只會得到“123.123”,因為默認情況下std::stringstream的精度是6(這是C語言程序庫中的“前輩”printf留下的傳統)。這可以說是boost::lexical_cast的一個bug。怎么辦呢?權宜之計,可以這么做:打開頭文件<boost/lexical_cast.hpp>,注意對照修改6

            #include <boost/limits.hpp>
            //...
            template<typename Target, typename Source>
            Target lexical_cast(Source arg) {
                    //...
                    Target result; 
                    interpreter.precision(std::numeric_limits<Source>::digits10);
                    if( !(interpreter << arg) ||
                    !(interpreter >> result) ||
                    !(interpreter >> std::ws).eof())
                    //...
            }

            即可得到正確結果。當然,理論上效率會有一點點損失,不過幾乎可以忽略不計。

            4 小結

            我們已經體驗了boost::lexcial_cast。當然,lexical_cast不僅僅局限于字符串類型與數值類型之間的轉換:可在任意可輸出到stringstream的類型和任意可從stringstream輸入的類型間轉換。這次的了解盡管很粗略,不過畢竟我們已經“走進Boost”,而不僅僅是“走近”。以后,我們可以自行領略Boost的動人之處啦。

            posted on 2008-04-25 17:08 肥仔 閱讀(643) 評論(0)  編輯 收藏 引用 所屬分類: Boost & STL

            国产精品99久久久久久人| 久久久久亚洲?V成人无码| 亚洲欧美精品一区久久中文字幕| 精品久久久久久国产潘金莲 | 91精品国产91久久| 久久超乳爆乳中文字幕| 久久婷婷五月综合97色| 久久久久国产精品熟女影院| 一本久道久久综合狠狠爱| 国产成人无码精品久久久性色| 国产免费久久精品99久久| 欧美日韩精品久久久免费观看| 武侠古典久久婷婷狼人伊人| 伊人色综合九久久天天蜜桃| 久久久久久精品无码人妻| 久久久噜噜噜久久中文福利| 久久国产精品99精品国产| 69久久精品无码一区二区| 国产精品成人精品久久久| 久久久久国产一区二区| 国产毛片欧美毛片久久久| 久久精品国产69国产精品亚洲| 久久国产福利免费| 热99RE久久精品这里都是精品免费 | 99国产精品久久久久久久成人热| 久久国产一区二区| 一级女性全黄久久生活片免费| 亚洲精品乱码久久久久久蜜桃不卡| 亚洲精品高清国产一线久久 | 国产精品久久久久久| 精品久久久久久99人妻| 久久国产免费直播| 成人免费网站久久久| 一本色道久久综合狠狠躁篇| 99久久婷婷国产综合亚洲| 日韩欧美亚洲综合久久影院Ds| 亚洲欧美成人综合久久久| 久久久久亚洲AV综合波多野结衣 | 亚洲v国产v天堂a无码久久| 无码久久精品国产亚洲Av影片 | 国产精品免费久久久久久久久|