2009/08/31

[轉貼]Vector用法

出處:Vector用法
內容:
Vector用于存储对象数组

常用方法

1.push_back 在数组的最后添加一个数据

2.pop_back 去掉数组的最后一个数据

3.at 得到编号位置的数据

4.begin 得到数组头的指针

5.end 得到数组的最后一个单元+1的指针

6.front 得到数组头的引用

7.back 得到数组的最后一个单元的引用

8.max_size 得到vector最大可以是多大

9.capacity 当前vector分配的大小

10.size 当前使用数据的大小

11.resize 改变当前使用数据的大小,如果它比当前使用的大,者填充默认值

12.reserve 改变当前vecotr所分配空间的大小

13.erase 删除指针指向的数据项

14.clear 清空当前的vector

15.rbegin 将vector反转后的开始指针返回(其实就是原来的end-1)

16.rend 将vector反转构的结束指针返回(其实就是原来的begin-1)

17.empty 判断vector是否为空

18.swap 与另一个vector交换数据

2009/08/26

將不特定檔案存入取出資料庫內

來源:請問如何將不特定檔案存入取出資料庫內
事實上方法極為簡單, 範例如下
(1)載入檔案存入note欄位內(note是一blob)

TFileStream *fs;
TStream *s;

if( OpenDialog1->Execute() )
{
s=Table1->CreateBlobStream( Table1->FieldByName("Note"), bmWrite );
s->Seek( 0, 0 );
fs=new TFileStream( OpenDialog1->FileName, fmOpenRead );
s->CopyFrom( fs, fs->Size );
fs->Free();
s->Free();
}

(2)自note內取出資料存成檔案
TFileStream *fs;
TStream *s;

