顯示具有 [程式]技術資料 標籤的文章。 顯示所有文章
顯示具有 [程式]技術資料 標籤的文章。 顯示所有文章

2022年10月4日 星期二

2022年7月31日 星期日

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年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;
}





2020年4月20日 星期一

白話設計原則

  • 里氏替換原則(Liskov Substitution principle)
    是對子類別設計的勸說或約束,要求在不修改使用端的程式演算法之下,使用到父類別實例的地方,改用子類別的實例去替代,都不會出錯

  • 依賴反轉原則(Dependency inversion principle,DIP)
    古老以前,要設計上層的的功能,得須了解下層元件有哪些功能再針對這些元件去設計,設計完之後,上層就被這些元件綁死了,上層強烈依賴下層,而且耦合度非常高。後來改成要下層去依照上層的需求來設計元件,所以才叫依賴反轉。
    不過現在一般都是依賴在一個介面,上層依介面提供的功能來使用,下層依介面設計提供服務的元件,而且耦合度降低。而介面標準也成了兵家必爭之地。

  • 開閉原則(對擴展開放,對修改封閉)
    概念上是說一個類別設計完成之後,就不應再去更動它,若要增加新功能,應該用繼承或組合去擴展,也就是說用擴展代替修改。

  • 封裝變化
    是指須要修改程式碼的部份獨立出來,通常都用策略模式來解決

  • 單一職責原則(Single responsibility principle)
    簡單地說就是類別的合理分割,但問題就在怎樣分割,分割到怎樣的程度才叫合理,十個人做十個都不一樣,只能說設計時要盡量考量清楚,途中有發現不適合也要大膽改正,畢竟日後的維護要比設計時花更多的精神和時間

  • 介面隔離原則(英語:interface-segregation principles)
    對於特定的使用端(角色)只提供符合它的介面給它用就好,實際運作的物件不要暴露給它。


2018年10月26日 星期五

插件成了 header only 的罩門

什麼是 header only? 可以先看此文了解一下 http://zevoid.blogspot.com/2012/04/c11-extern-template.html

簡單的說,header only 是把一個 class 的程式碼就包含在這個 class 中,而這個 class 就放在引入檔(.h)中供大家使用。有別於引入檔只放 class 介面,程式碼則放在 .cpp 中。

header only 的好處是執行快,因一大部份的函數可以用 inline 的方式呼叫,另外也不用再加 .cpp 或是還要連結程式庫(lib 或 dll)。

但有一個不得不面對的問題,class 的程式碼因不放在特定的 .cpp 中,那麼使用它的模組(exe、lib、dll)都得編譯出各別的執行碼,一般來說除了程式會比較胖之外,也沒有其它不好的影響。但是遇到插件就出問題了。

插件是一個 dll 檔,特點是要用的時候才載入,不用的時候可以卸載,但若某一個 class 產生的物件,其執行碼在那個被卸載的 dll 中,就會出大問題了,以下範例程式就是在演示這種情況。

2018年7月7日 星期六

快速排序法改良版

因遞廻會有爆掉堆疊的危險,所以若有可能盡可能用廻圈,但是不是可以用廻圈取決於關鍵變數,在一個廻圈後是不是須要保留其值,若不須要則可以重設其值,進行下一個廻圈的運行

以下用快速排序法做進一步的說明,先說它的改良法是青衫教的,我一直銘記在心

因快速排序法運行一個回合後會由定位點分割成左右兩部份,若要重設關鍵變數再處理左邊部份,右邊就失去關鍵變數沒法處理,反過來做亦相同,因此就讓較短的那邊用遞廻,長的那邊用廻圈

2018年4月8日 星期日

instal 是 windows 執行檔名的特殊關鍵字

只要執行檔名含有 instal,無論位於哪個位置都會被視為安裝程式,不會用一般程式的方式啟動,害我抓 bug 抓了老半天

jhfcaginstalhfhgfg.exe 這個不是一般程式



2018年4月5日 星期四

nPr 排列法

這方法會比旋轉要來得快

#include <functional>   // std::function
#include <memory>       // std::shared_ptr
#include <vector>
#include <iostream>

using namespace std;

