顯示具有 [程式]C++ 標籤的文章。 顯示所有文章
顯示具有 [程式]C++ 標籤的文章。 顯示所有文章

2023年5月9日 星期二

讓 wxMediaCtrl 可播放

在網路上找到的資料或 AI 生成的範例,要真正能夠讓 wxMediaCtrl 動起來的方法都不是很完整,此文沒有高深的技巧,只是在初始建構上做補充。

要讓 wxMediaCtrl 能夠播放有兩點被 AI 忽略,建立時要指定後台播放器;以及要確定 Load 完成,即要捕捉 wxEVT_MEDIA_LOADED 這個事件。

2023年3月29日 星期三

多重字串替換

這是指在一次執行中把要替換的多筆字串一次完成,哪組先找到先替換,替換過的不能再被替換。有別於多次執行替換的處理。

關於拿掉 if (!f)   return Src; 的原因在,只有 Replacements 為空時才會有作用可提早離開,並不會影響功能的正確性,絕大多數 Replacements 並不會是空的,沒必要多此一舉。

正則表達式的特殊字元編碼與解碼

因 ChatGPT 同樣的問題每次的回答都不一樣,這次的作法覺得不錯,所以在這留一份。

對於詠唱詞我個人覺得,那是給 AI 看的不是給人看,意思是人是不是看得懂或是否覺得優美不重要,但若能兩者兼具那也很好,當作是詠唱詞與註解的結合

2022年11月8日 星期二

Association File 範例

這是用 CodeBlocks 製作的專案,並須備好 C++ 編譯器和 wxWidgets,主要在介紹幾個 wxWidgets 強大的功能。程式雖然在 Windows 系統環境下寫的,但因 wxWidgets  是跨平台的程式庫,因此在其他系統環境下也應該可行。

程式的主要目的在達成程式與關聯檔案(Association File)的聯結,只要對關聯資料檔案點兩下,就可以叫出程式來虙理。

2022年11月2日 星期三

在 Ubuntu 安裝 CxxlMan2 程式庫

這次的目標在安裝 CxxlMan2 程式庫和多國語言插件,以及用一個簡單的例子做範例。在 CxxlMan2 的部份先下載以下檔案,並解壓到一個資料夾中,我是放在 ~/MySrc

首先安裝好 C++ 編譯器,先下三道命令
$ sudo apt install gcc
$ sudo apt install c++
$ sudo apt-get install uuid-dev
再到 Ubuntu Software 安裝 CMake 及 Code::Blocks IDE,準備完成後就可以編譯安裝了。

編譯完成後的相關成品都要放到 /usr/local,也就是 Include 檔要放到 /usr/local/include,CxxlMan2 程式庫要放到 /usr/local/lib,Release 版的插件要放到 /usr/local/plugin,Debug 版的插件要放到 /usr/local/plugin_d。

2022年10月23日 星期日

C++20 UTF-8 的轉換

 一直都停留在使用 C++17 的標準,其中一個重要原因是 C++20 對 UTF-8 有了一個明確的型別定義,一些舊有的程式都過不了 C++20 這關,所以就一直攔著。

不過後來發現可以用強制型別指示轉換(type&)這招來破解,這招用在其他地方會很危險,因編譯器會無條件通過轉換,不會給你任何警告訊息。

C++20 對於 UTF-8 提供兩個新東西,一個 char8_t 型別,另一個是 std::u8string 類別,也只有這樣而已。最重要的 STL 完全只能用 char 和 std::string。

2021年12月10日 星期五

建置 VScode 的 C++ 開發環境

 VScode 進化非常神速,就 C++ 而言搭配 CMake 延伸模組的支援,以往那些麻煩的設定可以拋諸腦後了。

首先到 CMake 下載並安裝最新版的 CMake。

再去抓最新版的 MinGW ,我抓的是 x86_64-posix-seh,解壓到 C:\x86_64-8.1.0-release-posix-seh-rt_v6-rev0,並將 C:\x86_64-8.1.0-release-posix-seh-rt_v6-rev0\mingw64\bin 設定到環境變數 PATH,這點是必須的,因 VScode 會去找編譯器。

2021年10月19日 星期二

在 Windows 的 Console 顯示 utf-8

在 C++ 程式編譯之字串 一文中提到在 Console 顯示 wchar_t 字串的方法,但在 Windows 11 + MinGw 8.1.0 已經行不通了。不過現在比較流行用 UTF-8,若有在 Windows 的 Console 顯示 UTF-8 的須求,以下的方法很容易就能逹成

#include <iostream>
#include <Windows.h>
using namespace std;


int main(int, char**) 
{
  // Set console code page to UTF-8 so console known how to interpret string data
  SetConsoleOutputCP(CP_UTF8);

  // Enable buffering to prevent VS from chopping up UTF-8 byte sequences
  setvbuf(stdout, nullptr, _IOFBF, 1000);

  const char *str = u8"你好 こんにちは 안녕하십니까";

  cout << "str = " << str << endl;


  return 0;
}







2021年7月5日 星期一

