最近Google又推出一項新服務 - Google App Engine
主旨是讓大家可以在Google上建立一個網頁伺服器的服務網站,不過提供的語法不是一般熟悉的PHP、ASP、JSP…等等。而是新時代語言:Python!
還提供資料庫可以使用,但是也不是一般人熟悉的MySQL,而是Google自己開發的新型態資料庫GQL - DataStore,這個資料庫不同於以往的關聯式資料庫,而是用到了Google引以自豪的BitTable的技術,不像複雜的關聯式資料庫為了符合第x正規化,而產生一個以上的Table,在這個DataStore裡,完全不怕你的Table太大,因此你可以將資料全部寫入同一個Table處理,我想這是一個對資料庫全新的詮釋,新接觸者可能要花一段時間了解才行。....不過這個免費的服務在撈資料時,有限制一次最多只能撈出1000筆data。
除此之外還有提供一些Google其他的API,包括GMail、Google Account、Picasa…等等的服務可以使用。
我已經開始看了一些文件、API,改寫了一下我的MoneyDog,目前看來,要弄起這個網站應該是沒啥太大的問題。之後有空再慢慢把心得貼上來。
26 6月 2008
16 5月 2008
Windows上建構wxWidgets的編譯環境
如何在Windows上,建構wxWidgets的編譯環境呢?由於wxWidgets只是個Library,所以必須要安裝其他的IDE+Compiler才能寫出wxWidgets的程式,或者也是可以直接用文字編輯器寫code,然後在Comand Line底下compile也是可以(如果你夠勤勞的話...)。否則,裝一個IDE決對是一個事半功倍的事情。
wxWidgets是跨平台的Library,所以我就決定找一個優秀的跨平台IDE:Code::Blocks。這樣在任何平台都可以用熟悉的環境寫wxWidgets的程式,多麼令人蘇胡的一件事啊~ 話不多說,馬上裝來用用看!
wxWidgets是跨平台的Library,所以我就決定找一個優秀的跨平台IDE:Code::Blocks。這樣在任何平台都可以用熟悉的環境寫wxWidgets的程式,多麼令人蘇胡的一件事啊~ 話不多說,馬上裝來用用看!
11 5月 2008
wxWidgets簡介
最近有點無聊,想說找找跨平台的Language來玩看看,找了一些資料,也拜讀了PCMan大大的文章(Qt, Gtk+, wxWidgets的比較),感覺wxWidgets在跨平台的表現上很猛的樣子,除了可以在不同的平台上重新編譯外,還可以結合不同的Compiler得到該平台上最佳化的結果(Ex: Windows上可用Visual C++、Borland C++ Builder compile)。
由於wxWidgets它底層的部分在不同的平台上是重新寫過的,所以跨平台的表現就比其他的Language來得強,也不像Java需要利用JVM來執行(馬的JVM...愈來愈肥)。但是也由於這個因素,在wxWidgets中,並非所有的元件都是跨平台的,有些元件只允許在某平台上才可執行(詳見此)。
而wxWidgets的中文資料真是有點少得可憐…Google一下wxWidgets,繁體中文的結果竟然不到7000個=_=,看來在台灣真的是不太流行。
● wxWidgets簡介
首先要先了解wxWidgets的定位是什麼,wxWidgets是一個Open Source的C++ GUI Library,所以你可以選擇自己喜歡的開發平台、及該平台上的IDE compiler撰寫wxWidgets的程式。
如果你不想用C++也沒關係,wxWidgets也提供其他binding wxWidgets的Language,比如Python(wxPython)、Perl(wxPerl)、Java(wx4j)…等等的Language來撰寫。
● wxWidgets支援的平台與相對應的wx Library:
由於wxWidgets只是個GUI的Library,所以必須透過其他的IDE來撰寫程式,GUI Library最被迫切需要的就是用快速拖拉的方式(RAD),拉出使用者所見的圖形介面。雖然說直接在文字介面下coding也是可以,但是透過所見即所得的拖拉方式,總是比較輕鬆比較直觀。
● wxWidgets的RAD工具( Rapid Application Development )
● wxWidgets支援各平台上,在相對應IDE上compile :
● 這邊提供一些wxWidgets的連結參考:
由於wxWidgets它底層的部分在不同的平台上是重新寫過的,所以跨平台的表現就比其他的Language來得強,也不像Java需要利用JVM來執行(馬的JVM...愈來愈肥)。但是也由於這個因素,在wxWidgets中,並非所有的元件都是跨平台的,有些元件只允許在某平台上才可執行(詳見此)。
而wxWidgets的中文資料真是有點少得可憐…Google一下wxWidgets,繁體中文的結果竟然不到7000個=_=,看來在台灣真的是不太流行。
● wxWidgets簡介
首先要先了解wxWidgets的定位是什麼,wxWidgets是一個Open Source的C++ GUI Library,所以你可以選擇自己喜歡的開發平台、及該平台上的IDE compiler撰寫wxWidgets的程式。
如果你不想用C++也沒關係,wxWidgets也提供其他binding wxWidgets的Language,比如Python(wxPython)、Perl(wxPerl)、Java(wx4j)…等等的Language來撰寫。
● wxWidgets支援的平台與相對應的wx Library:
- Windows : wxMSW
- Linux : wxGTK
- Mac : wxMac
由於wxWidgets只是個GUI的Library,所以必須透過其他的IDE來撰寫程式,GUI Library最被迫切需要的就是用快速拖拉的方式(RAD),拉出使用者所見的圖形介面。雖然說直接在文字介面下coding也是可以,但是透過所見即所得的拖拉方式,總是比較輕鬆比較直觀。
● wxWidgets的RAD工具( Rapid Application Development )
- wxFormBuilder : 免費,跨平台,但是只提供拖拉視窗並產生code,並不提供compile環境(純RAD),而且目前尚未提供將元件拖拉到Form上任何一點的位置,一定要擺在Layout(wxSizer)裡面才行
- wxSmith : Code::Blocks內建的wxWidgets RAD工具,使用結果覺得不是挺穩定的
- wxDev-C++ : 以Delphi開發的免費軟體,只能在Windows上執行,RAD+IDE
- wxGlade : 以wxPython撰寫而成,RAD+IDE
- 其他...
● wxWidgets支援各平台上,在相對應IDE上compile :
- Cross-platform :
- Code::Blocks
- Eclipse
- Windows :
- Visual C++
- Borland C++ Builder
- Dev-C++
- Linux :
- Anjuta
- KDevelop
- Mac :
- Xcode
● 這邊提供一些wxWidgets的連結參考:
09 5月 2008
[Linux] 基本的Timer介紹
Linux提供了兩種基本的Timer機制可以使用:
● alarm
Return value : 返回上一次呼叫alarm的剩餘秒數。若未設定alarm,則返回0。
Example : 第一次等待1秒後觸發Timer,之後每隔2秒觸發一次。
--------------------------------------------------------------------------------------
● setitimer
setitimer由第二個參數value設定觸發的時間。第三個參數ovalue用來取得上一次 setitimer設定的itimerval值(此參數可以為NULL)。值得注意的是,根據itimerval裡變數的意義,當it_interval設定為0時,Timer只會觸發一次。而it_value設定為0時,代表Timer結束。
Return value : 如果成功則return 0,失敗則return -1。
Example : 第一次等待1秒後觸發Timer,之後每隔2秒觸發一次。
● 根據以上,可知Linux內建的Timer還是有點簡陋,而且setitimer同一時間只能處理3個Timer,如果應用程式需要多個Timer的話,這個Linux內建的Timer可能就不敷需求了!
- alarm
- setitimer
● alarm
#include <unistd.h>這是一個簡單的設定Timer介面。當呼叫了alarm( n )後,等待n秒後,就會觸發一次的SIGALRM的signal,所以必須要在呼叫alarm前,先設好SIGALRM的handler function才行。而當乎呼alarm(0)時,則表示停止當前的timer處理,不要發出SIGALRM的signal。
unsigned int alarm(unsigned int seconds);
Return value : 返回上一次呼叫alarm的剩餘秒數。若未設定alarm,則返回0。
Example : 第一次等待1秒後觸發Timer,之後每隔2秒觸發一次。
#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;
void my_alarm_handler(int a)
{
cerr<<"my_alarm_handler"<<endl;
alarm(2);//重新設定
}
int main()
{
signal( SIGALRM, my_alarm_handler );
alarm(1);
while(1){}
return 0;
}
--------------------------------------------------------------------------------------
● setitimer
#include <sys/time.h>setitimer與getitimer提供了三種類別的Timer使用:
#define ITIMER_REAL 0
#define ITIMER_VIRTUAL 1
#define ITIMER_PROF 2
int getitimer(int which, struct itimerval *value);
int setitimer(int which, const struct itimerval *value,
struct itimerval *ovalue);
- ITIMER_REAL : 以系統真實的時間來計算,觸發時會送出SIGALRM。
- ITIMER_VIRTUAL : 只計算process真正在執行的時間(在User Mode的處理),觸發時會送出SIGVTALRM。
- ITIMER_PROF : 計算該process在User Mode與Kernel Mode的處理時間,觸發時送出SIGPROF。
struct itimerval {
struct timeval it_interval; /* next value : 下一次觸發所需的時間*/
struct timeval it_value; /* current value : 目前距離觸發時間點 剩餘的時間*/
};
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};setitimer由第二個參數value設定觸發的時間。第三個參數ovalue用來取得上一次 setitimer設定的itimerval值(此參數可以為NULL)。值得注意的是,根據itimerval裡變數的意義,當it_interval設定為0時,Timer只會觸發一次。而it_value設定為0時,代表Timer結束。
Return value : 如果成功則return 0,失敗則return -1。
Example : 第一次等待1秒後觸發Timer,之後每隔2秒觸發一次。
#include <iostream>
#include <sys/time.h>
#include <signal.h>
using namespace std;
void my_alarm_handler(int a)
{
cerr<<"test "<<endl;
}
int main(){
struct itimerval t;
t.it_interval.tv_usec = 0;
t.it_interval.tv_sec = 2;
t.it_value.tv_usec = 0;
t.it_value.tv_sec = 1;
if( setitimer( ITIMER_REAL, &t, NULL) < 0 ){
cerr<<"settimer error."<<endl;
return -1;
}
signal( SIGALRM, my_alarm_handler );
while(1){
sleep(2);
}
return 0;
}
● 根據以上,可知Linux內建的Timer還是有點簡陋,而且setitimer同一時間只能處理3個Timer,如果應用程式需要多個Timer的話,這個Linux內建的Timer可能就不敷需求了!
18 4月 2008
[BCB] 升級indy9的元件後 compile後link產生的問題
在程式compile後 會有Error出現:
[Linker Fatal Error] Fatal: Unable to open file 'INDY.BPI'
因為安裝了INDY9.0元件以後,indy.bpi變成了indy60.bpi
兩種方法可以解決:
[Linker Fatal Error] Fatal: Unable to open file 'INDY.BPI'
因為安裝了INDY9.0元件以後,indy.bpi變成了indy60.bpi
兩種方法可以解決:
- 修改預設值,改一遍即可
Project->Option->Packages裡面的Runtime packages,找到indy刪除就可以了(左下角的Default要打勾) - 如果之前已經存在的專案
可用文字編輯器打開*.bpr,搜尋裡面出現的indy.bpi,將它刪除即可
28 2月 2008
Skype4Com in BCB 的一些範例
Skype4Com在BCB上的應用,其實官網上的資料給的並不多,只是有Delphi的範例可以看一下(註:我不會寫Delphi啊~~~~~XD) 還好在論壇上找到一些些的資料,然後再靠自己的一些摸索後,終於抓到一些訣竅了。以下是一個簡單測試一些Skype4Com的Code,有興趣的可以試試看。
比較需要注意的是,由於Skype4Com下載下來的壓縮檔裡面的說明檔Skype4Com.chm,裡面所說到的Class name, Function name都不能直接用,因為Skype4Com.dll已經透過BCB封裝過了,所以必須按照BCB編過後的方式去處理才行,封裝過後的檔案在$(BCB)/Imports/裡,有四個檔案,包括SKYPE4COMLib_OCX與SKYPE4COMLib_TLB的.cpp與.h檔。以下的範例有提到,請參考。
比較需要注意的是,由於Skype4Com下載下來的壓縮檔裡面的說明檔Skype4Com.chm,裡面所說到的Class name, Function name都不能直接用,因為Skype4Com.dll已經透過BCB封裝過了,所以必須按照BCB編過後的方式去處理才行,封裝過後的檔案在$(BCB)/Imports/裡,有四個檔案,包括SKYPE4COMLib_OCX與SKYPE4COMLib_TLB的.cpp與.h檔。以下的範例有提到,請參考。
#include <vcl.h>範例檔下載連結
#include <iostream>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "SKYPE4COMLib_OCX"
#pragma resource "*.dfm"
TForm1 *Form1;
using namespace std;
// 這個程式是用來測試Skype4Com的一些功能
// (1) 要執行這個程式 首先要將$(BCB)/Imports/加入 Include Path
// #include "SKYPE4COMLib_OCX.h"
// (2) 需要新增以下的元件:
// TListBox *ListBox1;
// TButton *Button1;
// TButton *Button2;
// TButton *Button3;
// TMemo *Memo1;
// (3) 需要額外宣告變數:
// TSkype * mSkype;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
mSkype = new TSkype(Owner);
mSkype->Attach(5,false);
// test if Skype is running, if not, start it;
if( !mSkype->Client->IsRunning )
mSkype->Client->Start(false,false);
// 1st parameter - start Skype in minimized state
// 2nd parameter - show splash screen
// Get the count of Friends
int count = mSkype->Friends->get_Count();
// Add Friend list to Memo
for( int i=1 ; i<count ; i++ )// start index from 1 !!!
this->ListBox1->Items->Add( mSkype->Friends->get_Item(i)->get_Handle() );
// 設置處理Skype Event的function
mSkype->OnCallStatus = OnCallStatus;
mSkype->OnMessageStatus = OnMessageStatus;
}
// @target :
// Create 一個Chat Object
// 並傳送訊息給 Friend "falldog7_test"
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IChatPtr chat;
chat = mSkype->CreateChatWith( L"falldog7_test" );
//開啟對話視窗
chat->OpenWindow();
//傳送訊息過去給falldog7_test
chat->SendMessage( L"Fuck You!" );
chat->Disband();
}
// @target :
// 撥電話給 好友 : "falldog7_test"
void __fastcall TForm1::Button2Click(TObject *Sender)
{
ICallPtr call = mSkype->PlaceCall(L"falldog7_test",L"",L"",L"");
}
// @target :
// 取出所有正在通話的 Call ,並將其所有的OutputDevice導至(1) Soundcard (2) File
void __fastcall TForm1::Button3Click(TObject *Sender)
{
wstring path = L"D:\\WorkRoom\\project-中文也行\\test.wav";
ICallCollectionPtr call_list = mSkype->ActiveCalls;
for( int i=1; i<=call_list->Count ; i++ ){
call_list->get_Item(i)->set_OutputDevice( callIoDeviceTypeSoundcard, L"default" );
call_list->get_Item(i)->set_OutputDevice( callIoDeviceTypeFile, const_cast<wchar_t*>(path.c_str()) );
this->Memo1->Lines->Add( "OutputDevice direct success!" );
}
}
// Skype4Com的Event
// 在Skype4Com.chm中定義的 Class : _SkypeEvents 裡面
// HRESULT CallStatus ([in] ICall *pCall,[in] TCallStatus Status)
// This event is caused by a change in call status.
// 經由BCB處理過後的header檔,定義在 $(BCB)/Imports/SKYPE4COMLib_OCX.h 88行
//
// @TCallStatus 的定義在Skype4Com.chm 與 SKYPE4COMLib_TLB.h中都找得到
// @target : 當有人Call我時(Ringing) 就直接接起此通Call
void __fastcall TForm1::OnCallStatus( TObject *Sender, ICall* _call/*[in]*/, TCallStatus Status/*[in]*/)
{
if( Status == clsRinging ){
// ShowMessage("A Call is Rining");
_call->Answer();
}
}
// Skype4Com的Event
// 在Skype4Com.chm中定義的 Class : _SkypeEvents 裡面
// HRESULT MessageStatus ([in] IChatMessage *pMessage,[in] TChatMessageStatus Status)
// This event is caused by a change in chat message status.
// 經由BCB處理過後的header檔,定義在 $(BCB)/Imports/SKYPE4COMLib_OCX.h 93行
//
// @TChatMessageStatus 的定義在Skype4Com.chm 與 SKYPE4COMLib_TLB.h中都找得到
// @target : 當有人傳訊息給我時,就在Memo1上印出訊息
void __fastcall TForm1::OnMessageStatus( TObject *Sender, IChatMessage* pMessage/*[in]*/, TChatMessageStatus Status/*[in]*/)
{
this->Memo1->Lines->Add( AnsiString("From : ")+ pMessage->FromHandle );
if( Status == cmsReceived ){
this->Memo1->Lines->Add( AnsiString("Msg : ")+ pMessage->Body );
}
}
31 1月 2008
Skype4Com in BCB
Skype4Com在BCB中實現有兩種方法
法1 : 透過Variant去控制Com的物件
法2 :
- 一種是廣為人知的透過Variant去控制Com的物件
- 另一種是使用BCB強大的功能,將Skype4Com.dll解析後,直接使用其中的class
法1 : 透過Variant去控制Com的物件
// Prepare Setp :
// 1. Add a Memo to the Form1
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Memo1->Clear();
//Create a Skype Com object
Variant oSkype;
oSkype = Variant::CreateObject("Skype4COM.Skype");
// test if Skype is running, if not, start it;
if( !oSkype.OlePropertyGet("Client").OlePropertyGet("IsRunning") )
oSkype.OlePropertyGet("Client").OleFunction("Start");
// Connect to Skype via API
oSkype.OleFunction("Attach");
// Get all firends
Variant friends = oSkype.OlePropertyGet("Friends");
int count = friends.OlePropertyGet( "Count" );
Memo1->Lines->Add( "User Count : "+IntToStr(count) );
// Add to Memo
for( int i=1 ; i<=count ; i++ )//start index from 1 !!!
Memo1->Lines->Add( friends.OlePropertyGet("Item", i).OlePropertyGet("Handle") );
}
//---------------------------------------------------------------------------
法2 :
- 下載Skype4Com Releas,解壓縮出Skype4Com.dll
- 打開BCB,點選Component -> Import ActiveX Control -> Add Skype4Com.dll -> Install
- 至元件列表中,點選「ActiveX」,看看有沒有出現「Skype」這個Icon,有的話,就是成功了
- 拉一個Skype元件下來,即可使用TSkype這個class了
- 切記:Skype4Com.dll的位置不能改變,否則BCB會出錯
// Prepare step :延伸閱讀:
// 1. Add a Skype to Form
// 2. Add a Memo to Form
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Skype = new TSkype(Owner);
Skype->Attach(5,false);
// test if Skype is running, if not, start it;
if( !Skype->Client->IsRunning )
Skype->Client->Start(false,false);
// 1st parameter - start Skype in minimized state
// 2nd parameter - show splash screen
// Get the count of Friends
int count = Skype->Friends->get_Count();
Memo1->Lines->Add( IntToStr(count) );
// Add Friend list to Memo
for( int i=1 ; i<count ; i++ )// start index from 1 !!!
Memo1->Lines->Add( Skype->Friends->get_Item(i)->get_Handle() );
}
//---------------------------------------------------------------------------
Skype API 的另一種應用 - Skype4Com
Skype4Com - 意思就是Skype for Com,是將Skype API包成一個Com的Object,讓任何支援Com/ActiveX元件的語言所使用(如:Visual Studio, Delphi, BCB, VB, PHP, ... ),但是只限於Windows平台上。
之前的文章介紹過的Skype API,是透過Windows Message去存取Skype的行為。但是這樣子的處理下,有些行為變得比較不直觀,比如,我想得到所有的友人清單,在自己撰寫的一個Function中,下Command : 「Search Friends」,卻必須在另一個Function : WndProc()中才能得到Skype回應的Message,這樣子的寫法會讓程式變得很支離破碎。
而使用Skype4Com就沒有這樣子的困擾了,當你Create出一個Skype的Com物件後,就可以直接存取它裡面的一些變數值。所以就程式的觀點而言,Skype4Com是比較優的!!!
以下的網址可參考:
延伸閱讀:
之前的文章介紹過的Skype API,是透過Windows Message去存取Skype的行為。但是這樣子的處理下,有些行為變得比較不直觀,比如,我想得到所有的友人清單,在自己撰寫的一個Function中,下Command : 「Search Friends」,卻必須在另一個Function : WndProc()中才能得到Skype回應的Message,這樣子的寫法會讓程式變得很支離破碎。
而使用Skype4Com就沒有這樣子的困擾了,當你Create出一個Skype的Com物件後,就可以直接存取它裡面的一些變數值。所以就程式的觀點而言,Skype4Com是比較優的!!!
以下的網址可參考:
- Skype官網上 Skype4Com的說明
- Skype4Com的元件說明
- Skype4Com的Example (包含VB, C++, C#, Delphi)
- Skype4Com 1.0.28.2 Release下載 (包含Skype4Com.dll, Skype4Com Windows說明檔)
延伸閱讀:
20 1月 2008
Netlimit IP Switcher 1.21 release 發佈
Netlimit IP Switcher
1.21 Release Note
-1. 自動更換IP程式
-2. 可設定流量上限
-3. 可選擇網卡更換IP
-4. 多國語言
-5. 下次執行時 可設定自動開始
Netlimit IP Switcher
1.21 Change Log
- Fixed : 修正無法正常切換IP的問題
下載連結
1.21 Release Note
-1. 自動更換IP程式
-2. 可設定流量上限
-3. 可選擇網卡更換IP
-4. 多國語言
-5. 下次執行時 可設定自動開始
Netlimit IP Switcher
1.21 Change Log
- Fixed : 修正無法正常切換IP的問題
下載連結
18 1月 2008
Netlimit IP Switcher 1.2 release 發佈
Netlimit IP Switcher
1.2 Release Note
-1. Automate Switcher your IP.
-2. Set the net limit.
-3. You can choice the interface adapter to change IP.
-4. Multi-Language.
-5. You can set it auto-run when you start it next time.
-------------------------------------
Netlimit IP Switcher
1.2 Change Log
- Add : 使用者可選擇處理哪一張網路介面卡.
- Add : 支援多國語言(中文、英文) ... testing...
下載連結
1.2 Release Note
-1. Automate Switcher your IP.
-2. Set the net limit.
-3. You can choice the interface adapter to change IP.
-4. Multi-Language.
-5. You can set it auto-run when you start it next time.
-------------------------------------
Netlimit IP Switcher
1.2 Change Log
- Add : 使用者可選擇處理哪一張網路介面卡.
- Add : 支援多國語言(中文、英文) ... testing...
下載連結
09 1月 2008
[Lex] flex如何結合c++的code
我在之前的文章介紹過Lex的基本用法了,flex是用來處理Token Analysis的好工具,原本的.l檔在flex compile過後,會變成lex.yy.c,再用gcc compile後,就可以成為執行檔了。所以一般在寫入.l檔時,都是使用c的library。不過有時候想使用c++的std library時,也是有方法可以達成的!以下介紹兩個方法供參考。
1. 偷吃步 簡易法
在.l檔直接include c++ std library,用flex產生lex.yy.c後,再用g++去compile即可。
2. c++達人 完全物件法
flex提供了一個Lex的c++版,.l檔的寫法完全class物件化,因此用了這種方法,並不能與之前的寫法相容喔。
使用方法有兩種:
a. 在.l檔裡,檔案開頭加上%option c++
b. flex指令加上-+
而flex compile過後的檔案是lex.yy.cc,而非lex.yy.c。而且會幫你自動include FlexLexer.h檔。檔案裡頭宣告了兩個class:FlexLexer和yyFlexLexer,FlexLexer是一個interface,是給yyFlexLexer繼承的,原本用到的lex c function,全部都被包進class yyFlexLexer裡,所以,在使用時,必須先宣告一個yyFlexLexer物件來使用,原本c的yyin不見了,所以要指定input、output的來源必須透過yyFlexLexer的constructor來指定(預設是stdin & stdout),下面會給個範例可以讀檔當input。
將c++版的class yyFlexLexer裡面的function與原本的c版的lex做簡單的比較:
const char * YYText()
回傳目前match的token字串,與c版的yytext相同。
int YYLeng()
回傳目前match的token字串長度,與c版的yyleng相同。
int lineno() const
回傳目前parser到的是文件中的第幾行(若要使用,記得寫入%option yylineno)
以下有個簡單完整的例子,是用c++版的Flex寫的,可以parser出文件中的number, name, string:
compile的指令:
參考文章:FreeBSD flex
1. 偷吃步 簡易法
在.l檔直接include c++ std library,用flex產生lex.yy.c後,再用g++去compile即可。
2. c++達人 完全物件法
flex提供了一個Lex的c++版,.l檔的寫法完全class物件化,因此用了這種方法,並不能與之前的寫法相容喔。
使用方法有兩種:
a. 在.l檔裡,檔案開頭加上%option c++
b. flex指令加上-+
而flex compile過後的檔案是lex.yy.cc,而非lex.yy.c。而且會幫你自動include FlexLexer.h檔。檔案裡頭宣告了兩個class:FlexLexer和yyFlexLexer,FlexLexer是一個interface,是給yyFlexLexer繼承的,原本用到的lex c function,全部都被包進class yyFlexLexer裡,所以,在使用時,必須先宣告一個yyFlexLexer物件來使用,原本c的yyin不見了,所以要指定input、output的來源必須透過yyFlexLexer的constructor來指定(預設是stdin & stdout),下面會給個範例可以讀檔當input。
將c++版的class yyFlexLexer裡面的function與原本的c版的lex做簡單的比較:
const char * YYText()
回傳目前match的token字串,與c版的yytext相同。
int YYLeng()
回傳目前match的token字串長度,與c版的yyleng相同。
int lineno() const
回傳目前parser到的是文件中的第幾行(若要使用,記得寫入%option yylineno)
以下有個簡單完整的例子,是用c++版的Flex寫的,可以parser出文件中的number, name, string:
%option noyywrap
%{
using std::cout;
int mylineno = 0;
%}
string \"[^\n"]+\"
ws [ \t]+
alpha [A-Za-z]
dig [0-9]
name ({alpha}|{dig}|\$)({alpha}|{dig}|[_.\-/$])*
num1 [-+]?{dig}+\.?([eE][-+]?{dig}+)?
num2 [-+]?{dig}*\.{dig}+([eE][-+]?{dig}+)?
number {num1}|{num2}
%%
{ws} ;/* skip blanks and tabs */
{number} cout << "number " << YYText() << '\n';
\n mylineno++;
{name} cout << "name " << YYText() << '\n';
{string} cout << "string " << YYText() << '\n';
%%
#include <fstream>
int main( int argc, char **argv )
{
std::ifstream input;
FlexLexer* lexer;
++argv, --argc;
//--- File input ---//
if ( argc > 0 ){
input.open(argv[0]);
lexer = new yyFlexLexer( &input, &std::cout );
}
//--- Stdin ---//
else{
lexer = new yyFlexLexer;
}
while( lexer->yylex() != 0 );
return 0;
}
compile的指令:
flex -+ xxx.l
g++ lex.yy.cc -o myoutput
參考文章:FreeBSD flex
03 1月 2008
[Linux] 搜尋資料夾底下 檔案內部文字
find "path name" -name "file name" -exec grep -H "search content" {} \;
find原本是用「檔案名稱」來搜尋在哪些地方有這些檔案,將這些路徑結果餵給grep後,就可以拿來搜尋檔案內部的文字片段。
Ex:
find ./kernel -name "*.c" -exec grep -H "main" {} \;
以上這段指令,是要搜尋./kernel底下所有的.c檔,內容含有"main"的地方。
find的參數:
-name 要搜尋哪些檔名
-exec utility name [argument...] {} \;
搜尋出的檔名 交給哪個執行檔(utility name)處理
{} 會被find搜尋後的檔名路徑名稱所取代
\; 代表exec的參數到此為止
grep的參數:
-H 列出搜尋到的檔案名稱路徑
find原本是用「檔案名稱」來搜尋在哪些地方有這些檔案,將這些路徑結果餵給grep後,就可以拿來搜尋檔案內部的文字片段。
Ex:
find ./kernel -name "*.c" -exec grep -H "main" {} \;
以上這段指令,是要搜尋./kernel底下所有的.c檔,內容含有"main"的地方。
find的參數:
-name 要搜尋哪些檔名
-exec utility name [argument...] {} \;
搜尋出的檔名 交給哪個執行檔(utility name)處理
{} 會被find搜尋後的檔名路徑名稱所取代
\; 代表exec的參數到此為止
grep的參數:
-H 列出搜尋到的檔案名稱路徑
27 12月 2007
[C/C++] string使用strtok的問題
string ip1 = "140.113.100.1"; string ip2 = ip1; strtok( (char*)ip1.c_str(), "." ); cout<<ip1<<endl; cout<<ip1<<endl;
這樣子的結果,會讓ip1與ip2的內容變成一樣的!!! 為什麼呢? 這一切都是strtok的陰謀啦!!!
首先 先了解一下strtok的處理動作:
char * strtok( char * input, const char * delimiter);
每呼叫一次,便將input裡的第一個delimiter字元,改成'\0' (內碼為0)。因為strtok會將input的字串的內容值改掉,因為當input=="140.113.100.1",呼叫strtok一次後,會變成"140\0113.100.1",呼叫三次後,會變成"140\0113\0100\01"。
所以在呼叫strtok時,自以為小聰明的把原本strtok(ip1.c_str(),".");產生的error改掉。改成strtok((char*)ip1.c_str(),".");將ip1.c_str()的型別const char *強制轉換成char *,才會產生這種結果。產生error的時候,就是在提醒你,可能會有問題囉。
再來,明明ip1與ip2是不一樣的變數,怎麼改到ip1後,ip2也變了呢!?
這邊的話,就跟string的assignment function的機制有關係了,據我測試後的猜測,應該是當ip2=ip1;時,兩個的字串的指標是指到同一塊memory的(for 效率)。而當ip1或ip2其中任一個將字串裡的值改變後,string的assignment function才會再allocate另一塊memory給改變字串值的變數使用。
因此,上面的code的結果,才會讓ip1與ip2的印出的結果是一樣。
所以,結論就是,想要對c++的string切token的話,就不要用c的strtok()!!!
26 12月 2007
Netlimit IP Switcher前進SourceForge!
前一陣子跑去申請了一個SourceForge的帳號,Creatte了Netlimit IP Switcher的Project來玩玩,最近終於通過了,剛上去玩了一下,通通是英文…好難看得懂喔=_="""
SourceForge Netlimit IP Switcher
最近會把之前的Release跟Source code都放上去,有興趣的人再去那邊抓吧。
SourceForge Netlimit IP Switcher
最近會把之前的Release跟Source code都放上去,有興趣的人再去那邊抓吧。
03 12月 2007
Ubuntu更改系統時間
最近在Ubuntu上,有時間不一致的問題,找了一些資料,找半天才找到,因此記錄一下。若要更改系統時間,指令如下(date+hwclock):
原本Linux上是用clock指令,而Ubuntu上是用hwclock指令。hwclock是將目前的時間,寫入HW中,才不會開機後時間又變回沒改之前的時間。
還有Ubuntu系統預設是用UTC的時間格式,若同一台電腦,同時安裝了Windows & Ubuntu可能會有時間上的問題,詳情請看此篇文章
另外一個方法:
透過ntp,網路校正時間,會跟國家標準實驗室的 time server 校時,這個方法更方便,不用再自己看時間調date。
sudo date -s 2007/12/03
sudo date -s 17:02:07
sudo hwclock --systohc --utc
原本Linux上是用clock指令,而Ubuntu上是用hwclock指令。hwclock是將目前的時間,寫入HW中,才不會開機後時間又變回沒改之前的時間。
還有Ubuntu系統預設是用UTC的時間格式,若同一台電腦,同時安裝了Windows & Ubuntu可能會有時間上的問題,詳情請看此篇文章
另外一個方法:
透過ntp,網路校正時間,會跟國家標準實驗室的 time server 校時,這個方法更方便,不用再自己看時間調date。
sudo ntpdate time.stdtime.gov.tw
訂閱:
文章 (Atom)