顯示具有 C_and_Cpp 標籤的文章。 顯示所有文章
顯示具有 C_and_Cpp 標籤的文章。 顯示所有文章

C++單元測試(1) - 下載CppUnit

沒有留言:

找到CppUnit - C++ port of JUnit - SourceForge,還有維基百科條目介紹
雖然前者是Google第一個,照理來說,就是它了,但是如果是他,我也不用特地發文介紹這一段。

先看看SourceForge

如果直接按下載,可以發現

問題一

它下載下來的壓縮檔,裡面的檔案都加了副檔名.v(ex: abc.cpp.v, abc.h.v),如果你想要手動去除的話,實在不建議,因為裡面的檔案超多的。

問題二

Summy的Last Update是2013-04-22
在Files裡的1.12.1版卻是2008-02-20


再來看看維基百科的介紹

有提到 在freedesktop.org 維護的版本是由 Markus Mohrhard 在維護。

那....參考資料呢?



發現它有紀錄最新版是......1.13.2 release
還有這個維護者的部落格文章

提到對Visual Studio,以及Windows x64的支援,對我這種臣服於M$邪惡帝國的子民來說,真是一大福音呀。

事不疑遲,快到freedesktop下載最新版吧!

如果有git建議直接用clone的
git clone git://anongit.freedesktop.org/git/libreoffice/cppunit/

參考資料:

[1] CppUnit - C++ port of JUnit
[2] CppUnit - Wikipedia, the free encyclopedia
[3] Cppunit 1.13.2 released

建構子的初始化Exception

沒有留言:
開門見山,以這樣的類別為例:

class foo{
    int i;
    char c;
public:
    foo();  //建構子
};
一般來說,我們的建構子都這樣寫
foo::foo()
:i(0), c(''){  <-- 建構初始列
}
但是,如果想在建構子上加try-catch,難道是這樣??
foo::foo()
:i(0), c(''){  <-- 建構初始列
    try{
    }
    catch(...){
    }
}
發現了嗎?那捕捉個屁呀?跟本就是把擸物放在網子外。
唷!不!所謂江湖一點訣!
在Primer C++中就有介紹,如果要捕捉到建構初始列上,初始化成員變數時的exception時,就一定要這樣寫
foo::foo()
try:i(0), c(''){  <-- 建構初始列
    
}catch(...)
{    }
這個名稱叫「function try block」

看到這,會想知道解構子怎麼處理嗎?

解構子.....基本上,絕對不可以出現exception!!!!

C++之可怕,在於它可以反映人心

沒有留言:
標題很玄。XDD
之前參加社群,聽見一位前輩,他們開公司不使用C++

他說「看見新人履歷上寫著會使用C++,我真的懷疑是不是真的會使用C++?」

其實,當下我在底下聽見這句話,還真不服氣。可見我當年多年輕氣盛,哈哈~~
不過,經過兩次看見同事的code(兩間不同屬性的公司)之後,我發現前輩講的話雖然用平凡的字,但是卻暗藏著高深的智慧。

其實,C++的多重寫作風格,是一件好事,但是在實現上,好與不好,也要看個人造化。

所謂「把事情做對≠做對的事情」

說來說去到底在說什麼呀?
再不說重點,就要按上一頁了?!><

我們把C++的寫作風格列出來,便可以開始說明白。

  1. C++ without OO(類似C語言)
  2. C++ with OO(類似Java)
  3. C++ template
  4. C++ generial

看看前兩種,C語言與Java的風格差非常的多
如果這兩種風格都出現在同一個專案中,時而看見一堆物件在跑,時而看見一堆function互call。這種精彩有趣的情況,應該只有C++的code獨享了。

那種Other類別的成員函數,也許就跟山一樣多(沒看到的話就可能是那些不屬於任何類別global function),程式設計師在設計它們時,不用去思考它們歸誰,這是C++的容許,也是C++的放縱,重覆使用的程式碼成為了function被創造的理由,而程式的概念整體性,不是被拋在腦後,就是從來沒有在大腦中出現過。

