読者です 読者をやめる 読者になる 読者になる

劣等コンプレックス500%

身動きとれねえ 絵・プログラミング(C/C++/Java/Perl/PHP/Mysql)

【C++】C++で連想配列\HashMapの実装をしてみた

C/C++ プログラミング

C++ STLunordered_mapを利用してリストからからO(1)で要素を取り出すコードを実装してみますー。。

ハッシュテーブルを使って高速に取り出すアレ。仕組みについてはあとで解説記事書きますわ


文字列をキー、オブジェクトは自作クラスで書いてます。

★おしながき
・格納
・参照
・キーの存在の有無
・キー指定して削除
・要素数取得
・全要素削除
・ループ内での削除
・ループで列挙


クラスはシンプルにint.stringのメンバのみ。

class CL{
public:
	int d;
	string s;

	CL(int _d, string _s) : d(_d), s(_s){

	}
};

以下コード

#include <unordered_map>
using namespace std;

	unordered_map<string, CL*> map;

	//格納
	map["鞄"] =     new CL(123, "かばん");
	map["serval"] = new CL(456, "さーばる");
	map["ねこ"] =   new CL(789, "すなねこ");
	map["あらーいさーん"] = new CL(111, "アライグマ");
	map["フェネック"] =     new CL(222, "Fennec");

	//参照
	CL *cl = map["鞄"];
	printf("refer [%d][%s]\n", cl->d, cl->s.c_str() );

	
	//キーの存在確認
	if(map.find("鞄") != map.end()){
		puts("あるよ!");
	}

	//キー指定して削除
	{
		auto itr = map.find("");
		itr = map.find("鞄");
		if(itr != map.end()) map.erase(itr);
	}

	
	//要素数取得
	printf("size: %d\n", map.size() );
	
	//全要素削除
	//map.clear();

	//ループ内で削除
	for(auto itr = map.begin(); itr != map.end();++itr){
		//キー指定して削除
		if(itr->first == "ねこ"){
			string s = itr->first;
			CL *cl =   itr->second;
			printf("delete. [%s][%d]\n", s.c_str(), cl->d);
			
			itr = map.erase(itr);
			itr--;
		}
	}
	//列挙
	for(auto itr = map.begin(); itr != map.end(); ++itr){
		string s = itr->first;
		CL *cl =   itr->second;

		printf("print: [%s][%d]\n", s.c_str(), cl->d);
	}

【Java】JavaでPerlの正規表現のループwhile(/~/g)風の最小コード

プログラミング Java

正規表現でループしながら文字列キャプチャを行うやつ。
0x5C文字にも対応してます。
マッチ開始位置、マッチ文字列長さも取得してます。

C++版はコチラ。Javaでも同じことしてます。
magicu.hatenablog.com

String reg;
Pattern pt;
Matcher m;
String s;

s = "<Ⅸ噂浬>ソソソ-111<欺圭構><Ⅸ噂浬>十十十-222<欺圭構><Ⅸ噂浬>貼貼貼-333<欺圭構><Ⅸ噂浬>能能能-444<欺圭構>";
reg = "<Ⅸ噂浬>(.*?)-(\\d*?)<欺圭構>";