if( SaveDialog1->Execute() )
{
s=Table1->CreateBlobStream( Table1->FieldByName("Note"), bmRead );
s->Position=0;
fs=new TFileStream( SaveDialog1->FileName, fmCreate );
fs->Seek(0, 0);
fs->CopyFrom( s, s->Size );
fs->Free();
s->Free();

夠簡單吧! 不過就是用 FileStream & Stream 在那兒轉來轉去而已
但它沒有原始檔名資料,建議你另加一欄位存放原始檔名
如果你不想存檔可以將Stream傳至您的其他元件直接觀看,例如pdf, bmp, jpg
tiff, word, excel..........等其他方式處理,反正BLOB是完完整整的將檔案存起來也不管你的資料格式是啥隨便你玩,只是請注意一下容量大小,若你是經由端
伺服器那麼最好有經過特別處理或不純放太大檔案

TClientDataSet的詳細介紹

出處:CSDN
=============================================================
在三層結構中,TClientDataSet的地位是不可估量的,她的使用正確與否,是十分關鍵的,
本文從以下幾個方面闡述她的使用,希望對你有所幫助.
1.動態索引
procedure TForm1.DBGrid1TitleClick(Column: TColumn);
begin
if (not column.Field is Tblobfield) then//Tblobfield不能索引,二進制
ClientDataSet1.IndexFieldNames:=column.Field.FieldName;
end;
2.多層結構中主從表的實現
設主表ClientDataSet1.packetrecord為-1,所有記錄
設從表ClientDataSet1.packetrecord為0,當前記錄
3.Taggregates使用
(1)在字段編輯中add new field類型為aggregates
後設置expression(表達試)
設置active:=true即可
使用dbedit的field為前者即可
(2)使用Aggergates屬性add設計表達式
調用
  showmessage(floattostr(ClientDataSet1.Aggregates.Count));
  showmessage(ClientDataSet1.Aggregates.Items[0].Value);
 
4.在單層數據庫中不要BDE
使用ClientDataSet代替table,使用ClientDataSet的loadfilename裝入cds
代替table的tablename的db或者dbf
原來的程序改造方法:
加一個ClientDataSet,使用右鍵assign locate data
後savetofile,再loadfromfile,後刪除table
將原連table的datasource設為ClientDataSet
唯一注意的是:要將midas.dll拷到system或者當前目錄
5.三層結構的公文包的實現方法
同時設定1:filename(*.cds)2.remote server
6.可以對data賦值(從另一個數據集取值)
ClientDataSet2.Data:=ClientDataSet1.Data;
ClientDataSet2.Open;
或者
ClientDataSet2.CloneCursor(ClientDataSet1,true);
ClientDataSet2.Open;
7.附加數據取得
客戶程序嚮應用服務器請求數據。如果TClientDataSet 的
FetchOnDemand 屬性設為True,
客戶程序會根據需要自動檢索附加的數據包如BLOB字段的值或嵌套表的內容。
否則,
客戶程序需要顯式地調用GetNextPacket 才能獲得這些附加的數據包。
ClientDataSet的packetrecords設置一次取得的記錄個數
8.ClientDataSet與服務器端query連接方法
(1)sql內容為空
ClientDataSet1.Close;
ClientDataSet1.CommandText:=edit1.Text;//即sql內容
ClientDataSet1.Open;
對於沒有應用服務器設置filter 如:country like 'A%'
filtered=true可實現sql功能
(2)有參數
如服務端query的sql為
select * from animals
where name like :dd
則:客戶端ClientDataSet
var
pm:Tparam;
begin
ClientDataSet1.Close;
ClientDataSet1.ProviderName:='DataSetProvider1';
pm:=Tparam.Create(nil);
pm.Name:='dd';
pm.DataType:=ftString;
ClientDataSet1.Params.Clear;
ClientDataSet1.Params.AddParam(pm);
ClientDataSet1.Params.ParamByName('dd').AsString:=edit1.Text ;
ClientDataSet1.Open;
pm.Free;
end;

9.數據的更新管理
(1)savepoint 保存目前為止數據狀態,可以恢復到這個狀態
var
pp:integer;
begin
pp:=ClientDataSet1.SavePoint;
ClientDataSet1.Edit;
ClientDataSet1.FieldByName('姓名').asstring:='古話';
ClientDataSet1.Post;
table1.Refresh;
end;
恢復點
ClientDataSet1.SavePoint:=pp;
(2)cancel,RevertRecord
取消對當前記錄的修改,只適合沒有post的,如果post,調用
RevertRecord
(3)cancelupdate
取消對數據庫所有的修改
(4)UndoLastChange(boolean),changecount
取消上一次的修改,可以實現連續撤消
參數為true:光標到恢復處
false:光標在當前位置不動
changecount返回修改記錄的次數,一個記錄修改多次,返回只一次
但UndoLastChange只撤消一次

10.可寫的recno
對於Ttable和Tquery的recno是只讀的,而TClientDataSet的recno可讀可寫
ClientDataSet1.recno:=5;是設第五個記錄為當前記錄
11.數據保存
對於table使用post可更新數據
而ClientDataSet1的post只更新內存數據,要更新服務器數據要使用
ApplyUpdates(MaxErrors: Integer),他有一個參數,是允許發出錯誤的
次數,-1表示無數次,使用simpleobjectbroker時常設為0,實現自動容錯和負載平衡

[CB6] AnsiString 類別介紹

以下也是轉載而來的內容,來源是:
AnsiString

全文如下:
AnsiString 其實是一個類(class),不過,它並不歸屬於VCL的框架,不是派生於TObject. 該類封裝了C,C++裏字串的大多操作,並有所發展。方便了C++程式師在程式中使用字串。下面挑典型和重要的說。

一、String就是AnsiString.typedef AnsiString String;

二;在VCL,幾乎所有字串都是AnsiString。若是屬性,則有要求, += 的重載對屬性不保證一定起作用。


Form1->Caption = "窗口標題"; //OK
Form1->Caption += " - 世界你好"; //Err
Form1->Caption = Form1->Caption + " - 世界你好"; //OK

同樣的事情發生 >>(移出) 或 << (移入) 重載上。如字元:
this->Font->Style >> fsBold; //不行的

三、如果要用空串,最好不用 "";

而是:AnsiString emptyStr = *NullStr;
四、現在你不用(顯式地)?字串管理記憶體了:
AnsiString name = "Mike";
ShowMessage(name); //顯示Mike
name = "張三";
ShowMessage(name); //顯示張三
AnsiString name2 = name;
name = 李四";
ShowMessage(name);
ShowMessage(name2);
AnsiString twoName = name + name2;
ShowMessage(twoName);

上面其實說明了,AnsiString 重載了 = 和 + 操作符,讓我們可以直接通過簡單的=或+操作,來賦值,改變一個字串。
如果不用Ansistring這樣或類似的而在C,C++,同樣的操作將是類似於(並不一定和上面完全一致的過程):
char* name = "Make";
ShowMessage(name);
name = new char[strlen("張三") + 1];
stcpy(name, "張三");
ShowMessage(name);
char* name2 = new char [strlen(name1)+1);
strcpy(name2,name);
delete[] name;
name = new char[strlem("李四")+1];
strcpy(name,"李四");
ShowMessage(name);
ShowMessage(name2);
char* twoName = new char [strlen(name) + strlen(name2) + 1)];
strcpy(twoName,name);
strcat(twoName,name2);
ShowMessage(twoName);
delete[] twoName;
delete[] name2;
delete[] name;