// n 取 r 做排列
// 採用逆時旋轉排列法
// 必須 n >= r
class Permutation_nPr
{
  // 回報結果
  function<void(const shared_ptr<vector<unsigned char> > &, size_t)> 
    m_Report;
  // 放置要排列的數字
  shared_ptr <vector<unsigned char> > m_Digital_Array;
  // 要做排列的數目值
  size_t m_r;

  void v(size_t n, size_t r)
  {
    if (r == 0)
      m_Report(m_Digital_Array, m_r);
    else
      v(n - 1, r - 1);

    for (size_t j = n; j > 0; --j)
    {
      {
        unsigned char tmp = m_Digital_Array->at(n);
        m_Digital_Array->at(n) = m_Digital_Array->at(j-1);
        m_Digital_Array->at(j - 1) = tmp;
      }

      if (r == 0)
        m_Report(m_Digital_Array, m_r);
      else
        v(n - 1, r - 1);

      {
        unsigned char tmp = m_Digital_Array->at(n);
        m_Digital_Array->at(n) = m_Digital_Array->at(j-1);
        m_Digital_Array->at(j - 1) = tmp;
      }
    }
  }

public:
  Permutation_nPr(
   const function<void(const shared_ptr<vector<unsigned char> > &, size_t)>
      &Receive
  ):m_Report(Receive)
  {}

  void nPr(size_t n, size_t r)
  {
    m_r = r;
    m_Digital_Array =
       shared_ptr<vector<unsigned char> >(new vector<unsigned char>(n));
    size_t i = n;
    while (i--)
    {
      m_Digital_Array->at(i) = i;
    }
    v(n - 1, r - 1);
  }
};



class MsgShow
{
  int N{1};
public:
  void ResetN(){N = 1;}
  void operator()(
    const shared_ptr<vector<unsigned char> > &Digital_Array, size_t r)
  {
    cout << N << ":\t";
    for (size_t i = Digital_Array->size() - 1; r > 0; --i, --r)
      cout << (int)Digital_Array->at(i) << ' ';
    cout << endl;
    ++N;
  }
};

int main()
{
  MsgShow Report;
  Permutation_nPr P(Report);

  cout << '\n' << "4P3 排列:" << endl;
  Report.ResetN();
  P.nPr(4,3);

  return 0;
}



2018年3月15日 星期四

n 取 r 逆時鐘旋轉排列法

#include <functional>   // std::function
#include <memory>       // std::shared_ptr
#include <vector>
#include <iostream>
using namespace std;
// n 取 r 做排列 
// 採用逆時旋轉排列法
// 必須 n >= r
class Permutation_nPr
{
  // 回報結果
  function<void(const shared_ptr<vector<unsigned char> > &, size_t)> m_Report; 
  // 放置要排列的數字
  shared_ptr <vector<unsigned char> > m_Digital_Array;
  // 要做排列的數目值
  size_t m_r;
  void v(size_t n, size_t r)
  {
    size_t i = n + 1;
    while (i--)
    {
      if (r == 0)
        m_Report(m_Digital_Array, m_r);
      else
        v(n - 1, r - 1);
      unsigned char tmp = m_Digital_Array->at(n);
      for (size_t j = n; j > 0; --j)
        m_Digital_Array->at(j) = m_Digital_Array->at(j - 1);
      m_Digital_Array->at(0) = tmp;
    }
  }
public:
  Permutation_nPr(
     const function<void(const shared_ptr<vector<unsigned char> > &, size_t)> 
      &Receive
  )
     :m_Report(Receive)
  {}
  void nPr(size_t n, size_t r)
  {
    m_r = r;
    m_Digital_Array = 
       shared_ptr<vector<unsigned char> >(new vector<unsigned char>(n));
    size_t i = n;
    while (i--)
    {
      m_Digital_Array->at(i) = i;
    }
    v(n - 1, r - 1);
  }
};
int N = 1;
void Show(const shared_ptr<vector<unsigned char> > &Digital_Array, size_t r)
{
  cout << N << ":\t";
  for (size_t i = Digital_Array->size() - 1; r > 0; --i, --r)
    cout << (int)Digital_Array->at(i) << ' ';
  cout << endl;
  ++N;
}
int main()
{
  Permutation_nPr P(Show);
  cout << "4P3 排列:" << endl;
  N = 1;
  P.nPr(4, 3);
  return 0;
}

2018年3月14日 星期三

n 取 n 逆時鐘旋轉排列法