pt = Pattern.compile(reg, Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
m = pt.matcher(s);
while(m.find()){
	for(int i = 0; i < m.groupCount() + 1; i++){
		System.out.println("グループ文字[" + i +"] :" + m.group(i));
		System.out.println("マッチ開始 位置 :" + m.start(i));
		System.out.println("マッチ終了 位置 :" + m.end(i));
		System.out.println("マッチ文字長さ  :" + m.group(i).length());
		System.out.println();
	}
}

・結果。。。
f:id:magicu:20170117125509j:plain

【C/C++】 C++でPerlの正規表現のループwhile(/~/g){}を実装してみた。

C/C++ プログラミング

標準C++ライブラリでの正規表現
Perlの繰り返しマッチwhile(/~/g){}を実現してみた。

VC++2010で動作確認。unicodeもマルチバイトでも動きました。cppはsjisで保存

しかしググっても情報が少なすぎる。正規表現の用途って文字列キャプチャが主じゃないの??
ということでメモって置きます

0x5Cにも問題対応。が、ワイド文字を扱うstd::wstringクラスを利用する必要がある。<Ⅸ噂浬>と<欺圭構>に囲まれた文字列を繰り返しキャプチャするコードです。
加えてマッチした位置を算出してますんでsubstr()なんかと組み合わせてアレコレできると思います。

おまけに普通の正規表現正規表現による置換処理も書いてあります。

あと、標準のregexには.(任意の1文字)に改行もマッチさせるオプションはないらしい。<Ⅸ噂浬>((?:.|\n)*?)<欺圭構>
こんなふうに書くしか無いすね



Perlの繰り返しマッチwhile(/~/g){}風

wcout << L"★ループマッチング " << endl;
wstring text = L"strstr<Ⅸ噂浬>ソソソ<欺圭構>gggg<Ⅸ噂浬>十十十<欺圭構><Ⅸ噂浬>貼貼貼<欺圭構><Ⅸ噂浬>能能能<欺圭構>";
wregex reg(L"<Ⅸ噂浬>(.*?)<欺圭構>", regex_constants::icase);

wstring::const_iterator text_iter = text.cbegin();
wsmatch results;
int idx = 0;
while(regex_search(text_iter, text.cend(), results, reg, regex_constants::match_default)){
	//括弧でキャプチャした個数が入る。マッチした文字列全体も含むので1以上になるハズ
	int count = results.size();
	for(int i = 0; i < count; i++){
		wcout << L"グループ("<<i<<"): "  << results.str(i)  << endl;
		wcout << L"マッチ文字長: " << results.length(i) << endl;
		wcout << L"マッチ位置 : " << idx + results.position(i) << endl;
		wcout << "" << endl;
	}
	idx = results[0].second - text.cbegin();
	text_iter = results[0].second;
}


・全体ソースコード

#include <regex>
#include <iostream>
#pragma comment(lib,"libcpmtd.lib")

using namespace std;

int _tmain(int argc, _TCHAR* argv[]){
	wcout.imbue(locale("japanese"));
	try {
		wcout << L"★ループマッチング " << endl;

		wstring text = L"strstr<Ⅸ噂浬>ソソソ<欺圭構>gggg<Ⅸ噂浬>十十十<欺圭構><Ⅸ噂浬>貼貼貼<欺圭構><Ⅸ噂浬>能能能<欺圭構>";
		wregex reg(L"<Ⅸ噂浬>(.*?)<欺圭構>", regex_constants::icase);

		wstring::const_iterator text_iter = text.cbegin();
		wsmatch results;
		int idx = 0;
		while(regex_search(text_iter, text.cend(), results, reg, regex_constants::match_default)){
			//括弧でキャプチャした個数が入る。マッチした文字列全体も含むので1以上になるハズ
			int count = results.size();
			for(int i = 0; i < count; i++){
				wcout << L"グループ("<<i<<"): "  << results.str(i)  << endl;
				wcout << L"マッチ文字長: " << results.length(i) << endl;
				wcout << L"マッチ位置 : " << idx + results.position(i) << endl;
				wcout << "" << endl;
			}
			idx = results[0].second - text.cbegin();
			text_iter = results[0].second;
		}

		//おまけ。1回のみの正規表現マッチング。
		// regex_match()を使う。
		//
		{	
			wcout << L"★一回マッチング " << endl;

			wstring text = L"<Ⅸ噂浬>HOGE255<欺圭構>";
			//regex_constants::icaseオプションで大小区別なし。
			wregex reg(L"<Ⅸ噂浬>(hoge)(\\d+)<欺圭構>", regex_constants::icase);
			wsmatch results;

			 if(regex_match(text, results, reg)){
				 wcout << L"マッチ! " << endl;

				 wcout << L"グループ(1): "  << results.str(1)  << endl;
				 wcout << L"グループ(2): "  << results.str(2)  << endl;
			 }
		}
		//おまけ2。正規表現による文字列置換
		{	
			wcout << L"★文字列置換" << endl;

			wstring text = L"<123/456>ソソソ<123/456>十十十<123/456>";
			wregex  reg(L"<(123)/(456)>");
			wstring replace = L"[$2-$1]"; 
	
			wcout << regex_replace(text, reg, replace) << endl;
			wcout << regex_replace(text, wregex(L"<(123)/(456)>"), wstring(L"[$2-$1]")) << endl;
		}
	} catch (regex_error &e) {
		cout << "what: " << e.what() << "; code: " << e.code() << endl;
	}

	getchar();
	return 0;
}

・結果
f:id:magicu:20170116001138j:plain

【C/C++/WINAPI】 (GUI画面)ウィンドウ表示するための最小コード

C/C++ WINAPI プログラミング

僕がいつもVC++2010で使ってる、C++/WINAPIでの真っ白なウィンドウを表示する
GUIの最小コードです。
マウス入力、キーボード入力、WM_PAINT処理も付いてます
dprintf関数を使ってデバッグウィンドウに文字列出力も可能。

#include <windows.h>
#include <stdio.h>

//デバッグ出力用関数。printf()のフォーマットで使える。
#define dprintf( str, ... ) \
	{ \
		TCHAR c[2560]; \
		_stprintf( c, str, __VA_ARGS__ ); \
		OutputDebugString( c ); \
	}
	
HWND hwnd;
HINSTANCE hInstance;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp){
	static HDC hdc;
	static PAINTSTRUCT ps;
	
	switch(msg){
		case WM_KEYDOWN:{
			switch(wp){
				case 'A':{
					
					break;
				}
			}
			return 0;
		}
		case WM_LBUTTONDOWN:{
			int x = (lp & 0xFFFF);
			int y = ((lp >> 16) & 0xFFFF);
			
			return 0;
		}
		case WM_MOUSEMOVE:{
			int x = (lp & 0xFFFF);
			int y = ((lp >> 16) & 0xFFFF);
			
			return 0;
		}
		case WM_LBUTTONUP:{
			int x = (lp & 0xFFFF);
			int y = ((lp >> 16) & 0xFFFF);
			
			return 0;
		}
		case WM_PAINT: {
			hdc = BeginPaint(hwnd , &ps);
			
			//
			/*
			SetDIBitsToDevice(
				hdc , 0 , 0 ,
				srcBit_Info.bmiHeader.biWidth , srcBit_Info.bmiHeader.biHeight ,
				0 , 0 , 0 , srcBit_Info.bmiHeader.biHeight ,
				drawPixelBits , &srcBit_Info , DIB_PAL_COLORS);
			*/
				
			EndPaint(hwnd , &ps);
			return 0;
		}
		case WM_DESTROY: {
			PostQuitMessage(0);
			return 0;
		}
		case WM_CREATE: {
			return 0;
		}
	}
return DefWindowProc(hwnd, msg, wp, lp);
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow){
	WNDCLASSEX wc;                                 // 定義用の構造体
	LPTSTR pClassName = TEXT("MWIN");      // クラス名
	hInstance = hInst;

	wc.cbSize        = sizeof(WNDCLASSEX);         // 構造体サイズ
	wc.style         = CS_HREDRAW | CS_VREDRAW;    // クラススタイル
	wc.lpfnWndProc   = (WNDPROC)WndProc;       // プロシージャ
	wc.cbClsExtra    = 0;                          // 補足メモリブロック
	wc.cbWndExtra    = 0;                          //   のサイズ
	wc.hInstance     = hInst;                      // インスタンス
	wc.hIcon         = NULL;   // アイコン
	wc.hCursor       = LoadCursor(NULL,IDC_ARROW); // カーソル
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);   // 背景色
	wc.lpszMenuName  = NULL;                   // メニュー
	wc.lpszClassName = pClassName;                 // クラス名
	wc.hIconSm       = NULL;    // 小さいアイコン
	if (!RegisterClassEx(&wc)){
		MessageBox(NULL,TEXT("RegisterClass Error."),TEXT(""),MB_OK|MB_ICONWARNING);
		return -1;
	}
	
	hwnd = CreateWindow(pClassName, TEXT("タイトル"),
		WS_OVERLAPPEDWINDOW ,
		CW_USEDEFAULT, CW_USEDEFAULT,
		640, 480,
		NULL , NULL ,hInst , NULL);
	if(!hwnd){
		MessageBox(NULL,TEXT("CreateWindow Error."),TEXT(""),MB_OK|MB_ICONWARNING);
		return -1;
	}
	
	ShowWindow(hwnd, SW_SHOW);
	MSG msg;
	while(GetMessage(&msg , NULL , 0 , 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}