• <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>
            cyt
            ??? boost就有一個實現(xiàn)類型安全format的類,不過類比較龐大,而且也比較復(fù)雜,用起來也不是很習(xí)慣。
            所以還是自己簡單實現(xiàn)一個了。
            ??? 先看看需求:format_string.format("[%] = %") % a % strName
            ??? 其實就是希望后面的a和strName分別替代格式化字符串"[%] = %"中的兩個%號,相當(dāng)于:
            ??? stringstream format_string;
            ??? format_string << "[" << a << "] = " << strName;

            ??? 當(dāng)然,要做到通用,還是希望不單能輸出到stringstream,最好還是能輸出到std::ostream。
            ??? class format_stream
            ??? {
            ??? public:
            ??????? explicit format_stream(std::ostream & outS) : m_output(outS),m_lpszFormat(&g_nEndFlags)
            ??????? {
            ??????? }

            ??????? inline format_stream & format(const char * lpszFormat)
            ??????? {
            ??????????? flushFormat();
            ??????????? m_lpszFormat = lpszFormat;
            ??????????? return outputPrefix();
            ?????? }
            ???????
            ??????? template
            ??????? inline format_stream & arg(const typeArg1 & val) {
            ??????????????? getOutput() << val;
            ??????????????? return outputPrefix();
            ??????? }

            ?????? ~format_stream(void) {}
            ??? protected:
            ??????? inline std::ostream & getOutput(void)
            ??????? {
            ??????????????? return m_output;
            ??????? }
            ??????? void??? flushFormat(void)
            ??????? {
            ??????????????? if (*m_lpszFormat)
            ??????????????? {
            ??????????????????????? getOutput() << m_lpszFormat;
            ??????????????????????? m_lpszFormat = &g_nEndFlags;
            ??????????????? }??????
            ??????? }
            ??????? format_stream & outputPrefixLoop(void);
            ??????? format_stream & outputPrefix(void);
            ????
            ??????? static? char??? g_nEndFlags;
            ??????? std::ostream &? m_output;
            ??????? const char *??? m_lpszFormat;
            ??? };
            ???????
            ??? char format_stream::g_nEndFlags = char();

            ??? format_stream & format_stream::outputPrefix(void)
            ??? {
            ??????? char * lpPos = strchr(m_lpszFormat,'%');
            ??????? if (lpPos != NULL)
            ??????? {
            ??????????????? getOutput().write(m_lpszFormat, lpPos - m_lpszFormat);
            ??????????????? m_lpszFormat = lpPos + 1;
            ??????????????? if (*m_lpszFormat == '%' && *(m_lpszFormat + 1) != '%')
            ??????????????????????? return outputPrefixLoop();
            ??????? } // if (lpPos != NULL)
            ??????? else
            ??????????????? flushFormat();
            ??????? return *this;
            ??? }

            ??? format_stream & format_stream::outputPrefixLoop(void)??
            ??? {
            ??????? while (*m_lpszFormat == '%')
            ??????? {
            ??????????????? char * lpPos = strchr(m_lpszFormat + 1, '%');
            ??????????????? if (lpPos != NULL)
            ??????????????? {
            ??????????????????????? getOutput().write(m_lpszFormat, lpPos - m_lpszFormat);
            ??????????????????????? m_lpszFormat = lpPos + 1;
            ??????????????????????? if (*m_lpszFormat != '%' || *(m_lpszFormat + 1) == '%')
            ??????????????????????????????? break;
            ??????????????? } // if (lpPos != NULL)
            ??????????????? else
            ??????????????? {
            ??????????????????????? flushFormat();
            ??????????????????????? break;
            ??????????????? }
            ??????? } // while (*m_lpszFormat)
            ??????? return *this;
            ??? }

            ??? 1、規(guī)定以'%'作為占位符,表示后續(xù)的變量替換的位置。
            ???????
            ??? 2、兩個連續(xù)'%'即 '%%'表示一個真正的'%'。不過需要注意的是:一般想輸出百分?jǐn)?shù)的時候,就是要寫%%%,
            分析程序發(fā)現(xiàn)三個連續(xù)'%',則認(rèn)為第一個是占位符,后兩個表示一個'%'。而發(fā)現(xiàn)四個'%'的時候,前兩個都會被認(rèn)
            為是占位符,最后兩個被認(rèn)為是一個'%'。

            ??? 3、boost用%連接后面的多個變量,也有些類庫使用逗號。個人都不是很喜歡:'%'用得太多,程序看起來不好
            看;很多書都再三聲明最好不要重載逗號運算符。所以還是使用函數(shù)比較穩(wěn)妥,所以就用函數(shù)arg(a)的形式。如果真
            的喜歡使用'%'或者逗號,只需要增加成員函數(shù):
            ??????? template
            ??????????? inline format_stream & operator%(const typeArg1 & val) { return arg(val); }
            ??????? template
            ??????????? inline format_stream & operator,(const typeArg1 & val) { return arg(val); }
            ???????????????
            ??? 4、arg還可以繼續(xù)擴(kuò)展,
            ??????? a、同一個占位符輸出多個變量,只需要增加多幾個成員函數(shù):
            ??????? template
            ??????? inline format_stream & arg(const typeArg1 & val1,const typeArg2 & val2)
            ??????? {
            ??????????????? getOutput() << val << val2;
            ??????????????? return outputPrefix();
            ??????? }
            ??????? template
            ??????? inline format_stream & arg(const typeArg1 & val1,
            ??????????????????????????????? const typeArg2 & val2,
            ??????????????????????????????? const typeArg3 & val3)
            ??????? {
            ??????????????? getOutput() << val1 << val2 << val3;
            ??????????????? return outputPrefix();
            ??????? }
            ??????? 例如有時候想輸出一個范圍:
            ???????
            ??????? stream.format("range1:% range2:%").arg(lowerbound1,'-',upperbound1);
            ??????? stream.arg(lowerbound2,'~',upperbound2)
            ???????
            ??????? b、格式化輸出。printf那么多的格式化輸出參數(shù)寫在格式化字符串中,我老是會記錯,一旦寫錯
            ??????? 程序就容易出問題了(不單是顯示錯誤,還有可能會coredump),另外發(fā)現(xiàn)不同平臺格式還會有
            ??????? 些不一樣。還是寫在arg里面比較穩(wěn)妥,而且程序也容易閱讀。
            ???????
            ??????? 為了和上面"同一個占位符輸出多個變量"的函數(shù)區(qū)分,還是另外取一個函數(shù)名:
            ???????
            ??????? enum??? INT_BASE
            ??????????????? {BASE10=std::ios::dec, BASE8=std::ios::oct, BASE16=std::ios::hex};
            ??????? enum??? CHAR_CASE
            ??????????????? {CHAR_UPCASE=0, CHAR_LOWCASE=1 };
            ??????? enum??? BASE_FLAG
            ??????????????? {HIDE_BASE=0, SHOW_BASE=1 };
            ??????? enum??? POS_FLAG
            ??????????????? {HIDE_POS=0, SHOW_POS=1 };
            ??????? enum??? FIX_FLAG
            ??????????????? { FIXED=0, SCIENTIFIC=1 };
            ??????? enum??? POINT_FLAG
            ??????????????? { HIDE_POINT=0, SHOW_POINT=1 };
            ??????? enum??? ADJUSTFIELD_FLAG
            ??????? {
            ??????????????? ADJUST_LEFT=std::ios::left,
            ??????????????? ADJUST_RIGHT=std::ios::right,
            ??????????????? ADJUST_INTERNAL=std::ios::internal
            ??????? };

            ??????? template
            ??????????????? format_stream & argWithFormat(typeInt nVal,
            ??????????????????????? INT_BASE nBase = BASE10,
            ??????????????????????? CHAR_CASE bUpcase = CHAR_UPCASE,
            ??????????????????????? POS_FLAG bShowPos = HIDE_POS,
            ??????????????????????? BASE_FLAG bShowBase = HIDE_BASE,
            ??????????????????????? ADJUSTFIELD_FLAG nAdjust= ADJUST_LEFT,
            ??????????????????????? int nWidth = -1,char chFill = ' ')
            ??????? {
            ??????????????? std::ios::fmtflags nFlags = getOutput().flags();
            ??????????????? getOutput().setf((std::ios::fmtflags)nBase, std::ios::basefield);
            ??????????????? if (bShowPos == SHOW_POS)
            ??????????????????????? getOutput().setf(std::ios::showpos);
            ??????????????? else
            ??????????????????????? getOutput().unsetf(std::ios::showpos);
            ??????????????? if (bUpcase == CHAR_UPCASE)
            ??????????????????????? getOutput().setf(std::ios::uppercase);
            ??????????????? else
            ??????????????????????? getOutput().unsetf(std::ios::uppercase);
            ??????????????? if (bShowBase == SHOW_BASE)
            ??????????????????????? getOutput().setf(std::ios::showbase);
            ??????????????? else
            ??????????????????????? getOutput().unsetf(std::ios::showbase);
            ??????????????? getOutput().setf((std::ios::fmtflags)nAdjust, std::ios::adjustfield);
            ??????????????? if (nWidth != -1)
            ??????????????????????? nWidth = getOutput().width(nWidth);
            ??????????????? chFill = getOutput().fill(chFill);

            ??????????????? getOutput() << static_cast(nVal);

            ??????????????? getOutput().flags(nFlags);
            ??????????????? if (nWidth != -1)
            ??????????????????????? getOutput().width(nWidth);
            ??????????????? getOutput().fill(chFill);

            ??????????????? return outputPrefix();
            ??????? }
            ??????? 還可以增加浮點數(shù)、字符串等等的格式處理。
            ???????????????
            ??? 5、現(xiàn)在輸入的格式字符串,在類里面只是使用const char * m_lpszFormat來保存,一旦傳入的
            lpszFormat所指的資源已經(jīng)被釋放,則會造成非法內(nèi)存訪問。例如:
            ??? std::string???? getString(void) { ..... }
            ??? stream.format(getString().c_str());
            ??? stream.arg(...);
            ??? 如果要避免這種情況,應(yīng)該在format_stream里面增加一個std::string成員,記錄字符串指針。
            又或者應(yīng)該寫成:
            ??? std::string strTemp = getString();
            ??? stream.format(strTemp.c_str());
            ??? stream.arg(...)
            應(yīng)該如何處理,還是看各人的習(xí)慣和需求了。
            ???????
            ??? 6、當(dāng)輸入?yún)?shù)比占位符多的時候,則多余的參數(shù)都會輸出到格式字符串的后面。
            ??? 7、當(dāng)輸入?yún)?shù)比占位符少的時候,輸出則停留在第一個多余的占位符的前面。
            ??? 8、對于字符串,可以使用stringstream來輔助:
            ??? stringstream str;
            ??? format_stream fmt(str);
            ??? fmt.format(".....").arg(...);
            ??? myFun(str.str());
            ??? 當(dāng)然,經(jīng)過適當(dāng)?shù)母脑欤梢允诡惛奖闶褂茫@里就不再多說,各位高手自己發(fā)揮了。

            posted on 2005-10-08 14:25 cyt 閱讀(946) 評論(0)  編輯 收藏 引用

            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


             
            久久精品aⅴ无码中文字字幕重口| 久久中文骚妇内射| 国产亚洲成人久久| 久久青青草原精品国产软件 | 久久久久久久综合日本亚洲| 四虎国产精品免费久久久| 国产福利电影一区二区三区,免费久久久久久久精 | 亚洲精品国精品久久99热| 久久综合噜噜激激的五月天| 国产69精品久久久久9999| 精品久久久一二三区| 色综合久久综精品| 色欲综合久久中文字幕网| 蜜臀久久99精品久久久久久| 大伊人青草狠狠久久| 久久久久亚洲精品日久生情| 精品久久久久久无码国产| 久久婷婷五月综合97色一本一本| 精品久久人人爽天天玩人人妻| 久久亚洲精品无码AV红樱桃| 精品久久久久久久久免费影院| 精品久久久久久无码人妻热| 97久久精品国产精品青草| 久久婷婷人人澡人人爽人人爱| 国产成人久久精品麻豆一区| 国产精品99精品久久免费| 久久青青草原亚洲av无码app| 久久亚洲AV无码精品色午夜| 亚洲欧美国产精品专区久久| 久久综合给合综合久久| 久久国产高清一区二区三区| 91精品国产91热久久久久福利| 国产Av激情久久无码天堂| 国产V综合V亚洲欧美久久| 蜜臀av性久久久久蜜臀aⅴ| 久久国产色av免费看| 久久婷婷五月综合国产尤物app| 久久亚洲中文字幕精品有坂深雪| 色噜噜狠狠先锋影音久久| 久久国产香蕉一区精品| 国产精品青草久久久久福利99 |