uniqコマンド ? の製作

とりあえずuniqフィルタ通すだけのためにVMwareOpenBSD起動するのもアレなんで uniq作成中...w

mfcよく分からんな...

結構使ってるけどダイアログモードだったり、CWndだったりするのできちんとSDI MDI使ったことないw

	ON_COMMAND(ID_UNIQ, OnUniq)

void CuniqApp::OnUniq()
{
    CString temp;
	CEditView* ev = (CEditView*)((CFrameWnd*)AfxGetMainWnd())->GetActiveView();
    ev->GetEditCtrl().GetWindowText(temp);

これでツールバーのクリックでCuniqApp::OnUniq()が呼ばれる

で、アクティヴなビューから
tempをパースする.... どーすっかなー strtokかけたろかwww

CStringを改行でパースしてCStringArray に投げ込む。

素直にMFC CStringで書いた
たぶんこっちのほうがオーバヘッド少なめだと想う。
Left Rightは実装的に自メンバのカウント操作してるだけだし。
*1

バッファ不足で落ちるから作り直したわー
CString 再帰かけるとムリダナ(・×・)
http://d.hatena.ne.jp/ore_de_work/20130223#1362403125

void ParseLines(CStringArray &sa, CString& doc)
{
	int loc, roc;
	if ( (loc = doc.Find(_T("\n"))) != -1 ) {
		// LF
		roc = loc + 1;
		if(doc.Left(loc).Right(1) == _T('\r')) {
			// CRLF
			loc = loc - 1;
		}
		sa.Add(doc.Left(loc));
		doc = doc.Right(doc.GetLength() - roc);
		ParseLines(sa, doc);

	} else if ( (loc = doc.Find(_T("\r"))) != -1 ) {
		// CR only
		roc = loc + 1;
		sa.Add(doc.Left(loc));
		doc = doc.Right(doc.GetLength() - roc);
		ParseLines(sa, doc);
	} else {
		// only line.
		sa.Add(doc);
		doc = _T("");
	}
}

再帰したらあかんわー

uniq実装部分

// CuniqApp メッセージ ハンドラ
void CuniqApp::OnUniq()
{
	// parse
	int i;
	CStringArray satemp;
	CStringArray sauniq;
	CString temp;
	CString newtext;

	CEditView* ev = (CEditView*)((CFrameWnd*)AfxGetMainWnd())->GetActiveView();
	ev->GetEditCtrl().GetWindowText(temp);
	ParseLines(sauniq, temp);

	//uniq
	if( sauniq.GetCount() > 0 )
	{
		temp = sauniq[0];
		satemp.Add(sauniq[0]);

		for(i=1;i<sauniq.GetCount();i++){
			if(temp != sauniq[i]){
				temp = sauniq[i];
				satemp.Add(sauniq[i]);
			}
		}

		// store
		for(i=0;i<satemp.GetCount();i++){
			newtext += satemp[i];
			if( i != satemp.GetCount() -1 ) newtext += _T("\r\n");
		}
		ev->GetEditCtrl().SetWindowText(newtext);
	}
}

さらに少し変更した。

  • 全選択追加
  • アクセラレーター追加
  • バース追加
  • ソート追加した。

所詮ニンゲンが読む程度のテキストファイルだしquicksortはいらんよね.
と想ったけど、やっぱquicksortにしたwww
CSortStringArray のソースは
http://support.microsoft.com/kb/120961
にあるのをコペピ
quick の場合は、http://support.microsoft.com/kb/216858/ja



// ダイアログを実行するためのアプリケーション コマンド
void CuniqApp::OnAppAbout()
{
	CAboutDlg aboutDlg;
	aboutDlg.DoModal();
}

void ParseLines(CStringArray &sa, CString& doc)
{
	int loc, roc;
	if ( (loc = doc.Find(_T("\n"))) != -1 ) {
		// LF
		roc = loc + 1;
		if(doc.Left(loc).Right(1) == _T('\r')) {
			// CRLF
			loc = loc - 1;
		}
		sa.Add(doc.Left(loc));
		doc = doc.Right(doc.GetLength() - roc);
		ParseLines(sa, doc);

	} else if ( (loc = doc.Find(_T("\r"))) != -1 ) {
		// CR only
		roc = loc + 1;
		sa.Add(doc.Left(loc));
		doc = doc.Right(doc.GetLength() - roc);
		ParseLines(sa, doc);
	} else {
		// only line.
		sa.Add(doc);
		doc = _T("");
	}
}

_AFXEXT_INLINE CEdit& CuniqApp::GetEditCtrl() const
{
	CEditView* ev = (CEditView*)((CFrameWnd*)AfxGetMainWnd())->GetActiveView();
	return ev->GetEditCtrl();
}


void CuniqApp::StoreStringArray(CStringArray& sa)
{
	INT_PTR i;
	CString newtext;

	for(i=0;i<sa.GetCount();i++){
		newtext += sa[i];
		if( i != sa.GetCount() -1 ) newtext += _T("\r\n");
	}
	GetEditCtrl().SetWindowText(newtext);
}

// CuniqApp メッセージ ハンドラ
void CuniqApp::OnSelectall()
{
	GetEditCtrl().SetSel(0,-1,0);
}

void CuniqApp::OnUniq()
{
	INT_PTR i;
	CStringArray sauniq;
	CString temp;
	CStringArray satemp;

	GetEditCtrl().GetWindowText(temp);
	ParseLines(sauniq, temp);

	//uniq
	if( sauniq.GetCount() > 0 )
	{
		temp = sauniq[0];
		satemp.Add(sauniq[0]);

		for(i=1;i<sauniq.GetCount();i++){
			if(temp != sauniq[i]){
				temp = sauniq[i];
				satemp.Add(sauniq[i]);
			}
		}

		StoreStringArray(satemp);
	}
}

void CuniqApp::OnSort()
{
	CSortableStringArray sa;
	CString temp;

	GetEditCtrl().GetWindowText(temp);
	ParseLines(sa, temp);
	sa.Sort();

	StoreStringArray(sa);
}


void CuniqApp::OnReverseSort()
{
	CSortableStringArray sa;
	CString temp;

	GetEditCtrl().GetWindowText(temp);
	ParseLines(sa, temp);
	sa.Sort(CSortableStringArray::Reverse);

	StoreStringArray(sa);
}

void CuniqApp::OnReverse()
{
	INT_PTR i;
	CStringArray sa;
	CStringArray reverse;
	CString temp;

	GetEditCtrl().GetWindowText(temp);
	ParseLines(sa, temp);

	for(i=sa.GetCount() -1;i>=0;i--){
		reverse.Add(sa[i]);
	}

	StoreStringArray(reverse);
}

しかし継承効いてるとそのままパース関数に食わせれるのが美味しいなw
Cでもできるだろうけど、無理矢理キャストしないとだめだしw

*1:Splitだと、\r \n 混在に対応できない、というか古いのでCString::Split なんてないです。AfxExtractSubString つかうらしい