為了避免這種情況,Java為此而生,規範了種種限制,而造就了物件導向的另一個高峰呀。
注重概念整體性的OO寫作風格,讓每一個fucntion都歸到它們所屬的類別,如果聽到有人說「就是有些function到哪都可以用,而且不屬於誰呀?」的時候,就是該程式設計師幸運使用Java而不是C++避免造就另一個泥巴程式碼出現在世上,不過也許這樣的規範也可以使用Other Class讓自己落入另一個沈淪的泥巴,不過比起C++,Other Class算是好的(至少有被圈出來)。

會使用other class的程式設計師,對於問題的了解程度還不夠深入,所以才會出現無法歸納或無法命名的問題。

不過OO也不是這麼神。

還是有新的泥巴產生,就是God Object,這在維基百科還有介紹呢!什麼叫God Object?什麼是God?用基督教的角度來說(畢竟這一個詞是一神論的西方人創的,就不好意思用東方的角度來解釋god object了),God就是全知全能,創造萬物的那位....,如果我們把它抽象化,不就是other class了嗎?如果所有的物件都不存在,把所有的member value和member fucntion都放在god object的類別中,那麼god objcet也相當符合其概念呀(笑~)


Java為了阻止凡人幹蠢事,寫個程式卻把自己搞死了。就像是發展個科技卻用污染把自己毒死了一樣。只好加了種種的限制,強制要求coding style一定要OO。

而C++呢?

只能夠靠著程式設計師自我規範與自律,寫作的同時不斷的自省,是不是這樣寫是好的?
如果C++的程式設計師自得意滿的以為自己寫的程式碼超棒,大家都要跟,那麼可以看看程式碼便知道這個人的習慣與想法是怎麼回事了。(這麼神?)

quality正好和quick and dirty背道而馳。

所以下次有人讚美你寫程式很快時,記住!這只是讚美一半。
另一半也許就是對程式碼品質上的保留(不批評,但也不讚美)

關於物件的「==」運算子與提昇UX。

沒有留言:
這不是要教你怎麼覆寫==運算子,讓物件的==得到適當的定義。
而是要教你,如何告訴使用者,哪一個沒有比對結果。

示範準備程式碼
#include <vector>
#include <iterator>
#include <iostream>

class tObj
{
    int m_condition[3];
public:
    void setCondition(const int& Value1, const int& Value2, const int& Value3)
    {
        m_condition[0] = Value1;
        m_condition[1] = Value2;
        m_condition[2] = Value3;
    }
    const int getCondition(int index) const
    {
        return m_condition[index];
    }
    bool operator==(const tObj& obj) const
    {
        if ( (m_condition[0] == obj.m_condition[0]) && 
             (m_condition[1] == obj.m_condition[1]) && 
             (m_condition[2] == obj.m_condition[2]) )
            return true;
        else
            return false;
    }
};

void InitDB(tObj* o)
{
    (o+0)->setCondition(4, 6, 8);
    (o+1)->setCondition(2, 6, 6);
    (o+2)->setCondition(2, 6, 6);
    (o+3)->setCondition(2, 6, 8);
    (o+4)->setCondition(2, 4, 8);
    (o+5)->setCondition(2, 4, 8);
    (o+6)->setCondition(2, 4, 8);
    (o+7)->setCondition(2, 4, 8);
    (o+8)->setCondition(2, 4, 8);
    (o+9)->setCondition(2, 4, 8);
}

void DBtoVector(tObj* o, std::vector<tObj>& vo)
{
    for (int i = 0; i < 10; ++i)
        vo.push_back(*(o+i));
}

void displayMatch(std::vector<tObj> const& matchSample)
{
    for (std::vector<tObj>::const_iterator ims  = matchSample.begin();
                                           ims != matchSample.end(); ++ims)
        std::cout << ims->getCondition(0) << ", " 
                  << ims->getCondition(1) << ", " 
                  << ims->getCondition(2) << ", " << std::endl;
}