肯定可以看出後者在記憶體管理(初始分配,擴容,連接,釋放)上的一堆瑣事。當然,可以考慮用純C的 malloc,realloc, free ,及 sprintf連減少一些操作,但在C++世界裏,這樣的記憶體管理會和使用new,new[] , delete,delete[]的代碼在交接上?生問題。並不是C++程式師的首選。

可能還會說,我就是原意累點,可是直接寫記憶體管理,會帶來高效率啊。。這是不知量力。由於字串管理在一個程式中的使用率太高了,事實上不管是VC的CString, 還是STL的string,或者是C#的string,及我們這裏的AnsiString,統統採用記憶體池,及“realloc on modify(在修改時才生分配記憶體)”等技術,可謂既提高了連續記憶體使用率,又提高了運行速度,這類高級功能,不是一般你我有精力甚至能力去實現。

四、小心,AnsiString 帶有Pascal風格。

AnsiString這個類也重載 [] 操作符 ,用於得到字串中指定的字元,可是,雖然AnsiString純是用C++寫成,但它是?了實現Object Pascal內置類型string,所以必須和Object Pascal保持相容,所以,它的下標也是從1開始:
AnsiString pascal = "Pascal";
char c = pascal[1]; // c 是 'P'

五、可以得到C風格的字串。

Windows在編程介面上還是非面向物件,(等.Net完全取代後,就是了) 它的API還得用到很多的C風格的字串(上面我們舉例的那個);再者,C++既然說完全相容C,那我們難免有時還會喜歡用用C的函數庫。
AnsiString s = "123456";
int len = strlen(s.c_str());
沒錯, c_str() 這個成員函數返回的是一個 const char* 常量字串指標。因?是const的,所以用在類似strlen()這樣僅要求是const char* 的函數還算方便,如果你想安全一點,或者人家函數指定就不能是const ,那你只好複製走:
AnsiString s = "123456";
char* tmp = new char[7];
strcpy(tmp, s.c_str()); //複製
然後對tmp愛幹嘛幹嘛去。

六、它有好多字串操作成員函數,並一般都有對應的同名全局函數。

比如取長度:
AnsiString s = "Hello!";
int len = s.Length(); //求長度
但你也可以這樣:
int len = Length(s);
或例如求子串:
string subString = s.SubString(2,3);
ShowMessage(subString) // "ell"
同樣用個全局的SubString(s,2,3);
注意了,索引從1開始。

用C++實作Strtok (類似 Java StringTokenizer)

來源:strtok:Split string into tokens

