Qt 的 QString 跟標準程式庫 (standard library) 中的 string 雖然都以字元 (character) 為元素 (element) ,卻是不同的型態 (type)
我們在單元 20 - 型態轉換問題介紹過基本內建型態 (primitive built-in data type) 的轉換問題,可是 QString 與 string 都是類別 (class) 定義的型態,因此兩者有各自不同的成員 (member) ,編譯器 (compiler) 認為 QString 是 QString ,而 string 是 string ,像 QString 的前綴 Q 就是標明這是 Qt 程式庫 (library) 的字串 (string) 類別。
基本上 Qt 的視窗介面無論顯示或接收都是 QString 字串,因此當我們想要把 Encrypt 的密碼表顯示在 label_display 的時候就會產生無法處理的問題。
解決這問題有兩種途徑,第一種就是回頭修改 Encrypt 類別,把密碼表從 string 改成 QString ,這樣一來,放到 label_display 或其他 Qt 視窗元件上就完完全全沒有問題了說。
這是種解決方式,聽起來還不賴!可是會讓 Encrypt 僅限於使用 Qt 程式庫,假如改天要換到另一種 GUI 程式庫的時候,就變成 QString 的地方又要全部改寫,反倒很麻煩,不是嗎?
第二種途徑則是進行型態轉換,利用 QString 提供轉換成字元陣列 (array) 的函數 (function) 來進行,這樣子我們需要宣告兩個新成員函數 (member function) 在 encryptwindow.h 的 EncryptWindow 類別宣告中
QString s2q(const string &);
string q2s(const QString &);
完整程式請參考範例程式碼的 encryptwindow.h 。
s2q() 將 string 型態的物件 (object) 轉換成 QString 型態,最後回傳 QString 型態的物件, q2s() 則是相反過來,兩者的參數 (parameter) 都是 const 參考 (reference) ,實作如下
// 將 string 轉換成 QString
QString EncryptWindow::s2q(const string &s) {
return QString(QString::fromLocal8Bit(s.c_str()));
}
// 將 QString 轉換成 string
string EncryptWindow::q2s(const QString &s) {
return string((const char *)s.toLocal8Bit());
}
完整程式請參考範例程式碼的 encryptwindow.cpp 。
這樣的轉換方式類似把物件轉換成字元陣列,再利用 QString 或 string 的建構函數 (constructor) 回傳 QString 或 string 型態的物件。
on_pushButton_new_clicked() 的實作就要加進 s2q() ,如下
ui->label_display->setText(s2q(e->get_code_array()));
重新執行就沒問題囉!
接下來繼續實作 on_pushButton_encode_clicked() 及 on_pushButton_decode_clicked() ,前者對使用者輸入的字串進行編碼,如下
// 按下「編碼」按鈕的事件
void EncryptWindow::on_pushButton_encode_clicked()
{
// 取得使用者輸入的英文句子
input_text = ui->lineEdit_input->text();
// 先測試使用者是否有輸入
if (input_text == "") {
// 使用者沒有輸入,在 label_display 顯示提示訊息
ui->label_display->setText("沒有輸入字串!");
}
else {
// 使用者有輸入,測試使用者是否有按過「新建」按按鈕
if (e == nullptr) {
// 沒按過「新建」按鈕,在 label_display 顯示提示訊息
ui->label_display->setText("沒有編碼物件!");
}
else {
// 有按過「新建」按鈕,進行編碼工作並將結果顯示在 lineEdit_output
output_text = s2q(e->ToEncode(q2s(input_text)));
ui->lineEdit_output->setText(output_text);
ui->label_display->setText("結果如上");
}
}
}
這裡針對兩種情況分別做了預防措施,第一種情況測試使用者是否有輸入,如果沒有輸入那麼從 lineEdit_input 取得的 input_text 就會是空字串,由於沒有輸入的話,進行編碼也就沒有意義,因此直接在 label_display 顯示提示訊息。
第二種是當使用者有輸入的情況,先測試使用者是否有按過 新建 按鈕,由於有按過 新建 按鈕才有建立 Encrypt 型態的資料成員 e ,也才可以實際進行編碼或解碼,因此如果 e 為 nullptr 的話就直接在 label_display 顯示提示訊息。
因此只有在使用者有輸入及有按過 新建 按鈕的情況下才會進行編碼或解碼。
至於 on_pushButton_decode_clicked() 跟 on_pushButton_encode_clicked() 非常相似,除了把 ToEncode() 換成 ToDecode() 之外
output_text = s2q(e->ToDecode(q2s(input_text)));
來執行測試看看囉!編碼結果如下
解碼結果如下
還不錯,接下來我們繼續實作 存檔 及 載入 按鈕,也就是實作存檔與載入的功能。
相關教學影片
中英文術語對照 | |
---|---|
標準程式庫 | standard library |
字元 | character |
元素 | element |
型態 | type |
基本內建型態 | primitive built-in data type |
類別 | class |
成員 | member |
編譯器 | compiler |
程式庫 | library |
字串 | string |
陣列 | array |
函數 | function |
成員函數 | member function |
物件 | object |
參數 | parameter |
參考 | reference |
重點整理 |
---|
1. Qt 的 QString 與標準程式庫的 string 是不同的資料型態,兩者都是以字元當元素。 |
2. QString 與 string 的轉換方式類似先轉換成字元陣列,再由各自的建構函數回傳屬於該型態的陣列。 |
3. GUI 中的編碼與解碼先進行兩項預防措施,先測試使用者是否有輸入,再測試使用者是否有按過 New 按鈕。 |
問題與討論 |
---|
1. 比較兩種解決 QString 與 string 不相通的途徑,列舉各自的優點及缺點。 |
2. 為什麼編碼與解碼要先進行兩項預防措施?如果不做會怎麼樣嗎? |
練習 |
---|
1. 承接上一個單元的 guess_game 專案,實作 Guess 按鈕,所有提示訊息都顯示在下方的 Text Browser 上。 |
2. 承上題,除了 QString 與 string 需要互相轉換外,回傳猜測紀錄的 get_times() 為整數型態,這可以用 QString 中的 static 成員函數 number() 來轉換。 |