void isMatch(const tObj& x, std::vector<tObj>& vo)
{
    std::vector<tObj> matchSample;
    for (std::vector<tObj>::iterator it = vo.begin(); it != vo.end(); ++it)
        if (*it == x)  matchSample.push_back(*it);
    vo.clear();
    vo = matchSample;
}

int main(int argc, char const *argv[])
{
    tObj o[10];           InitDB(o);
    std::vector<tObj> vo; DBtoVector(o, vo);
    tObj x;               x.setCondition(2, 4, 8);  //sample

    isMatch(x, vo);    
    displayMatch(vo);

    return 0;
}

一開始,C++的書都會教我們,比對資料這件事覆寫operator==()然後,用vector + iterator + for就可以找出來想要的了!。
但是,為了使用者!你必須告訴他,如果比對資料輸入錯誤,那麼,又該怎麼寫,才可以告訴使用者「你的第幾個值寫錯了」呢?

第一件事,就是刪掉operator==()先。真的!

新增這一段程式碼
const bool partsMatch(const int& index, std::vector<tObj>& vo, const tObj& x)
{
    std::vector<tObj> matchSample;
    for (std::vector<tObj>::iterator it = vo.begin(); it != vo.end(); ++it)
        if (it->getCondition(index) == x.getCondition(index))
            matchSample.push_back(*it);

    vo.clear();
    vo = matchSample;
    return (matchSample.size()) ? true : false;
}
修改這一段程式碼,將回傳值改成字串
std::string isMatch(const tObj& x, std::vector<tObj>& vo)
{
    if (!partsMatch(0, vo, x))
        return "條件1 無符合項目";
    else if (!partsMatch(1, vo, x))
        return "條件2 無符合項目";
    else if (!partsMatch(2, vo, x))
        return "條件3 無符合項目";
    else
        return "完全符合";
}
主程式修改一下
int main(int argc, char const *argv[])
{
    tObj o[10];           InitDB(o);
    std::vector<tObj> vo; DBtoVector(o, vo);
    tObj x;               x.setCondition(2, 6, 1);  //sample

    std::cout << isMatch(x, vo) << std::endl;
    displayMatch(vo);

    return 0;
}
最後變成這樣(全部的程式碼)
#include <vector>
#include <iterator>
#include <iostream>
#include <string>

class tObj
{
    int m_condition[3];
public:
    void setCondition(const int& Value1, const int& Value2, const int& Value3)
    {
        m_condition[0] = Value1;
        m_condition[1] = Value2;
        m_condition[2] = Value3;
    }
    const int getCondition(int index) const
    {
        return m_condition[index];
    }
};

void InitDB(tObj* o)
{
    (o+0)->setCondition(4, 6, 8);
    (o+1)->setCondition(2, 6, 6);
    (o+2)->setCondition(2, 6, 6);
    (o+3)->setCondition(2, 6, 8);
    (o+4)->setCondition(2, 4, 8);
    (o+5)->setCondition(2, 4, 8);
    (o+6)->setCondition(2, 4, 8);
    (o+7)->setCondition(2, 4, 8);
    (o+8)->setCondition(2, 4, 8);
    (o+9)->setCondition(2, 4, 8);
}

void DBtoVector(tObj* o, std::vector<tObj>& vo)
{
    for (int i = 0; i < 10; ++i)
        vo.push_back(*(o+i));
}

void displayMatch(std::vector<tObj> const& matchSample)
{
    for (std::vector<tObj>::const_iterator ims  = matchSample.begin();
                                           ims != matchSample.end(); ++ims)
        std::cout << ims->getCondition(0) << ", " 
                  << ims->getCondition(1) << ", " 
                  << ims->getCondition(2) << ", " << std::endl;
}

const bool partsMatch(const int& index, std::vector<tObj>& vo, const tObj& x)
{
    std::vector<tObj> matchSample;
    for (std::vector<tObj>::iterator it = vo.begin(); it != vo.end(); ++it)
        if (it->getCondition(index) == x.getCondition(index))
            matchSample.push_back(*it);

    vo.clear();
    vo = matchSample;
    return (matchSample.size()) ? true : false;
}