在網路上在查Strtok的做法,無意間找到C++的處理模式
有網友熱心的公佈出他的程式碼(類似 Java StringTokenizer)
內容寫的真的很棒,所以就轉來這邊收藏。
如果要套用AnsiString,則可以使用AnsiString的c_str()函式,也同樣適用哦!
以下是它的源始碼內容:
//---------------------------------------------------------------------------
#include <iostream>
#include <string>
#include <vector>
#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
using namespace std;

class StringTokenizer : public std::vector<string>{

public:
 StringTokenizer(const string& s, const string& delim = " ,") {
   string::size_type lastPos = s.find_first_not_of(delim, 0);
   string::size_type pos = s.find_first_of(delim, lastPos);

   while( string::npos != pos || string::npos != lastPos ) {
     push_back(s.substr(lastPos, pos - lastPos));
     lastPos = s.find_first_not_of(delim, pos);
     pos = s.find_first_of(delim, lastPos);
   }
 }
};
int main(int argc, char* argv[])
{
 StringTokenizer stk("1, 2, 3");

 for( StringTokenizer::size_type i = 0; i < stk.size(); i++ ) {
   cout << stk[i] << endl;
 }

 system("pause");
 return 0;
}
//---------------------------------------------------------------------------

2009/08/21

羅技新滑鼠m555b試用心情(?)

最近用了一下m555b的感覺,很棒!
滾輪零磨擦!滾一下就滾個沒完沒了,需要手動煞車
常常也因為這樣而讓食指磨掉一層皮 (誤)

好用的電池更換開關,按一下蓋子就和本體分離了!很方便!

1000dpi的解析度,滑起來很柔很滑順(?)

預設的中鍵是在滾輪後面的按鈕,按滾輪是沒反應的唷!

而滾輪的左右鍵預設也是沒作用的,需要另外安裝driver才行,下次再來試試看吧!

20090821更新:
裝了m555b的驅動程式後,設定介面就跑出來了,滾輪的左右鍵也可以正常使用了
中鍵的應用程式切換鍵(有點像ALT + TAB功能的方式)所帶出來的介面很炫!跟VISTA的切換視窗功能很像,但沒這麼耗資源。

另外,零磨擦滾輪其實可以變成傳統棘輪滾輪(會出現咔啦咔啦聲音的那種)
只要壓一下滾輪,就可以做傳統和零磨擦模式的切換哦!

真是好棒的滑鼠呀!

2009/08/19

[轉載]加快你ADD Items的速度!virtual list、vector for TListview教學


寫這篇文章的人真的是佛心來的耶!超厲害的啦!希望我有一天也能夠寫出這樣的作品 ^___^

轉載自:300分求解决listview大量数据添加慢的方法

轉載內容

主  题:     讨论ListView里显示十万级以上记录时,象SQL   Server里的返回所有行的方式显示记录,怎么实现?

作  者:     cmsoft   (韦小宝是我的老乡)

等  级:

信   誉   值:     100

所属论坛:     C++   Builder   基础类

问题点数:     99

回复次数:     38

发表时间:     2002-12-31   9:57:02

回复人:   bigwhiteshark(大白鲨)   (   )

信誉:被封杀

哈哈正中本人下怀

如何用TListView来处理大量数据

采用常规方法处理ListView,在数据量大时无论是还是用了BeginUpdata和EndUpdata()

还是处理WM_EraseBkgnd信息都不会得到理想的效果,那答案是什么呢?嗯,

采用所谓Virtual ListView技术。说起来很神秘,其实点通了很简单。

通常ListView中的所有数据都是由ListView自己来管理的,它负责这些数据空间的分配和释放,

当你把ListView->OwnerData设为true时,ListView就把数据的管理权交给了你,而它只负责显示。

这时你需要自己来为数据分配和释放空间,至于你怎样来管理这些数据完全有你自己来定,

ListView完全不关心,当ListView需要显示某条数据时,它就调用OnData事件,

你只要在这个事件的处理函数里指定ListView即将显示的Item的内容就可以了。

这就是所谓的Virtual ListView技术。

由于ListView对数据管理的功能强大,随之而来的却是效率低下,

