1. 程式人生 > >C++入門簡單例項

C++入門簡單例項

教授C++,如果還使用Hello World的例子作為入門,那就弱爆啦!它只能告訴你不要用printf,要用cout。但是,為什麼?這兩個有什麼區別?cout就代表了C++嗎?我們還是整點有技術含量的吧。

問題編寫“字串與數值互相轉換”的函式。

1. C語言風格

/* C 風格編碼*/
#include <cstdlib>
#include <cstdio>
using namespace std;

void value2str(int value)
{
    char str[30] = {'\0'};

    itoa(value, str, 10); //C標準庫有這個函式麼?
    printf("string : %s\n", str);
}

void str2value(char* str)
{
    int value = atoi(str);
    printf("value : %d\n", value);    
}

這種方式至少存在如下幾個問題:(1)字串的長度有限制;(2)必須預先定義一個數組儲存字串,使用陣列也有記憶體洩露的危險;(3)呼叫C的庫函式,受制於函式引數約束。

2. C++風格

/* C++ 風格編碼*/
#include <string>
#include <sstream>

using namespace std;

/* 整型-> 字串*/
string ValueToStr(int value)
{
    ostringstream ost;
    ost << value;

    return ost.str();
}

/* 字串-> 整型*/
int StrToValue(char* str)
{
    string strValue(str); //轉換為string
    istringstream osValue;
    osValue.str(strValue); //得到istrstream

    int value;
    osValue >> value; //得到數值

    return value;
}

使用C++的string stream,可處理變長字串,無記憶體洩露之虞。但無擴充套件性,因為如果要求是double型別與字串互相轉換,需要再寫兩個過載函式。


3. 函式模板

/* 函式模板*/
template <typename T>
string Value2Str(T value)
{
    ostringstream ost;
    ost << value;
    return ost.str();
}

template<typename T> 
T Str2Value(char* str)
{
    string strValue = str; //轉換為string
    istringstream osValue;
    osValue.str(strValue); //得到istrstream

    T value;
    osValue >> value; //得到數值

    return value;
}


使用template,可處理各種資料型別和字串的轉換,使用者程式碼中呼叫了哪個型別,編譯器才會編譯相應的目的碼,靈活性很大。


當然這個例子中還要考慮字串轉換出來的數值,不能超出資料型別的最大值,這個不是講述的重點。重點在於,通過這幾種風格的程式碼,展現一下為了解決一個簡單的問題,在C++中我們到底能有多少選擇。

我是因為平時編寫程式碼時需要用到上述功能,用的多了,就慢慢總結出了這麼一套做法,當然比較粗糙,下面來看個不粗糙的。

某日翻閱boost的文件,發現boost里居然已經提供了類似功能的lexical_cast。

其定義形式如下:

namespace boost
{
    class bad_lexical_cast;
    template<typename Target, typename Source>
    Target lexical_cast(const Source& arg);
}

也是採用模板的形式定義的一套東西,用於string和數值的相互轉換。簡單的使用例子如下:


#include <boost/lexical_cast.hpp>

//下面的例子把一系列數字作為命令列引數:
int main(int argc, char * argv[])
{    
    using boost::lexical_cast;   
    using boost::bad_lexical_cast;

    std::vector<short> args;

    while(*++argv)    
    {
        try
        {
            args.push_back(lexical_cast<short>(*argv));    
        }
        catch(bad_lexical_cast &)      
        {
            args.push_back(0);    
        }
    }
    //...
}

//下面的例子使用字串表示式來表示數字:
void log_message(const std::string &);
void log_errno(int yoko)
{
    log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
}

和我的設計具有相同的一個缺陷,浮點數的精度無法控制。更詳細的內容,請參見boost庫的相關文件。

結語:從上面的例子我們可以看出,同樣是使用C++語言,不同的程式設計風格寫出來的程式碼卻相差很大。C++功力越深,寫出來的程式碼越抽象,越難以理解,但越靈活,越簡潔。當然,程式碼寫得越簡潔,也有老闆越覺得你工作偷懶的危險^_^。