2021

在 wxWidgets 中執行繁重工作時不讓 UI 凍結的作法

我想要用 wxWidgets 寫一個程式,能夠掃瞄整個目錄結構,然後把不需要的檔案刪掉。掃瞄這件事情可以用遞迴來做:

void MainFrame::RecursiveClean(const wxString& dirname) {
  wxDir dir(dirname);
  if (!dir.IsOpened()) {
    return;
  }
  wxString name;
  wxFileName fn(dirname, "");
  bool found = dir.GetFirst(&name);
  while (found) {
    wxString fullpath = fn.GetPathWithSep() + name;
    if (wxDirExists(fullpath)) {
      if (delete_folder_patterns_.Match(name)) {
        // ...delete folder...
      } else {
        RecursiveClean(fullpath);
      }
    } else if (wxFileExists(fullpath)) {
      if (delete_file_patterns_.Match(name)) {
        // ...delete file...
      }
    }
    found = dir.GetNext(&name);
  }
}
Code language: C++ (cpp)

但掃瞄的過程很花時間。如果我們就直接這樣硬幹,在掃瞄的過程中,wxWidgets 就沒有辦法處理事件,導致整個 UI 就會停在那邊沒有反應。所以我們要想個方法去解決。

Read More

用 Rust 寫簡單的互動式命令列程式

最近在研究 1904 年日期系統,想說寫一個簡單的 Rust 程式來測試一下想法。主要的轉換函式寫完後,希望把程式寫成簡單的互動式程式,方便測試。

參考網路上的文章,結果如下:

// 先不用管 y1904 的細節,在這個範例中不重要。
mod y1904;

// 使用 std::io::Write 是為了 flush()
use std::io::{stdin, stdout, Write};
use y1904::*;

fn main() {
    loop {
        // 記得轉成 lowercase,比較好處理
        match prompt_for_input("> ").to_ascii_lowercase().as_str() {
            "exit" => break,
            s @ _ => match s.parse::<u64>() {
                Ok(num) => println!("{:?}", num_to_date(num)),
                _ => continue,
            },
        }
    }
}

fn prompt_for_input(prompt: &str) -> String {
    print!("{}", prompt);

    // 如果沒有呼叫 flush() 的話,在使用者輸入之前,上一行可能不會印出來
    stdout().flush().unwrap();

    let mut result = String::new();
    stdin().read_line(&mut result).unwrap();

    // 使用 trim() 去掉換行符號。
    // trim() 回傳的是 &str,因此要再轉成 String 回傳
    result.trim().to_string()
}

至於 y1904 的內容.... 之後再說好了。 XDD

全主場時代球迷與球團的心態調整

按:此文為 2014 年 Lamigo 桃猿隊實施「全猿主場」之初,於 Blogger 及 PTT 上發表過的文章,單純搬運回來當作備份。

我從職棒紀元前的「甲組成棒聯賽」開始看台灣成棒/職棒,看著看著竟也有二十餘年了。職棒走過了二十多年的「草創時期」,今年終於有個球團完全落實屬地主義,打破二十多年來「壁壘分明」、「漢賊不兩立」的傳統,將整個內野區劃為「主場球隊責任區」。突破「傳統」的做法想當然爾會引起話題和爭論,不過平心而論,這樣的做法完全符合世界潮流,是中華職棒的一大進步;球迷間的反應也以正面居多。而其他球團雖然有些反對的雜音,但目前的趨勢看起,各隊都多多少少朝著「全主場」的方向前進中。

不諱言地說,我目前支持的球隊正是實施「全猿主場」的 Lamigo 桃猿,今年的「全猿主場」當然也進場體驗過了幾次。對於球團努力的成果,我給予高度的肯定!不過,也許是二十多年來那種壁壘分明的對立心態還存在我們心中,我覺得球迷們(尤其是客隊的球迷)好像還沒有準備好接受這樣的改變。另外,目前的「全猿主場」做法我也覺得還有些可以調整的地方,藉由這篇文章來一起討論。

Read More

Rustlings 習題探討:errors6.rs

主要是要練習如何撰寫及應用 error conversion。

整個程式是要實作一個新的型別 PositiveNonzeroInteger,意即「正整數」;0 或負整數都不是合法的。這個正整數要從字串 parsing 而來。如果 parsing 時就出問題,要把 parse() 的 error 轉換成 ParsePosNonezeroError::ParseInt();而如果 parsing 沒問題,但數值本身是 0 或負整數的話,就要回傳 ParsePosNonezeroError::Creation()(依據數值是 0 或負整數,會代不同的 error code)。

Conversion 的部份很單純:

impl ParsePosNonzeroError {
    fn from_creation(err: CreationError) -> ParsePosNonzeroError {
        ParsePosNonzeroError::Creation(err)
    }

    fn from_parsing(err: ParseIntError) -> ParsePosNonzeroError {
        ParsePosNonzeroError::ParseInt(err)
    }
}

比較有趣的是應用的部份。

Read More

Dev-C++ 的前世今生

Dev-C++ 是一套 Windows 上免費(且開放原始碼)的 C/C++ 整合式開發環境 (IDE)。它的 GUI 部份基本上是使用 Delphi 寫成,而背後的編譯器則是使用 Mingw 版本的 GCC。因為可以免費取得,而且安裝、使用上又方便(跟原始 Mingw GCC 比較的話),所以不少學校在教 C++ 的時候,都建議學生使用這一套 IDE。

但 Dev-C++ 在網路上有幾個常見的分支,常常看到初學者使用非常舊的版本,不但編譯器不支援新的 C++ 語法,而且 Dev-C++ 本身還可能有尚未修正的 bug。在此稍微聊一下 Dev-C++ 常見的幾個版本,並且提出給 C/C++ 初學者的建議。

Read More

[Exercism][Rust] Diffie Hellman

題目網址(需登入 Exercism)

這個題目在 Rust 語言方面,沒有什麼太困難的地方。所以重點都是在 modular arithmetic 的運算上。

use rand::Rng;

pub fn private_key(p: u64) -> u64 {
    let mut rng = rand::thread_rng();
    rng.gen_range(2..p)
}

pub fn public_key(p: u64, g: u64, a: u64) -> u64 {
    modular_exp(g, a, p)
}

pub fn secret(p: u64, b_pub: u64, a: u64) -> u64 {
    modular_exp(b_pub, a, p)
}
Read More