如果你采用更高效的数据管理方式就会极大的改变效率。

而且Virtual ListView只在数据需要显示时才调用OnData事件载入数据,所以速度很快。

下面的例子中,假设ListView中需要显示4列数据,所有的数据被保存在vector里。

/*Unit1.h*/
//---------------------------------------------------------------------------     
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------     
#include   <Classes.hpp>
#include   <Controls.hpp>
#include   <StdCtrls.hpp>
#include   <Forms.hpp>
#include   <ComCtrls.hpp>
#include   <vector.h>

using namespace std;
//---------------------------------------------------------------------------     

struct ListViewData //用於存儲一條資料的結構體     
{
  AnsiString Caption;
  AnsiString SubItems1;
  AnsiString SubItems2;
  AnsiString SubItems3;
};

class TForm1: public TForm
{
  __published: //   IDE-managed   Components     
    TListView * ListView1;
  void __fastcall ListView1Data(TObject * Sender, TListItem * Item);
  private: //   User   declarations     
    vector < ListViewData * > m_lvDataVector; //用於存儲所以資料的向量     
  public: //   User   declarations     
    __fastcall TForm1(TComponent * Owner);
  __fastcall~TForm1();
};

//---------------------------------------------------------------------------     

extern PACKAGE TForm1 * Form1;

//---------------------------------------------------------------------------     
#endif

/*unit1.cpp*/
//---------------------------------------------------------------------------     
#include   <vcl.h>
#pragma hdrstop#include   "Unit1.h"

//---------------------------------------------------------------------------     

#pragma package(smart_init)
#pragma resource "*.dfm"

TForm1 * Form1;
//---------------------------------------------------------------------------     
__fastcall TForm1::TForm1(TComponent * Owner) : TForm(Owner)
{
  ListView1 -> OwnerData = true;
  const int iListViewCount = 5000;
  ListView1 -> Items -> Count = iListViewCount; //必須指定,以使ListView知道其虛擬資料量   

  //保存資料     
  for (int i = 0; i < iListViewCount; ++i) {
    ListViewData * plvData = new ListViewData;
    plvData -> Caption = "Caption" + AnsiString(i);
    plvData -> SubItems1 = "SubItems1" + AnsiString(i);
    plvData -> SubItems2 = "SubItems2" + AnsiString(i);
    plvData -> SubItems3 = "SubItems3" + AnsiString(i);
    m_lvDataVector.push_back(plvData); //向vector中添加一項     
  }
}

__fastcall TForm1::~TForm1()
{
  int iCount = ListView1 -> Items -> Count;
  for (int i = 0; i < iCount; ++i) {
    ListViewData * plvData = m_lvDataVector[i];
    delete plvData; //釋放資料佔用的資源     
  }
  m_lvDataVector.clear(); //清空vector中所有條目     
}
//---------------------------------------------------------------------------     

//ListView在要顯示某條資料時會調用這個函數   
void __fastcall TForm1::ListView1Data(TObject * Sender, TListItem * Item)
{
  if (Item -> Index > m_lvDataVector.size())
    return;

  ListViewData * plvData = m_lvDataVector[Item -> Index];

  //指定要顯示的條目的資料     
  Item -> Caption = plvData -> Caption;
  Item -> SubItems -> Add(plvData -> SubItems1);
  Item -> SubItems -> Add(plvData -> SubItems2);
  Item -> SubItems -> Add(plvData -> SubItems3);
}
//---------------------------------------------------------------------------

速度很快,5000条数据只要1秒左右. 在使用Virtual ListView方式时,如果要对数据排序,只需对你保存的内部数据(这里时vector对象)排序,然后ListView->Refresh()即可。

这时你在ListView中看到的数据就是排好序的数据了。

2009/08/09

你今天上線了沒?

這兩天颱風天出門,發現了很有趣的景象,連結電線杆的電線上面滿滿都是麻雀。

嘰嘰喳喳吵個不停,彷彿是在聊天………

「你今天上線了沒?」

不知道有沒有人懂我的笑話,哈!