std::string isMatch(const tObj& x, std::vector<tObj>& vo)
{
    if (!partsMatch(0, vo, x))
        return "條件1 無符合項目";
    else if (!partsMatch(1, vo, x))
        return "條件2 無符合項目";
    else if (!partsMatch(2, vo, x))
        return "條件3 無符合項目";
    else
        return "完全符合";
}

int main(int argc, char const *argv[])
{
    tObj o[10];           InitDB(o);
    std::vector<tObj> vo; DBtoVector(o, vo);
    tObj x;               x.setCondition(2, 6, 1);  //sample

    std::cout << isMatch(x, vo) << std::endl;
    displayMatch(vo);

    return 0;
}
也許不是完全美的做法,但是,還不賴。

function template裡使用vector和iterator

沒有留言:
一開始的程式碼是這樣
void Add(std::vector<double> _V)
{
    for (std::vector<double>::iterator _I = _V.begin(); _I != _V.end(); ++_I)
        add(*_I);
}
void Add(std::vector<CString> _V)
{
    for (std::vector<CString>::iterator _I = _V.begin(); _I != _V.end(); ++_I)
        add(*_I);
}
就想使用template將它們兩個合併成一組程式碼
template<class T> 
void Add(std::vector<T> _V)
{
    for (std::vector<T>::iterator _I = _V.begin(); _I != _V.end(); ++_I)
        add(*_I);
}
如果你也覺得這樣的程式碼沒問題,就值得繼續往下看,因為他complier一萬年也不會過!!


在Google「function template vector」之後,終於有結果了。[1]
template<typename T, typename A>
void some_func( std::vector<T,A> const& vec ) {}
但是還是不行!怎麼會這樣?!
這時,就讓我想起一句話

「M$不符合標準,因為他當自己就是標準」

所以,我就將程式碼改成這樣(測試平台: VC6)
template<class T> 
void Add(std::vector<T,std::allocator<T> > const & _V)
{
    for (std::vector<T>::iterator _I = _V.begin(); _I != _V.end(); ++_I)
        add(*_I);
}
就可以了!(哭哭)

但是,標準要怎麼寫呢?
我就使用MiniGW + Sublime text 2來測試一下
果然VC6的寫法不適合,那要怎麼改呢?

再Google「function template vector iterator」了一陣子,終於有結果了。[2]

改成下面這樣,就可以了!
#include <vector>
#include <iterator>
#include <string>
#include <iostream>

class Display
{
public:
    template < typename T, typename A >
    void Show( std::vector<T,A> const& vec )
    { 
        typename std::vector<T>::const_iterator it;
        for (it = vec.begin(); it != vec.end(); ++it)
            std::cout << *it << std::endl;
    }
};

int main()
{
    std::vector<double> vD;
    vD.push_back(2.4);
    vD.push_back(2.1);
    vD.push_back(2.2);
    vD.push_back(2.3);

    std::vector<std::string> vS;
    vS.push_back("這是");
    vS.push_back("這是..");
    vS.push_back("這是...");
    vS.push_back("這是....");
    vS.push_back("...");


    Display A;
    A.Show(vD);

    Display B;
    B.Show(vS);
}
程式執行結果
2.4
2.1
2.2
2.3
這是
這是..
這是...
這是....
...

最後的最後一件事提醒,function template的定義(不是宣告唷,是定義)請寫在.h檔[3]或者使用inline

參考資料:
[1] c++ - std::vector as a template function argument - Stack Overflow
[2] c++ - Question about vector iterator in template functions - Stack Overflow
[3] fatal error LNK1120: 2 unresolved externals

c++的interface

沒有留言:
最近和朋友一起看Design Pattern的書,選定的書本,是使用C#來實作。
而C#又是一種學java的語言,有interface這種C++沒有的東西。
心中浮現了一個問題,在C++中,要怎麼表達,才會最最最最貼切interface呢??
不知道有在使用C++的朋友怎麼做呢?

在此,我介紹一下我自己的想法。