#include <functional>   // std::function
#include <memory>       // std::shared_ptr
#include <vector>
#include <iostream>
using namespace std;
// n 取 n 做排列 
// 採用逆時旋轉排列法
class Permutation_nPn
{
  // 回報結果
  function<void(const shared_ptr<vector<unsigned char> > &)> m_Report;
  // 放置要排的數字
  shared_ptr <vector<unsigned char> > m_Digital_Array;
  void v(size_t n)
  {
    if (n == 0)
      m_Report(m_Digital_Array);
    else
    {
      size_t i = n + 1;
      while (i--)
      {
        v(n - 1);
        unsigned char tmp = m_Digital_Array->at(n);
        for (size_t j = n; j > 0; --j)
          m_Digital_Array->at(j) = m_Digital_Array->at(j - 1);
        m_Digital_Array->at(0) = tmp;
      }
    }
  }
public:
  Permutation_nPn(
    const function<void(const shared_ptr<vector<unsigned char> > &)> 
    &Receive
  )
    :m_Report(Receive)
  {}
  void nPn(size_t n)
  {
    m_Digital_Array = shared_ptr<vector<unsigned char> >(
      new vector<unsigned char>(n));
    size_t i = n;
    while (i)
    {
      m_Digital_Array->at(i - 1) = i - 1;
      --i;
    }
    v(n - 1);
  }
};
int N = 1;
void Show(const shared_ptr<vector<unsigned char> > &Digital_Array)
{
  cout << N << ":\t";
  
  for (size_t i = Digital_Array->size(); i > 0; --i)
    cout << (int)Digital_Array->at(i - 1) << ' ';
  cout << endl;
  ++N;
}
int main()
{
  Permutation_nPn P(Show);  
  cout << "4! 排列:" << endl;
  N = 1;
  P.nPn(4);
  return 0;
}


2017年12月26日 星期二

靜態多型

相對於靜態多型就是一般較多使用的的動態多型,如:
class Base
{
public:
  virtual void f() = 0;
};
class Derived :public Base
{
  virtual void f() override
  {
  }
public:
};
若改為靜態多型可能會像以下這樣:
template<typename DERIVED>
class Base
{
public:
  void f()
  {
    static_cast<DERIVED*>(this)->f_Imp();
  }
};
class Derived :public Base<Derived>
{
  void f_Imp()
  {
  }
public:
  friend class Base<Derived>;
};

2017年1月7日 星期六

[轉傳]修改 subversion log 訊息

http://askalee.blogspot.tw/2006/11/subversion-log.html

在 Windows 系統下用 TortoiseSVN,到 TortoiseSVN repository 的 hooks 目錄中,新增或編輯一個名為 pre-revprop-change.bat 的檔案,內容改為

  exit 0

即可



2015年5月28日 星期四

如何取得最新版的 MinGW

首先要取得 MSYS2,再更新軟體倉庫,請參考下面兩個連結
http://sourceforge.net/p/msys2/wiki/MSYS2%20installation/
http://msys2.github.io/

為了預防以後失連,把重點摘錄於下:

2015年3月28日 星期六

排列組合產生器

整理來自 http://www.programmer-club.com.tw/ShowSameTitleN/c/46015.html 的討論,討論結果大致可分為遞迴法、計算法及量子演算法三種。但遞迴法有 stack overflow 的隱憂,所以改寫成模擬遞迴法;而計算法則因須要使用大數才能完整,所以加入了 goost 的 multiprecision;量子演算法要有量子電腦才能真正發揮實力,這裡使用 thread 去模擬,過這些做法象徵意義大於實質意義。

2013年5月16日 星期四

關於 OpenGL 和 D3D 的 major matrix

在許久以來的傳說...

OpenGL 採用如下的的矩陣運算,把它的矩陣稱作 colum matrices

     m11 m12 m13 m14  x
     m21 m22 m23 m24  y
     m31 m32 m33 m34  z
     m41 m42 m43 m44  1

而 D3D 採用如下的的矩陣運算,把它的矩陣稱作 row matrices
            m11 m12 m13 m14

       m21 m22 m23 m24
 x y z 1
       m31 m32 m33 m34

       m41 m42 m43 m44

但那是一個錯誤,那只能說是 "數學" 上的格式,實際上在程式記億體上的儲存方式如下...