多機率分佈

 這個小程式方便產生不同機率分佈的亂數,建構函數接受 vector<double> 含陣列各位置的機率分佈權值,實際運作時會傳回命中的陣列的索引

#include <chrono>
#include <random>
#include <iostream>
#include <vector>

using namespace std;

// 多機率分佈
class Multi_probability_distribution
{  
  size_t Max;
  vector<double> m_Probability_accumulation;
public:
  // Constructor
  Multi_probability_distribution(const vector<double> &Probability_distribution)
    :Max(Probability_distribution.size()-1),
    m_Probability_accumulation(Probability_distribution.size())
  {
    m_Probability_accumulation[0] = Probability_distribution[0];
    for (size_t i = 1; i <= Max; ++i)
      m_Probability_accumulation[i] = m_Probability_accumulation[i - 1] +
      Probability_distribution[i];

    double Max_v = m_Probability_accumulation[Max];

    for (double& v : m_Probability_accumulation)
      v /= Max_v;
  }

  size_t operator()()
  {
    static minstd_rand0 Generator((unsigned)
      chrono::system_clock::now().time_since_epoch().count());
    static uniform_real_distribution<double> Distribution(0.0, 1.0);
    double number = Distribution(Generator);

    size_t Start = 0, End = Max;

    // 二分搜尋加快速度
    while (Start != End)
    {
      size_t Sel = (Start + End)/2;
      if (number < m_Probability_accumulation[Sel])
        End = Sel;
      else
        Start = Sel + 1;
    }

    return Start;
  }
};

int main()
{
  vector<double> pd{1,3,5}; // 期望陣列各位置的機率分佈權值
  vector<size_t> Score(pd.size(),0); // 累記實際亂數產生所處位置

  Multi_probability_distribution MPD(pd);

  for (int i = 0; i < 100; ++i)
    ++Score[MPD()];

  for (int i = 0; i < Score.size(); ++i)
    cout << "[" << i << "] = " << Score[i] << endl;

}







2021年7月3日 星期六

UnassocWin10 解除檔案關聯

這個程式只能用於 Win10 和 Win11,若要用於 Win7,可上網找一套 unassoc 1.4。

我這程式主要參考 删除Windows10后缀名关联程序.cpp ,其實那個程式已經足夠輕巧好用了。我寫的須要包裹一堆程式庫,有點大包。

我寫這程式的目的為了保留和測試一些技術。

原始檔案包,須用最新版 CxxlMan2 先建構好開發環境
Unassociate_File_Types_1.0.1_Src.7z

採用 CMake 方式編譯的執行檔無法在變更語言後自動調整版面,可用 CodeBlocks 載入 Src 資料夾中的 UnassocWin10.cbp 編譯一個來用

64位元版完整檔案包,可直接執行 UnassocWin10.exe
UnassocWin10_1.0.1.7z

另外程式支援多國語言,但能力有限只提供繁中語言檔,其他的語言會用內建的英語顯示,若有人願意轉譯他國語言,可到 MLedit 多國語言編輯器  下載工具,這 UnassocWin10 的多國誩言檔放在 Lang 資料夾中。




2021年7月2日 星期五

取得 Windows 的版本

 在這找到好辦法 C++ How to detect Windows 10 - Stack Overflow ,保留一份

#include <iostream>
#include <windows.h>

using namespace std;

// 回報 Windows 的版本 (7, 8, 8.1, 10)
double getSysOpType()
{
    double ret = 0.0;
    NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOEXW);
    OSVERSIONINFOEXW osInfo;

    *(FARPROC*)&RtlGetVersion = 
      GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");

    if (NULL != RtlGetVersion)
    {
        osInfo.dwOSVersionInfoSize = sizeof(osInfo);
        RtlGetVersion(&osInfo);
        ret = (double)osInfo.dwMajorVersion;
    }
    return ret;
}

int main()
{
    cout << getSysOpType() << endl;
    return 0;
}





2021年6月30日 星期三

正則表達式檢測

編輯 C++ 正則表達式須要不斷嘗式,網路上找到一個簡單的程式碼(一時找不到在哪看到)蠻不錯的,留一份在這

#include <iostream>
#include <regex>

using namespace std;

int main()
{

  // regex reg("[\\.]|[\\b]+$");
  //regex reg("([.]*)([\\.]+)([.]*)");

  //regex reg(".*(\\.+).*");
  //regex reg(".*(\\s$)");
  //regex reg(".*(\\.+).*|.*(\\s$)");
  //regex reg("[\\s]+");
  regex reg("Applications\\\\.+_\\.bbbbb");

  string input;

  smatch sm;

  while(true)
  {
    cout << "Enter: ";
    getline(cin, input);
    if(input == "quit")
      break;

    if( regex_match(input, sm , reg) )
    {
      cout << "Match!" << endl;
      for( unsigned int i = 0 ; i < sm.size() ; ++i )
      {
        cout << i << ": [" << sm[i] << ']' << endl;
      }

    }
    else
    {
      cout << "Not Match!" << endl;
    }
  }

    return 0;
}

2021年3月18日 星期四