先來看看一個例子(c#)
interface ICloneable
{
    Object^ Clone();
}
有幾個使用interface上的規則要注意:
  1. 要被繼承,不可以自己成為物件
  2. 繼承後要實作interface裡的function
  3. function權限預設公開
常見的C++實作,都是使用像下面這樣的做法滿足[1]
class ICloneable
{
public:
    Object* Clone() = 0;
}
利用純虛擬的特性,強迫「被繼承」以及「衍生類別必實作其function」。
但是,使用C#與java的朋友知道,虛擬類別與interface的差別在於

interface就是預計被繼承的member function介面集合(繼承介面的衍生類別,一定要實作該介面的member function。)interface沒有member var。

嗯~~回過頭看看C++的實作,似乎滿足上面的樣子,但是總是無法區分純虛擬與interface,那怎麼辦呢?

再回去看看上面interface的規則要注意的三點,其第三點,我們尚未滿足。

看到這,你可能會問「怎麼會?我們有加 public: 呀!不就公開其權限了??」

嘖嘖嘖,會這樣反駁者,一定沒有仔細看描述

   3. function權限預設公開

看到這,心裡應該有底了吧?
我們來實作看看,什麼叫做預設公開的....interface
struct ICloneable
{
    Object* Clone() = 0;
}
發現了嗎?我們利用了struct的特性,讓它裡面只裝虛擬函式。這樣就和純虛擬類別區分開來了,並且預設公開。一般struct的用法是不放function,但是事實上,用法和class一模一樣,並沒有太多限制,所以可以這樣使用達到既與一般的struct不同,也和純虛擬函數不同,來達到interface的作用。

最後,如果真的要實實在在的實作出一模一樣的程式,也不是不可能的,最後一個例子,就給程式碼語法狂熱愛好者看看,這樣做就可以滿足程式碼的美感與力度。
typedef struct interface
interface ICloneable
{
    Object* Clone() = 0;
}

追求程式碼表現的美,還真的需要一點狂熱!哈哈~~

參考資料:
[1] [C++][筆記]介面實作

vector去除重覆混合技

沒有留言:

去除自身重覆的元素。

void removeRepeatMember()
{
    vector<CTest> member;

    /*  member.push_back(lots of data)  */

    std::sort(result.begin(), result.end());
    result.erase(std::unique(result.begin(), result.end()), result.end());
}

去除外來指定元素

void removeMember(const CTest& objTest)
{
    result.erase(remove(result.begin(), result.end(), objTest), result.end());
}
上例的vector是裝string,如果是裝自訂的類別CTest,則需要重載運算子。
sort()需要重載<運算子。
unique()需要重載==運算子。
class CTest
{
public:
    bool operator< (const CTest&     oCompany ) const;
    bool operator==(const CTest& oCompany ) const;
}

參考:
STL—vector删除重复元素
std::remove - c++ Reference

c++讀寫.txt檔(以每行為單位)

沒有留言:
初衷:

建立一個可以讀寫.txt檔的零件。
需求:
以每一行'\n'為單位,把vector<std::string>丟進去就可以得到文件文容。
可以讀取任意大小(至少是很大的)文件。
原始碼放在Github,以BSD LICENSE
kxTxtFile.h
#ifndef TXTFILE_H
#define TXTFILE_H
#include <vector>
#include <string>
#include <fstream>

class kxTxtFile
{
    std::fstream ftxt_Std;
    std::vector dtxt_Txt;

public:
    bool Open(const char*);
    bool Save(const char*);

    void Close(){ ftxt_Std.close(); };

    void iTxtData(std::vector& data){ dtxt_Txt = data; mem2file(); };
    void oTxtData(std::vector& data){ file2mem(); data = dtxt_Txt; };
    std::vector oTxtData(){ file2mem(); return dtxt_Txt; };

private:
    void file2mem();
    void mem2file();
};
#endif
kxTxtFile.cpp
#include "kxTxtFile.h"

bool kxTxtFile::Open(const char* path)
{
    ftxt_Std.open (path, std::ifstream::in);
    return ftxt_Std.good();
}

bool kxTxtFile::Save(const char* path)
{
    ftxt_Std.open (path, std::ifstream::out | std::ifstream::trunc);
    return ftxt_Std.good();
}

void kxTxtFile::file2mem()
{
    dtxt_Txt.clear();
    std::string str;

    while (getline(ftxt_Std , str))
        dtxt_Txt.push_back(str);
}

void kxTxtFile::mem2file()
{
    if (!dtxt_Txt.empty())
    {
        for (std::vector::iterator it = dtxt_Txt.begin(); it != dtxt_Txt.end(); ++it)
        {   
            *it += '\n';
            ftxt_Std.write(it->c_str(), it->length());
        }
    }
}
主程式的使用情況
#include <iostream>
#include <fstream>
#include <vector>
#include "kxTxtFile.h"

using namespace std;

int main()
{
    kxTxtFile ifile;

    if (!ifile.Open("readFilePath"))
        std::cout << "read error" << std::endl;

    std::vector vstr;
    ifile.oTxtData(vstr);
    ifile.Close();

    for (std::vector::iterator it = vstr.begin(); it != vstr.end(); ++it)
        std::cout << *it << std::endl;  

    kxTxtFile ofile;

    if (!ofile.Save("saveFilePath"))
        std::cout << "save error" << std::endl;
    
    ofile.iTxtData(vstr);

    ofile.Close();
    return 0;
}

printf vs cout

沒有留言:
這篇文章所有的程式碼,都是使用Sublime Text 2 + minGW的g++

#include <iostream>
#include <iomanip>
#include <string>
#include <cstdio>

using namespace std;

int main()
{
    /*sample code*/
    return 0;
}

保留顯示空間,向右對齊

printf("%3d", 10);
cout.width(3);
cout << 10;
cout << setw(3) << 10;

空白填入的字元

(不行填入字串)
cout.width(3);
cout.fill('@');
cout << 10;
cout << setw(3) << setfill('@') << 10;

8/10/16進制

printf("%d\n", 10);
printf("%x\n", 10);
printf("%o\n", 10);
cout << dec << 10 << endl;
cout << hex << 10 << endl;
cout << oct << 10 << endl;

設定小數點格式輸出

printf("%2.2f\n", pi);

小數點顯示設定位數

有這一個就變成不含小數點,沒有的話就要含小數點
cout.setf(ios::fixed, ios::floatfield);
cout.setf(ios::fixed, ios::floatfield);  //加了這一行precision()定義就變成小數點(不含)後數2位
cout.precision(2); //小數點(含)後數2位(原始定義變成無效)
cout.width(5);  //2+1+2 小數點前2位+小數點+小數點後2位
cout << pi << endl;
cout.setf(ios::fixed, ios::floatfield);  //加了這一行precision()定義就變成小數點(不含)後數2位
cout << setw(5) << setprecision(2) << pi << endl; //保留顯示總寬度至少5個字元,小數點(含)後2位
恢復預設的小數點顯示設定
cout.unsetf (ios::floatfield); 

科學記號格式輸出

預設寬度

printf("%e\n", pi);
cout.setf(ios::scientific, ios::floatfield);
cout << pi << endl;

保留寬度

printf("%2.2e\n", pi);
cout.setf(ios::scientific, ios::floatfield);
cout << setw(5) << setprecision(2) << pi << endl;
cout.setf(ios::scientific, ios::floatfield);
cout.precision(2); //設定小數位數2位
cout.width(5);
cout << pi << endl;


參考資料:
[PPT]C/C++ch4
C Gossip: printf() 與 scanf()

寫給C++程式設計師的UML實務手冊//讀書心得

沒有留言:

此篇文章是我讀《UML for C++ programmer》的讀書心得,透過書裡的範例,重新整理而成的一篇文章。


本文目錄

  • 類別圖
    系統內部的靜態結構
  • 循序圖
    實作,物件外部的互動行為
  • 案例圖
    系統的外部行為
  • 狀態圖
    物件內部變化

隱藏.cpp裡一切細節的範例程式

沒有留言:
在C++中,分離類別實作和類別介面的做法有幾個優點:

  1. 編譯時可以減少因為修改而牽動的檔案數量,大幅降低檔案重新編譯的規模(Effective C++ 2nd #37, 3rd #31)
  2. 在提供別人編譯所需要的檔案時,可以成功讓人編譯,又不會導致自己的Source Code被看光,而破壞類別的封裝性,或被修改程式碼,破壞了類別的整體概念性。

基於以上兩點優點,一定要學下這一招。
去翻了一下Effective C++ 2rd #37,以下是以它的程式碼為基礎,所做的練習。

虛擬函數+動態連結

沒有留言:
此做法在VC6中會有 ERROR C2555,不過我有解決方案,有興趣的人可以參考。
#include <iostream>

using namespace std;

class A
{
public:
 virtual A* fun1() = 0;
 virtual A* fun2() = 0;
};

class B : public A
{
public:
 B* fun1() { cout << "B::fun1()" << endl; return this; }
 B* fun2() { cout << "B::fun2()" << endl; return this; }
};

class C : public A
{
public:
 C* fun1() { cout << "C::fun1()" << endl; return this ; }
 C* fun2() { cout << "C::fun2()" << endl; return this ; }
};

int main()
{
B b1;
C c1;

A* a = &b1;
a->fun1()->fun2();

a = &c1;
a->fun1()->fun2();
}

消失在記憶中的code

沒有留言:
KillProcess("EXCEL")


Public Sub KillProcess(ByVal Str_ProcessName As String)
Dim myProcesses() As Process = Process.GetProcesses
Dim procName As String = Str_ProcessName
Dim myProcess As Process
For Each myProcess In myProcesses
If (myProcess.ProcessName.ToLower = procName.ToLower) Then
myProcess.Kill()
End If
Next
End Sub

How to return reference

沒有留言:
Cartridge At(int i) const;

Cartridge CDataChain::At(int i) const
{
        return m_CarChain1.at(0);
}
               ↓變成這樣寫
Cartridge& At(int i);

Cartridge& CDataChain::At(int i)
{
        return m_CarChain1.at(0);
}

刪除vector重複元素

沒有留言:

突然找不到這個,還查了一下書。
C++ Primer 3/e p.1193

然後自己keyin了一個簡單的程式
成功。

執行結果:

開始了
0, 1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 6, 7, 7, 7, 8, 8, 9,
0, 1, 2, 4, 5, 6, 7, 8, 9, 4, 5, 5, 5, 6, 7, 7, 7, 8, 8, 9,
0, 1, 2, 4, 5, 6, 7, 8, 9,
結束了
Press any key to continue


程式碼:

#include <iostream>
#include <vector>
#include <algorithm>

void show(std::vector<int>& vch)
{
    for (std::vector<int>::iterator it = vch.begin(); it != vch.end(); ++it)
        std::cout << *it << ", ";
    std::cout << std::endl;
}

int main()
{
    std::cout << "開始了" << std::endl;
    std::vector<int> vch;
    std::vector<int>::iterator eraseit;
 

    for (int i = 0; i<20; ++i)
    {
        //std::cout << i << std::endl;
        vch.push_back(rand()%10);
    }
    std::sort(vch.begin(), vch.end());  //排序
    show(vch);
    eraseit = std::unique(vch.begin(), vch.end());  //排不重覆元素
    show(vch);
    vch.erase(eraseit, vch.end()); //沒被排到的刪掉
    show(vch);

    std::cout << "結束了" << std::endl;
    return 0;
}

CDC活用術

沒有留言:
因為,View想要做得複雜又好維護,用起來像網頁語法一樣順暢
就這樣想

最後設計出來的code如下
void CColorEyeIView::OnDraw(CDC* pDC)
{
    CColorEyeIDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    //表格的部份
    //設計一個table class用類似HTML的語法來管理表格

    //視窗左半邊,導覽區
    CPoint ptTemp = ptFix;

    CTable tbInfo(pDC, ptTemp);
        ptTemp = tbInfo.SetCellNum(2, 4).SetTableBoard(0).SetGridBoard(0).SetFont(afont).SetCellSpace(1)
         .Width(0, TextHight*10).Width(1, TextHight*12).Hight(0, 16).Hight(1, 16).Hight(2, 16)//.Hight(3, 16)
                 .tr().td().b().text("Panel ID").b_().td_()          .td().text(pDoc->GetOmdFile().GetPnlID()).td_().tr_()
                 .tr().td().b().text("Measurement device").b_().td_().td().text(pDoc->GetOmdFile().GetMsrDvc()).td_().tr_()
                 .tr().td().b().text("Probe").b_().td_()             .td().text(pDoc->GetOmdFile().GetPrb()).td_().tr_()
                 .tr().td().b().text("Chanel").b_().td_()            .td().text(pDoc->GetOmdFile().GetCHID()).td_().tr_()
            .table_();
...
}


(重載)多載運算子

沒有留言:
因為上網查太多次了,每次又查到想翻書算了,翻書翻到覺得書寫得太多了。
所以乾脆自己來寫一篇簡單小筆記

operator系列

物件導向之回傳this

沒有留言:
最近在ptt上看見討論串
而且討論得還滿有結果的

之前也為了這件事查半天(突然忘記怎麼用了XD)
就來給自己做一個小筆記吧!

某一個演算法

沒有留言:


Suppose that a matrix m[ ][ ] is stored in a linear array a[ ] with the following sequence:
0 1 5 6 14 ···
2 4 7 13 ···
3 8 12 ···
9 11 ···
10 ···
Please give the mapping function from m[i][ j] to a[k]. Note that the upper left corner of m is the
first element m[0][0], the first element of a is a[0], m[0][1] = 1 and m[0][2] = 5. (8%)

Sol)


.RAW的Smooth

沒有留言:
#include <iostream>
#include <fstream>

using namespace std;

#define frameH 1920
#define frameV 1080

int main()

{
    unsigned char *fp = new unsigned char [frameH*frameV];

    fstream file;
    file.open("W:\a.raw", fstream::in | fstream::binary);
    if( !file.good())
        cout << "file讀檔失敗" << endl;

    file.read((char*) fp, frameH*frameV);    //轉態unsigned char* 轉態成 char* 放入函式
    file.close();

    int *ifp = new  int [frameH*frameV];

    for(int i = 0 ; i < frameH ; ++i){
    for(int j = 0 ; j < frameV ; ++j){
            *(ifp+i+j*frameH) = *(fp+i+j*frameH);
    }}

    int temp;

    for(int i = 1 ; i < frameH-1 ; ++i){
    for(int j = 1 ; j < frameV-1 ; ++j){
        temp =
            *(ifp + (i-1) + (j-1)* frameH) +
            *(ifp +  i    + (j-1)* frameH) +
            *(ifp + (i+1) + (j-1)* frameH) +
            *(ifp + (i-1) +  j   * frameH) +
            *(ifp +  i    +  j   * frameH) +
            *(ifp + (i+1) +  j   * frameH) +
            *(ifp + (i-1) + (j+1)* frameH) +
            *(ifp +  i    + (j+1)* frameH) +
            *(ifp + (i+1) + (j+1)* frameH);

        *(ifp+i+j*frameH) = (temp /9);
    }}

    for(int i = 0 ; i < frameH ; ++i){
    for(int j = 0 ; j < frameV ; ++j){
        *(fp+i+j*frameH) = *(ifp+i+j*frameH);
    }}

    fstream ofile;
    ofile.open("W:\ba.raw", fstream::out | fstream::binary);
    if( !ofile.good())
        cout << "ofile讀檔失敗" << endl;

    ofile.write((char*) fp, frameH*frameV);  //轉態unsigned char* 轉態成 char* 放入函式
    ofile.close();

    delete [] fp;
    delete [] ifp;
    system("PAUSE");
    return 0;
}