C++字串和數位轉換完全攻略

2020-07-16 10:04:42
以字串形式儲存的數位和以數位形式儲存的數位之間是有區別的。

例如,字串 "2679" 就不是一個數位:它是由 2、6、7、9 這 4 個字元的 ASCII 碼組成的序列。由於字串 "2679" 不是一個數位,所以編譯器將不允許對它進行加法、乘法和除法之類的數學運算。以數位表示的字串必須首先轉換為數位形式,然後才能與算術運算子一起使用。

同樣地,數位形式的程式值,例如 int、long 和 double 等,有時也需要轉換為字串形式,這樣結果字串才能立即輸出到檔案或其他輸入輸出裝置,或者存入記憶體中的某個字串物件,供以後使用。

當使用者在鍵盤上輸入一個數位時,該數位以字串的形式輸入,就好像使用者輸入的一系列字元(數位)。在 C++ 中,這樣的數位通常通過流提取運算子 >> 來讀取。在儲存到數位型別的變數之前,該運算子會根據需要自動執行轉換。在輸出期間,數位到字串的反向轉換由流輸出運算子 << 執行。

使用字串流物件進行數位轉換

C++ 有兩個類,ostringstream istringstream,可以用來對記憶體中的值執行字串/數位轉換。

ostringstream 類是 ostream 的子類(cout 也屬於該類),並使用流插入運算子 << 將數值轉換為字串。ostringstream 型別物件的工作方式與cout和檔案物件的工作方式相同,但它不是將資料寫入螢幕或檔案,而是寫入它所包含的字串物件中。

每次在 ostringstream 物件上使用 << 時,它都會執行必要的數位到字串的轉換,並將結果追加到其字串的末尾。除了支援 ostream 類的所有成員函數和運算子外,ostringstream 物件還支援表 1 中所示的 str 成員函數。

istringstream 類是從 istream 派生的。它內部包含一個字串物件,函數將它作為可以從中"讀取"的輸入流。

輸入流可以在建立物件時由 istringstream 建構函式設定,也可以在建立物件後通過呼叫 str(string s) 函數來設定。流提取操作符 >> 從封閉的字串中讀取,並在必要時將字串轉換為數位。表 1 列出了 istringstream 的成員函數,必須在程式中包含 sstream 標頭檔案才能使用這些類。

表 1 ostringstream 和 istringstream 類的成員函數
成員函數 描 述
istringstream(string s) istringstream 的建構函式:設定物件的輸入流的初始值。範例:
istringstream istr ("50 64 28");
ostringstream(string s) ostringstream 的建構函式:設定物件的輸出流的初始值。範例:
ostringstream ostr("50 64 28");
string str() 返回 ostringstream 或 istringstream 物件中包含的字串。範例:
string is = istr.str();
string os = ostr.str ();
void str(string &s) 設定作為物件的輸入或輸出流的字串。範例:
ostr.str ("50 64 28");
istr.str("50 64 28");

下面的程式演示了這些類的用法:
//This program illustrates the use of sstream objects
#include <sstream>
#include <iostream>
#include <string>
using namespace std;

int main()
{
    string str = "John 20 50"; // string to read from
    const char *cstr = "Amy 30 42"; // Cstring to read from
    istringstream istr1 (str);    // istr1 will read from str
    istringstream istr2; // istr2 will read from cstr
    ostringstream ostr; // The ostringstream object to write to
    string name;
    int score1, score2, average_score;

    // Read name and scores and compute average then write to ostr
    istr1 >> name >> score1 >> score2;
    average_score = (score1 + score2)/2;
    ostr << name << " has average score" << average_score << "n";
    // Set istr2 to read from the C string and repeat the above
    istr2.str(cstr);
    istr2 >> name >> score1 >> score2;
    average_score = (score1 + score2)/2;
    ostr << name << " has average score" << average_score << "n";
    // Switch to hexadeximal output on ostr
    ostr << hex;
    // Write Amy's scores in hexadecimal
    ostr << name << "'s scores in hexadecimal are: " << score1 << " and " << score2 << "n";
    // Extract the string from ostr and print it to the screen
    cout << ostr.str();
    return 0;
}
程式輸出結果:

John has average score35
Amy has average score36
Amy's scores in hexadecimal are: 1e and 2a

請注意,這些類具有 ostream 和 istream 物件的全部功能,包括使用八進位制和十六進位制等不同進位制將數位轉換為字串的能力。當然,它們也是有缺陷的,它們強制程式設計師建立 sstream 物件,只有這樣才能使用它們的插入和提取運算子執行轉換。

數位轉換函數

C++ 11 提供了若干 to_string(T value) 函數來將 T 型別的數位值轉換為字串形式。以下是幾個 to_string() 函數的列表:

string to_string(int value)
string to_string(long value)
string to_string(double value)

來看以下程式碼範例:
int a = 5;
string str = to_string(a*a);
cout << " The square of 5 is " << str << endl;
以上範例即顯示了該系列函數的用法。它將列印如下字串:

The square of 5 is 25

to_string() 函數無法處理非十進位制整數的轉換。如果需要該功能,則應該使用 ostringsteam 物件來完成該轉換。

字串到數位的轉換可以通過 stoX() 系列函數來執行。該系列函數的成員可以將字串轉換為 int、long、float 和 double 型別的數位。具體語法如下所示:

int stoi(const strings str, size_t* pos = 0, int base = 10)
long stol(const strings str, size_t* pos = 0, int base = 10)
float stof(const strings str, size_t* pos = 0)
double stod(const strings str, size_t* pos = 0)

第一個形參 str 是一個字串(例如 "-342" 或 "3.48" 等),它將被轉換為恰當的數位形式。這些函數可以將 str 可能的最長字首轉換為數位,並返回一個整數地址 pos,pos 中儲存了 str 無法被轉換的第一個字元的索引。型別 size_t 是在標準庫中定義的,常用於表示無符號整數的大小或陣列、向量、字串中的一個索引。

例如,如果試圖轉換字串 "-34iseven",則將成功返回整數 -34,而無法轉換的第一個字元的位置 pos 則被設定為 3。base 形參僅適用於整數轉換,指示用於轉換的進位制。pos 和 base 形參都是可選的,所以它們可以被忽略。如果 pos 被忽略,則不會儲存停止字元的索引。如果 base 被忽略,則預設為十進位制。如果字串 str 包含一個無效值,例如 "is-34 even?",則不會進行轉換,函數將丟擲一個 invalid_argument 異常。

下面的程式演示了字串轉換函數的用法:
// This program demonstrates the use of the stoXXX()
// numeric conversion functions.
#include <string>
#include <iostream>
using namespace std;

int main()
{
    string str; // string to convert
    size_t pos; // Hold position of stopping character
    //Convert string to double
    str = "-342.57is a number";
    cout << "The string is " << str << endl;
    double d = stod(str, &pos);
    cout << "The converted double is " << d << endl;
    cout << "The stopping character is " << str[pos] << " at position " << pos << endl;
    // Convert string to int (default to decimal)
    str = "-342.57is a number";
    cout << "nThe string is " << str << endl;
    int i = stoi(str, &pos);
    cout << "The converted integer is " << i << endl;
    cout << "The stopping character is " << str[pos] <<" at position " << pos << endl;
    // Convert string to int (base is binary)
    str = "01110binary number";
    cout << "nThe string is " << str << endl;
    i = stoi (str, &pos, 2);
    cout << "The converted binary integer is " << i << endl;
    cout << "The stopping character is " << str[pos] << " at position " << pos << endl;
    return 0;
}
程式輸出結果:

The string is -342.57is a number
The converted double is -342.57
The stopping character is i at position 7

The string is -342.57is a number
The converted integer is -342
The stopping character is . at position 4

The string is 01110binary number
The converted binary integer is 14
The stopping character is b at position 5