把 GLAD 編譯成 dll

因 LearnOpenGL 採用 GLAD 來抓取 OpenGL API,所以也研究了一下,GLAD 的好處是可以明確指定你開發程式所要支援的 OpenGL 版本,在初始化時可以檢查顯示卡是否能支援。

GLAD 可到 https://glad.dav1d.de 下載,但拿到的會是原始檔,因 GLAD 只是把 OpenGL API 的函數位址抓出來存放到程式可觸及的記憶體空間中,若採用把 glad.c 和你的專案一起編譯,則主程式(exe) 和各用到 OpenGL API 的 dll 都得把 glad.c 一起編譯,並各別呼叫 gladLoadGL() 做初始化,既浪費空問(因得各別保存 OpenGL API 的函數位址)又沒人性(因得各別 gladLoadGL() 初始化)。

我想最完美的做法是把 GLAD 編譯成 dll,這樣 GLAD 的 OpenGL API 函數位址就放在這個 dll 獨立空間中,而 gladLoadGL() 只要由主程式呼叫一次就可以了。

2021年2月16日 星期二

NeHe OpenGL 教學

這是很古早以前的教學了,但還是有它的參考和歷史價值,網路上還是可找到它的教學,唯原始碼的檔案不容易找到,這論壇的有心人有完整的保留,包括 C++ 原始檔,也做了中文翻譯,介紹給大家。

尤其是原始檔為了安全的理由,大家應保留一份。

 计算机科学论坛--NeHe OpenGL教程(中英文版附带VC++源码)中英文系列 (ieee.org.cn)

2021年1月28日 星期四

OIS 輸入設備程式庫

跨平台輸入設備程式庫,包含鍵盤 滑鼠 搖桿 觸控 ,支援 cmake 編譯

到 Releases · wgois/OIS · GitHub 抓取,我取得時是 1.5 版

看一下 demos\OISConsoleDemo 子目錄中的範例大概就知道的怎麼用,以下摘錄範例的 Win 平台做簡要說明

2020年9月4日 星期五

設計 Singleton 模式的插件

這裡的插件是指 CxxlMan2 程式庫的 cxxlObjectPlugin 插件,cxxlObjectPlugin 插件有一個特性,當某個 DLL 檔所提供的所有 cxxlObjectPlugin 物件已無使用者時,這個  DLL 檔就會被卸載。

但 DLL 檔提供的物件若是一般的 Singleton 模式物件,那麼永遠都會有一個不能放棄的持有記錄,即使已無持有者了,這個 DLL 檔也永遠卸不掉。這時可藉由 LifeCustody 這個工具的幫忙,就可以解決這問題。

因要設計成 DLL 和 使用端 兩部份,所以直接提供範例原始檔:
SingletonExample.zip

要編譯這範例須先如下的東東:

  1. CxxlMan2 程式庫 - 抓最版,順便說明檔也一起抓吧
  2. CMRegSelf 插件註冊輔助 - 內附說明
  3. LifeCustody 物件終結插件 - 內附說明

範例有提供 CMake 的支援,編譯不會很難

大致說一下這個範例,test.cpp 定義了兩個 class Input 及 class Output,建立後會各別由 DLL 插件取得 ISingleton 物件,因取得的 ISingleton 是同一個物件,所以 Input::PutStr() 輸入的文字可以由 Output::GetStr() 取出。當兩個 Input 及 Output 物件銷毀時也會通知 DLL 插件銷毀 ISingleton 物件。







2020年6月24日 星期三

函數中的靜態變數

函數中的靜態變數只在第一次呼叫這個函數才會建立,之後不管呼叫幾次都用的都是同一個,包括成員函數也一樣。如以下的範例:
 
#include <iostream>

using namespace std;

class A
{
  int m_v;
public:
  // Constructor
  A(int v)
  {
    m_v = v;
  }

  void Show()
  {
    cout << "數值:" << m_v << endl;
  }
};

class B
{
public:
  // Constructor
  B()
  {}

  void Show(int v)
  {
    static A a(v); // 函數中的靜態變數
    a.Show();
  }
};


int main()
{
  B b1;
  B b2;

  b1.Show(1); // 第一次執行會設定靜態變數,往後用的都是同一個
  b1.Show(11);

  b2.Show(2);
  b2.Show(22);

  return 0;
}




2020年3月3日 星期二

莫名其妙的問題

以下程式使用 MinGW 8.1.0 64位元版(x86_64-posix-seh) 編譯

採用 Release 和 Debug 兩種模式編譯的執行結果不一樣(另人傻眼)

本來想說是不是編譯器的 bug,但有以下的訊息:
the compiler can assume that the address of 'p' will never be NULL [-Waddress]

更另人傻眼了

2020年1月15日 星期三

打造在 Win10 的 C++ 編譯環境

此文有點像廢文,因每人須求不同,所以做法也不一樣,所以只能說給大家作為參考。

這裡用的編譯器是 MinGW 系列,可到這裡下載,至此文發佈時間為止,提供了如下最新的版本:
▲MinGW 各版本列表