5月21日 柏原正三 第9章
シリアライズ関数を使うと、保存の際、頭に a ががが のようにが入る? ちなみにこの文字コード値は一定していない。
漢字の場合、最後に・が残るが、これは何かの半角文字である。 エンターキーを押せば消えるのは、 これにより2バイトの空文字と判断されるためではないか。
いずれにせよ、以下のように実装しなおす。
void CDocViewDoc?::BackSpace?() { int index = 0; int kanji_stat = 0; unsigned char uch; int len = strData.GetLength?(); while(index < len) { uch = (unsigned char)strData.GetAt?(index);
if(uch >= 0x81 && uch <= 0x9f || uch >= 0xe0 && uch <= 0xfc) { kanji_stat = 2; } else if(uch == 0x0d) { kanji_stat = 1; } else{ kanji_stat = 0; }
switch(kanji_stat) { case 0: AfxMessageBox?("半角文字である"); strData.Delete(strData.GetLength?() - 1, 1); break; case 1: AfxMessageBox?("改行文字である"); strData.Delete(strData.GetLength?() - 1, 1); break; case 2: AfxMessageBox?("漢字である"); strData.Delete(strData.GetLength?() - 2, 2); break; } len = strData.GetLength?(); // by ISHIDA 先頭文字から削除したので、もう一度長さを計りなおす。 }
}
}
10章
手作業で 1 ユーザーメッセージ、2 メッセージマップ、3 ハンドラ関数を実装。
ハンドラ関数は、1,2がすんだ状態であれば、たとえばP361は CMaiFrame?.cpp に直接
LRESULT CMainFrame?::
と打ち込むと、関数選択ダイアログが出てくるので、そのまま実装する。
5月24日 wsprintf
/* int num = 10; CString nums;
wsprintf((const char*)nums, "%i", num); wsprintf(nums, "%i", num); 'wsprintfA' : 1 番目の引数を 'class CString' から 'char *' に変換できません。 (新しい機能 ; ヘルプを参照) この変換を実行可能なユーザー定義変換演算子がないか、または演算子を呼び出せません。
/* wsprintf((char*)nums, "%i", num); error C2440: 'type cast' : 'class CString' から 'char *' に変換することはできません。(新しい動作 ; ヘルプを参照) この変換を実行可能なユーザー定義変換演算子がないか、または演算子を呼び出せません。
/* wsprintf((const char*)nums, "%i", num); 'wsprintfA' : 1 番目の引数を 'const char *' から 'char *' に変換できません。 (新しい機能 ; ヘルプを参照) 変換で修飾子が失われます。 (constが属性が消えることになってしまう by ISHIDA)
たとえば int sprintf( char *buffer, const char *format [, argument] ... );
この関数では、2番目の引数(コピー元の文字列にconst属性があるから、 コピー先である第一引数にCString 文字クラスのオブジェクトをおいた場合、char型へのキャストと共に、const指定が必要となる。
void Func( CString& str, int i ) { char buffer[100]; wsprintf( buffer, "i = %i", i ); str = buffer; }
あるいは str.Format("i= %i", i); Subject: [vcpp 00000013] CString (Re: Call DLL)
解答は Visual C++ マニュアル ”文字列 : CString 演算と C スタイルの文字列” に。
また柏原C++ P.87
const char *p_moji = new char[10]; << この式は実体はconst化するが、ポインタは変更可能。 strcpy(p_moji, "ABCDE"); << 1 番目の引数を 'const char *' から 'char *' に変換できません。
一番目の引数の「実体」を変更しようとするからエラーとなる。この引数のポインタであれば変更可能。だから、さらにポインタ方にキャストするというのが原理。
要するにC、C++ 環境でも、const宣言した変数のポインタを、たとえば const属性されていない別の参照変数に代入したりなんかすると、後者の方 で前者の実体を勝手に変更されるような操作が認められたりするから、そ れは許されない。だから後者にもconst属性が必要である。それと同じよう な理屈かと、納得できたような気がします。ともかく、お騒がせしまし た。m(__)m
const char moji* = "A"; char &ref_moji = moji; << エラー const char &ref_moji = moji; << OK
6月15日 ワイド文字 と マルチバイト文字
HexString?プログラムより
ch1 = str.GetAt?(0); ch2 = str.GetAt?(1);
unsigned char toWch[2]; toWch[0] = ch1; toWch[1] = ch2; wchar_t wch; mbtowc(&wch, (char*)(const char *) toWch, 2);
str5.Format("最初の全角文字のユニコードは \"%04X\"",wch);
/* 以下はエラー
mbtowc(&wch, toWch,2);
E:\Program\cpp\HexString?\Change.cpp(58) : error C2664: 'mbtowc' : 2 番目の引数を 'unsigned char [2]' から 'const char *' に変換できません。 (新しい機能 ; ヘルプを参照) 指示された型は関連がありません; 変換には reinterpret_cast、 C スタイル キャスドたは関数スタイルのキャストが必要です。
6月25日 トークン化 strtok
strtok には最初の文字列を残して、残りを削除する効果がある?
SYNTAX.VCFILE プロジェクトより
char seps[] = "!$\"\u00a3%^&*()_+=#{}[]'`/?.,:; \t\n"; char crlf[] = "\r\n"; char *token;
m_text = ""; while(fin.ReadString?(buff,1000) != NULL) { m_text = m_text + buff; }
token = strtok((char *)(const char *)m_text, seps);
while( token != NULL ) { char *m_token = token; m_list.AddString?(m_token); token = strtok( NULL, seps ); }
UpdateData?(FALSE);
m_text エディットボックスに 表示されるのは、 ファイルから読み込んだ文字列のうち、最初のトークンまでの一単語だけ。 m_list リストボックスには、全てのトークンが表示される。
ただし strtok の処理をネストすることはできない! たとえば Tag プログラムでは、元テキストを読み込み、 それを スペースごとに strtok かけ、その過程で、Tag()関数へトークンを渡しているが、そのTag()関数内部には、別の strtok 関数があるので、 エラーとなる。
6月25日 オブジェクトのコピーと代入
柏原 C++ の基礎知識 154ページ 林 VC++ ビギナー 468ページ
6月27日 Tagger
Brill, Eric(1992), A simple rule-based part of speech tagger. IN: Third Conference on Applied Natural Language Processing, 152 - 155, Trento, Italy. (BA20054323)
Tufis, Dan and Oliver Mason (1998), Tagging romanian texts: a case study for qtag, a language independent probabilistic tagger. IN: Proceedings of the First International Conference on Language Resources & Evaluation(LREC), 589 - 596, Granada, Spain, May;BA36075741)
McEnery? & Wilson(1996). Mason(2000).
本論では、英文テキストファイルをコーパス処理し、 単語ごとに品詞のタグを付加するプログラムを紹介する。 筆者がこのプログラムを作成した本来の目的は、 最近の(語彙素性主義の)生成文法理論にそって、入力文を樹形図に 解析するプログラムの作成である。 そのためには、最初に、文をトークンに分け、文脈に従って品詞属性を 付与するプログラムモジュールが必要となる。 小論で紹介するのは、そのモジュールである。
アルゴリズム
Tagger クラス
1 クラスインスタンスの作成 辞書読み込み(タグ種の設定)。
2 対象ファイルを読み込む。 一行読み込むごとにトークンに分ける。 トークンごとにTAGメソッドに渡す。 渡されたトークンの直前の単語、およびその品詞情報を出力してから(3を参照)、現在のトークンの処理に移る。 TAGメソッドでは、渡されたトークンを辞書に求めて、仮のTAG文字変数に代入する。 辞書にない場合は、デフォルトの "N J V" を代入。 仮のTAGをトークンに分ける。 最初の品詞情報が、対象文字の一つ前の品詞情報と共起する可能性を求める。 品詞情報が複数ある場合は、もっとも可能性の高い数値から、品詞を求める。 ファイルの読み込みが終わったとき、直前のトークンと現在のトークンはまだ出力されていないので、これを出力して、ファイルを閉じる。
3 タグ情報のマッピング トークンごとに単語と品詞情報が渡される。ただ一文字のTAG情報では分かりにくいので、詳細化する。 詳細なTAG情報を、スクリーンまたはファイルに出力する。
Lexionクラス
1 配列クラスを用意し、辞書ファイル読み込みと同時に、単語(key)と品詞(word)の情報をセットする。
2 key(トークン = 単語)が渡されとき、 先頭の単語が数字なら M を 文字ならそのkeyに対応するwordを返す。 見つからないときは 先頭文字を小文字に変えて、key検索する。 それでも見つからないときは、 接尾辞から判断する。 単語と、辞書クラスオブジェクトを Suffix クラスに渡す。 接尾辞がsの場合、Suffixクラスから Lexicon クラスを呼び出すのに必要。 さらに見つからないときは 最初の文字が大文字なら、固有名詞。 そうでなければデフォルトの "N V J" を返す。」
Suffix クラス 渡された文字の語末のつづりから、可能性のある品詞を返す。 接尾辞が S の場合は、s を削除したトークンを、 再度辞書クラスlookup関数に渡して、品詞を得る。
6月27日 新規クラス作成
新規にクラスを作成した場合、すぐに保存しておかないと、 その後その新規クラスに追加した関数など削除すると、クラスそのものがプロジェクトの ClassView?から消え去ってしまう。
6月30日 BOOL or bool
BOOL check; // bool check にすると警告が出る if (!m_mapStr.IsEmpty?()){ check = m_mapStr.Lookup(word, entry);
6月30日 Syntaxエラー
その1
#include "stdafx.h"
#include "Tag.h"
#include "Suffix.h"
#include "Lexicon.h"
自分のクラスの後に他のクラスの宣言がある
#include "stdafx.h"
#include "Suffix.h"
#include "Lexicon.h"
自分のクラスより先に他のクラスの宣言がある
e:\program\cpp\syntax\tag\suffix.h(15) : error C2061: 構文エラー : 識別子 'CLexicon' がシンタックスエラーを起こしました。 E:\Program\cpp\Syntax\Tag\Lexicon.cpp(80) : error C2660: 'match' : 関数が不正な 2 個の実引数をともなって呼び出されました。 Suffix.cpp e:\program\cpp\syntax\tag\suffix.h(15) : error C2061: 構文エラー : 識別子 'CLexicon' がシンタックスエラーを起こしました。 E:\Program\cpp\Syntax\Tag\Suffix.cpp(34) : error C2511: 'match' : オーバーロードされたメンバ関数が '<Unknown>' にありません。 コードを生成中... cl.exe の実行エラー
Tag.exe - エラー 4、警告 0
その2
#include "stdafx.h"
#include "Tag.h"
#include "Lexicon.h"
#include "Suffix.h"
自分のクラスより前に宣言
#include "stdafx.h"
#include "Lexicon.h"
#include "Suffix.h"
自分のクラスである Lexicon クラスは、後に宣言しなければならない
コンパイル中... Lexicon.cpp E:\Program\cpp\Syntax\Tag\Lexicon.cpp(79) : error C2664: 'match' : 2 番目の引数を 'class CLexicon *const ' から 'class CLexicon' に変換できません。 (新しい機能 ; ヘルプを参照) コンストラクタはソース型を持てません、 またはコンストラクタのオーバーロード レゾリューションがあいまいです。 Suffix.cpp E:\Program\cpp\Syntax\Tag\Suffix.cpp(63) : error C2678: 二項演算子 '==' : 型 'class CLexicon' の左オペランドを扱う演算子は定義されていません。(または変換できません)(新しい動作; ヘルプを参照) コードを生成中... cl.exe の実行エラー
つまり CSuffixクラスのstaticメンバ関数を呼び出すCLexiconクラスでは、 まず自分のヘッダファイルをインクルードし、その後で呼び出し先の Suffixヘッダをインクルードしなければいけない
6月30日 関数の呼び出しに this ポインタを使う
次の呼び出しに対して
retval = CSuffix::match(word, this);
呼び出される方の宣言が
static CString match(CString word, CLexicon lex);
の場合 次のエラーが出るが
またはコンストラクタのオーバーロードレゾリューションがあいまいです
呼び出される方の宣言が
static CString match(CString word, CLexicon * lex);
の場合でかつ この関数内で
lex->lookUp(word) とすれば
エラーはでなくなる
7月1日 staticメンバ
Statictestプログラム
CReturnString?::CReturnString?() { str = "CReturnString? Class";
}
CReturnString?::~CReturnString?() {
}
CString CReturnString?::ReturnStr?() { return str;
}
CString CReturnString?::ReturnStaticString?() { return staticStr;
}
CString CReturnString?::staticStr = "STATIC";
またstatic メンバへのアクセスは スコープ演算子 :: で行う!
}
7月4日 static メンバ配列
Tagger クラスにて
staticメンバとして 配列を用意した場合
cpp ファイル内で 配列を初期化するが 宣言部が
static int matrix[][]; だと添え字が不正とされてエラーとなる
配列を必要な数を指定して宣言しないと、たとえば
static int matrix[18][18];
あるいは
static int matrix[][18];
としないと、エラーとなる
多重配列は 最左端の添え字を除いて、添え字を指定しなければいけない
int CMatrix::matrix[][18] = {
でコンパイル可能となる
7月5日 ファイルオブジェクトの作成
たとえば、クラスメンバとして
private CStdioFile? fout;
などと宣言済みで、
メンバ関数内で、このオブジェクトを使って、ファイルをオープンしたい場合は
void CTagger::setOutputFile?(CString outfile) { fout.Open(outfile, CFile::modeCreate | CFile::modeWrite); }
とする、次はエラーとなる。
} 7月18日 ポインタとゼロの比較
Schildt C P.152 参照のこと
Subject : [vcpp 00054455] ローカル変数の初期化について From : Ryuki Sotogaki <sotogaki@sbd.nnes.nec.co.jp> Date : Wed, 18 Jul 2001 16:01:25 +0900 Message-Id : <200107180700.f6I70wl22827@elmeth.sbd.nnes.nec.co.jp>
#include <iostream> using namespace std;
struct ST_ETC{ string txt; int num; ST_ETC( char* x ){ char* lpPtr = strchr( x, ',' ); // 2回目のf()の時が問題
ここで lpStr は ",1" という文字列へのポインタ if( lpPtr == 0 ){ num = 0; return; }
この一つ繰り上がったポインタには'1' が格納されている。 txt = x; よって x は "aaa" これは定数なので、2回目の f() 呼び出し時に使われるのは "aaa,1" ではなく "aaa"である。 num = atoi(lpPtr); num は '1' となる。 } };
void f() { ST_ETC etc1("aaa,1"); ST_ETC etc2("bbb,2"); ST_ETC etc3("ccc,3");
cout << etc1.txt.c_str() << "\t" << etc1.num << endl; cout << etc2.txt.c_str() << "\t" << etc2.num << endl; cout << etc3.txt.c_str() << "\t" << etc3.num << endl; cout << endl; }
void main() { f(); f(); int i; cin >> i; }
/* 結果 ===> aaa 1 bbb 2 ccc 3
0 0 0 /* <=== 結果 */
/* 期待した結果 ===> aaa 1 bbb 2 ccc 3
aaa 1 bbb 2 ccc 3 /* <=== 期待した結果 */
2002年8月27日
http://n76cd-01p05.ppp11.odn.ad.jp/old/a3225.html
IntelliSense?について 99.10.28.23.28 kabe
皆さんはじめまして。
Ver6.0を使っていますが、困った事が起きてしまいました。 それは、最近になってIntelliSense?(コード入力サポート機能) が使えたり、使えなくなったりすることです。
以前に自分で追加したクラスなどはIntelliSense?が働くのですが、 最近追加したクラスはIntelliSense?が働かなくなってしまいました。(同一プロジェクト内) 名前を間違っていれていたり、文法エラーが起こっているわけではありません。 しょうがないから自分で全部入力すればコンパイルは通るのです。
ヘルプファイルなど調べてみましたが、原因が分かりません。 99.10.29.14.28
もろ
ワークスペースのディレクトリに????.ncbというファイルがあると 思いますが、これは構文解析結果のキャッシュ的なファイルらしい です。 VC6ではバックグラウンドで随時更新されているようですが、経験から 言うと何かのはずみで壊れることが少なくないみたいです。 このファイルが壊れるとClassView?の表示がおかしくなったりしますが IntelliSense?も多分影響を受けると思います。 ワークスペースを閉じ、ncbファイルを削除すれば次回ワークスペース を開くときに正しく作り直されるはずなので、やってみては? 関連情報(ncbファイルの削除について): http://www.microsoft.com/japan/support/kb/articles/j045/8/62.htm
new と delete について
2002年8月27日
#include <string>
#include <iostream> using namespace std;
int main() { char * pstr; まずここで、char型ポインタpstrを宣言する。このポインタ用のメモリが確保される。
pstr = new char; 次に、メモリのどこかに、名前のない(変数名のない) char型データ用の場所を用意し、これ へのポインタを、上で用意したポインタpstrに代入する。
だから、たとえ確保されたのが char 型データ一個だけだとしても、これへのポインタが手に入り、かつこれに続くメモリが空の状態であれば、これへのポインタを先頭に、char型の配列をそっくりコピーすることができる。(最初のcharがたデータは上書きされる、足りない分は、これに続く空きメモリに書き込まれる)。
ちなみに、pstr = new char[] や pstr = new [] char ではエラーになる。これは型違いになる(char型とchar型配列は異なる)。 これは、new は、自動的にその型へのポインタを返すため、new char で用意されるのが (配列ではない)単独の char であっても、 new が返すのは、その(配列ではない単独の) char データの場所へのポインタ char* であるため,結局,配列データ型を用意したのと同じなる。
strcpy(pstr, "test"); pstr に文字列を代入する。代入先は、メモリのどこかの名前の無い(変数名がない)データの場所 。
printf("%s\n", pstr); データを表示し、
delete pstr; そして delete を使って、メモリのどこかの名前のないデータを削除してしまう。
注意するのは、この時、pstr というポインタそのものはまだ消されていないこと。だから、次のように、pstr はまだ使える。
strcpy(pstr,"that"); printf("%s\n", pstr); }
2004年9月14日 Visual C++ におけるコレクション 成功例 for(int cnt = 0; cnt <= count; cnt++){ if(m_string[cnt] != ""){ CPerson *num; BOOL check = pDoc->m_map.Lookup(m_string[cnt],(CObject *&) num); if(check){ num->age++; } else { pDoc->m_map[m_string[cnt]] = new CPerson(0); } } }
失敗例 for(int cnt = 0; cnt <= count; cnt++){ if(m_string[cnt] != ""){ CPerson *num; CPerson per(0); BOOL check = pDoc->m_map.Lookup(m_string[cnt],(CObject *&) num); if(check){ num->age++; } else { pDoc->m_map.SetAt?(m_string[cnt], (CObject *&)per); } } }
VisualBasic?
7月17日
Sub Exit
If 文の中に、さらにIf 文をネストした場合、原理的には、If文の数だけ、End If が必要になるんだろうと思いますが、次のようなコード見かけました。
Sub Test() If A >1 Then If A = 2 Then Num = "2": Exit Sub End If
If A < 10 Then If A = 7 Then Num = "7": Exit Sub End If End Sub
仮に A が 3 であった場合、最初の A > 1 が真なので、ネスとされたIf A = 2 Then に制御が移りますが、こっちは偽なので、Then以下は実行されず、次の A < 10 に移って欲しいわけです。これ自体、あんまりうまくないアルゴリズムのような気もしますが、 ともかく上のコードで期待通り動作するようです。 が、なんとなく腑に落ちず、ふと、コロンを使わず、素直に改行して、次のよう変更してみたら
If A >1 Then If A = 2 Then Num = "2" Exit Sub End If
If A < 10 Then If A = 7 Then Num = "7" Exit Sub End If
気持ちとしては、ネスとされた内部の If A = 2 Then で、これが真の場合だけ、Exit Sub で Sub Test() を抜け 、偽の場合は、内部のIf文だけ抜けて、続けて If A < 10 の評価に進んで行ってもらいたいのですが、 ところが、実行してみると、そうではなく、ここでSub Test() 自体が中断されてしまうわけです。 あるいは、場合によっては End If が無いと、エラーが出る場合もあります。 いずれにせよ、私には、この方が当然のような気がします。 つまりEnd If で明示されていない以上、Exit Sub は、ネスとされた If A = 2 Then だけに対応するのではなく、最初の If A > 1 Then にも対応しうる制御文としても実行されてしまう文なのですね。 そこで If の数だけ、対応する End If で適当に囲むと、 つまりExit Sub の次の行にもう一つ End If を足すと、 無事 If A < 10 の評価に進んでくれます。
私の感覚からすると、この後者の方が当然の動作のような気がします。 しかし、とすると、最初の コロン : の意味が良く分からんところです 。Basic でコロン : は単に、数行にわたる制御を1行で書くための記号であるだけのものだとしたら、 そもそも最初の方で、 End If を二つ省略している表記が許されるという理屈もよく納得できないところです 。 明らかに、最初の例では、コロンを続けて一行で書いた Exit Sub はネスとされた直前の If A = 2 Then 文が真のときにだけ実行される制御であるのに 、コロンを使わず、素直に改行した後者の方では、 Exit Sub はネスとされた方のIf文が偽であっても、その前の最初のIf文が真である限り、 必ず実行される制御になるようです。 ちなみに以下もだめでした。腹ただしい限りです。
If A >1 Then If A = 2 Then Num = "2": Exit Sub End If
If A < 10 Then If A = 7 Then Num = "7": Exit Sub End If
コロンで続けて文を一行に書きまとめることができる 。ただしネストされたIf文と同じ行にExit制御を書いた場合、直前にある IF 文が真のときのみ実行され 、偽の場合は、Exit Sub は実行されない。 Exit Sub を改行して記した場合、適時 End If を補わないと、 予期したような動作をしないって、ことなんですかね 。Visual Basic ってのは、よく分からんです。
以下、MSDN より、要するに Case 文か? Exit ステートメントの使用例 次の例は、Exit ステートメントを使って、For...Next ループ、Do...Loop ループ および Private Sub プロシージャから抜け出します。
Sub ExitStatementDemo?() Dim I, MyNum? Do ' 無限ループを設定します。 For I = 1 To 1000 ' ループを 1,000 回繰り返します。 MyNum? = Int(Rnd * 1000) ' 乱数を発生させます。 Select Case MyNum? ' 乱数を評価します。 Case 7: Exit For ' MyNum? が 7 であれば、For...Next から抜け出します。 Case 29: Exit Do ' MyNum? が 29 であれば、Do...Loop から抜けます。 Case 54: Exit Sub ' MyNum? が 54 であれば、Private Sub プロシージャから抜け出します。 End Select Next I Loop End Sub
VB.NET におけるアイコンの変更
アイコンは,新規追加でアイコンファイルを追加.アイコンをデザインし, ソリューションエクスプローラで,プロジェクトを右クリック. 共通プロパティ → ビルド で,作成したアイコンファイルを指定します.
フォームの左上に表示されるアイコンは フォームのプロパティー, アイコンで指定します.
theEtc その他
5月11日 文字コード計算方法
Jisコードのビット値 たとえば ア 0100101 にMBS 1 を加えてる。 日本語EUC では 10100101 となる。
5月12日
文字列プログラム
int wa = str1.Find("は"); int ga = str1.Find("が");
if(wa > 0){ str2 = str1.Left(wa); str3 = str1.Mid(wa + 2); // 1 にすると、1バイトしか読まない } else if (ga > 0){ str2 = str1.Left(ga); str3 = str1.Mid(ga + 2); // 1 にすると、1バイトしか読まない }
5月21日 whitespace
Blank, tab, Line Break のこと。Mason165ページ
2002年7月11日
Unicode で保存した文書を、Unicode に対応していないエディタで開くと、次のようになる。
? x m l v e r s i o n = " 1 . 0 " ? >
Unicodeの最初のバイトが 00 なので、当然こうなる。
2002年10月5日
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() { char data[20] = "this=is&that=is"; char first[10]; strcpy(first, strtok(data, "=&")); strcpy は配列に適用する // strcpy(first, strtok*1; もしも data を char型ポインタとしたなら、キャストすればよい。
printf("first = %s\n",first); }
Emacs Lisp
2002-1-12
Emacs-Lisp でキャラクタは ?a (= #\a)
thePerl, CGI
7月7日 my,local
ファイルポインタなどは、サブシージャーに渡した後、sabu関数内では local関数で引き受けねばいけない。 藤田:ポケットリフェランス
theLinux
6月27日 TreeTagger?
ホームディレクトリ直下で、TreeTagger?/cmd/tree-tagger-english alice.txt とすると
./cmd/separate-punctuation そのようなディレクトリ、ファイルはありませんといわれるので、 必ず TreeTagger? ディレクトリに移動して実行する。
[VC++] Form View で ダイアログを入れ換える方法
まず そのプロジェクト名(F:\program\VC_2000\TowForm\TwoForm.h)のヘッダファイルに,任意のIDを設定
#define IDU_CHANGE_VIEW (WM_USER + 101) #define IDU_CHANGE_VIEW2 (WM_USER + 101)
そのプロジェクトの(メイン)フレームクラスのヘッダ MainFrm.h に以下を記述。
protected: afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg LRESULT OnChangeView(WPARAM wParam, LPARAM lParam); afx_msg LRESULT OnChangeView2(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
そのプロジェクトの(メイン)フレームクラスのクラスファイル MainFrm.cpp に以下を記述。
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
ON_MESSAGE(IDU_CHANGE_VIEW,OnChangeView)
ON_MESSAGE(IDU_CHANGE_VIEW2,OnChangeView2)
END_MESSAGE_MAP()
// CMainFrame メッセージ ハンドラ
MainFrm.cpp に OnChangeView, OnChangeView2 を以下のように記述 OnChangeView2 の方では pNewViewClass = RUNTIME_CLASS(CTwoFormView); とオリジナルの View クラスを指定する。
LRESULT CMainFrame::OnChangeView(WPARAM wParam,LPARAM lParam){ CView* pOldActiveView = GetActiveView();
CRuntimeClass* pNewViewClass;
pNewViewClass = RUNTIME_CLASS(CNew);新しいViewクラス名 // create the new view
CCreateContext context;
context.m_pNewViewClass = pNewViewClass;
context.m_pCurrentDoc = GetActiveDocument();
CView* pNewView = STATIC_DOWNCAST(CView, CreateView(&context));
if (pNewView != NULL){ // the new view is there, but invisible and not active... pNewView->ShowWindow(SW_SHOW);
pNewView->OnInitialUpdate();
SetActiveView(pNewView);
RecalcLayout(); // finally destroy the old view...
pOldActiveView->DestroyWindow(); }
return 0L; }
新しいダイアログ IDD_FORMVIEW を FormView 型として作成し,新ダイアログ上でダブルクリックし,
新しいクラス CNew を,FormView を継承元として作成。
New.h に以下を追加 #include "TwoFormDoc.h" ...
public: CTwoFormDoc* GetDocument() const; ...
#ifndef _DEBUG
inline CTwoFormDoc* CNew::GetDocument() const { return reinterpret_cast(m_pDocument); }
#endif
New.cpp に以下を追加
CTwoFormDoc* CNew::GetDocument() const { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTwoFormDoc))); return (CTwoFormDoc*)m_pDocument; }
#endif //_DEBUG
またオリジナルのViewクラスのヘッダファイル (TwoFormView.h) にも以下を追加
#include "TwoFormDoc.h"
これにより,両方の ViewClass から以下のようにして Doc クラスを参照できる。 CTwoFormDoc * pDoc = (CTwoFormDoc *) GetDocument();
変更メッセージの発信元 (例えばオリジナルの View クラスのボタンコントロールから) TwoFormView.cpp に以下を記述。
void CViewChangeView::OnBnClickedButton1()
{ // TODO : ここにコントロール通知ハンドラ コードを追加します。
CWnd *pwd = GetParentFrame(); pwd->SendMessage(IDU_CHANGE_VIEW,0L,0L); }
[VC++] コントロールを消す方法
コントロールのコントロール変数を用意し,ShowWindow 関数の引数を ゼロにすれば良い。
m_control.ShowWindow(0);
[VC++] ウインドウ表示直前にコントロールを初期化する
View クラスに仮想関数 InitialUpDate を追加し,ここでコントロールの初期化を指定する。
[c++] Linux 数学ライブラリを使ったコンパイル
数学関数を使ったプログラムを作る場合は数学関数ライブラリを リンクする必要がある。
-l オプションを使います。
$ gcc (他の引数) -l(ライブラリ名)
ここで l と ライブラリ名の間にはスペースが入らないことに注意してくだ さい。 数学関数の場合は -lm となります。
実行例
例 1 $ gcc -o first -c first.c -lm (first.c をコンパイルし数学ライブラリをリンクする)
[perl] Perl 配列からランダムに要素を取り出す
#!/usr/bin/perl @old = 1..100; $num = 5;
for($x = 0; $x < $num; $x++){ push(@new,splice(@old,rand(@old),1)); # splice(@old, rand(@old), 1) は 配列 @old から, ランダムに選んだ添字(先頭からの番号)を指定して1個取り出す。 そして,取り出した要素は,@old から取り去る。
}
@sorted = sort{$a<=>$b}(@new);
foreach(@sorted){ print; print" "; } print "\n";
[c++] C言語でコンパイルされたオブジェクトファイル *.o をリンクする必要がある場合
extern "C"{ #include "sslib.h" }
という形式が必要。これで g++ hoge.o hoge2.o とリンクできる。
はじめから g++ でコンパイルしたオブジェクトファイルなら,extern は不要。
[PHP] php トランザクション制御
pg_query($con, "BEGIN"); pg_query($con,"LOCK TABLE $table IN SHARE ROW EXCLUSIVE MODE"); $sql = "INSERT INTO $table (mail,ip,hostname,osname,lname,fname,d) VALUES('$mail','$ip_name','$host_name','$os_name','$lname','$fname','NOW')"; @$res = pg_query($con, $sql); pg_query($con,"COMMIT"); # pg_query($con,"END");
また php.ini を以下のように編集しないと,トランザクションがエラーとなる. ;; 出力バッファリングを有効にする output_buffering = On ;; mb_output_handlerによる出力変換を有効にする output_handler = mb_output_handler
[SQL] データベースの確認
どのようなデータベースが存在しているか。
[ishida@localhost ishida]$ psql -l List of databases Name | Owner | Encoding -----------+----------+----------- ishida | ishida | EUC_JP template0 | postgres | SQL_ASCII template1 | postgres | SQL_ASCII (3 rows)
[ishida@localhost ishida]$
個別のデータベースへのアクセス (データベース名を省略するとユーザ名のデータベースへアクセスする。) [ishida@localhost ishida]$ psql ishida Welcome to psql 7.4.3, the PostgreSQL interactive terminal. ... ishida=> \d List of relations Schema | Name | Type | Owner --------+-----------+----------+-------- public | hanbai | table | ishida public | ip | table | ishida public | ip_id_seq | sequence | ishida public | shohin | table | ishida (4 rows)
ishida=>
[SQL] データベースの参照,更新
[ishida@localhost ishida]$ psql ishida Welcome to psql 7.4.3, the PostgreSQL interactive terminal. ...
ishida=> select * from hanbai ishida-> ; client | code | total ----------+-------+------- 加藤商会 | A5023 | 100 佐藤商店 | A5023 | 150 加藤商会 | A5025 | 120 加藤商会 | A5027 | 100 佐藤商店 | A5027 | 160 (5 rows)
ishida=>
[SQL] Postmasterが起動できないとき
明示的に postgresql を終了せず,PC を shutdown した場合,次回 postgresql を起動できない場合がある。
[postgres@localhost postgres]$ postmaster FATAL: pre-existing shared memory block (key 5432001, ID 1703941) is still in use HINT: If you're sure there are no old server processes still running, remove the shared memory block with the command "ipcrm", or just delete the file "/usr/local/pgsql/data/postmaster.pid". [postgres@localhost postgres]$ rm /usr/local/pgsql/data/postmaster.pid rm: remove regular file `/usr/local/pgsql/data/postmaster.pid'? y [postgres@localhost postgres]$ postmaster -S
停止は postges アカウントで
pg_ctl stop pg_ctl -m f stop //ユーザが利用中の場合
[SQL]データベースの作成,削除
postgres ユーザ,あるいは作成権のあるユーザで
createdb --encoding EUC_JP data_base dropdb data_base
[SQL]ファイルからのデータ作成
psql -e -f create.sql
特定のテーブルが対象ならば
psql -f newdatafile.sql databaseName
psql へのアクセス後は
\copy table_name from ctv.txt using delimiters ' ' ;
[SQL]データの参照
[ishida@localhost ishida]$ psql database_name Welcome to psql 7.4.3, the PostgreSQL interactive terminal. ... ishida=> \d List of relations Schema | Name | Type | Owner --------+-------+-------+-------- public | myref | table | ishida (1 row)
ishida=>
[SQL]データベースのバックアップ
データベース名ごとバックアップしたければ [ishida@server data]$ pg_dump kokusai > kokusai.dump
テーブル単位でバックアップしたければ [ishida@server data]$ pg_dump kokusai -t student_id > student_id.dump [ishida@server data]$ pg_dump kokusai -t student_address > student_address.dump [ishida@server data]$ pg_dump kokusai -t student_message > student_message.dump [ishida@server data]$
[SQL] Query の結果をファイルに出力する
まず student=> \o 2005.csv として出力ファイルを指定 student=> select student_id.id, lname,fname,lname_kana,fname_kana,sex,mail,tel, address,message from student_id, student_address, student_message where student_id.id=student_address.id and student_id.id = student_message.id; クエリーを実行 student=> \o ファイル出力の完了 student=> \q
[c++ ] C言語での冪乗
pow(x,y)を使う。
[VC++] ダイアログの動的な表示
リソースにダイアログを追加
ダイアログクラスを設定
利用する側のクラスで,上記を include
新クラスの変数を用意し,DoModalで表示。
ただし,コンストラクなどで 新クラスの変数を用意しておかないと,クラスのメンバに永続性は無い。
[VC++] ラジオボタンのグループ化と,チェック判定
グループ化ウインドウ内にそれぞれのラジオボタンを配置。ただしタブオーダが連続すること。 その上で,グループ化コントロールのGroup を true 設定。 (最初のラジオボタンの グループプロパティでも良い。)
ラジオのチェック判定は int x = GetCheckedRadioButton(IDC_FIRST_BUTTON, IDC_LAST_BUTTON); とすると,選択されたラジオボタンのID番号が取得できる。
[PHP] 表示の列名を変える エイリアスの用法
$sql = "select first as 山田, select second as 加藤 from $table where id = $id and pass = $pass and sex = $sex"; などとする。
[PHP] pg_fetch_assoc 2005/06/03
$rows = pg_fetch_assoc($res,0) とした場合
$rows["fieldname"] と,列名で1行目(0起算)の,任意の列の値を取得できる。
ただし query で列名をエイリアスにしている場合は,そのエイリアスを使う。
[PHP] Form への変数割当て
phpでformを形成する際、セッションを継続する場合、それによって継続する変数を取得し、 それをformの各typeのvalue値として設定できる。kokusai_ip_form.incの上部を参照。 <type=text name= hoge value=$fromBeforePage>
[etc 5] クラスオブジェクトとポインタ,アロー演算子
林 新C++入門 320にあるように
myclass * x; (*x).hensu // *(x.hensu)は不可
の簡略記法が
x->hensu
[etc 8] 関数内で宣言した変数を戻り値にする 2005 7 29
まず、関数が呼び出されると、仮引数や、その関数の中で宣言される変数の領域が スタックというメモリーの領域などに確保されます。 その領域は例え再帰呼び出しで同じ関数でも呼び出しの度に別々な領域になります。 実引数も関数呼び出しの度に別々にスタックにコピーされ(pushされる)て 呼ばれた関数に制御が移行します。 呼ばれた側では様々な演算処理を行い、最終的に戻る(returnする)時に、 呼び出した側にレジスターなどを用いて値を戻します。 戻り値を受け取った側はそれを代入式などの処理を通じて他の変数に代入したりして 利用できますがそれは一度だけです。
http://www2.ee.knct.ac.jp/el/E3/E305/functionQandA.html
[java script] アニメーション
JPEG/PNG画像をアニメーションさせるには連番のファイル名を付けた画像を用意しておきます。 あとは画像のsrcプロパティに番号+拡張子で構成されるファイル名を指定します。 表示される画像の番号を1ずつ増やしていき、最大枚数になったら0に戻します。 これは剰余演算を利用するとiNo %= maxNoのように簡潔に記述する事ができます。
コード
<html> <head> <title>JPEG/PNG画像をアニメーションさせる (GIFアニメの代用)</title> <script language="JavaScript"> <!-- maxNo = 5; // アニメーション枚数 iNo = 0; // 最初に表示されている画像番号 imgName = "myIMG"; preImg = new Array(); for (i=0; i<maxNo; i++) { preImg[i] = (new Image()).src; preImg[i] = i+".jpg"; } function anime() { iNo++; iNo %= maxNo; document.images[imgName].src = iNo+".jpg"; }
// --></script> </head> <body onLoad="setInterval('anime()',500)"> <img src="0.jpg" width="180" height="120" name="myIMG"> </body> </html>
[VC++] タイマーを使ったアニメーション表示 2005 10 14
WM_TIMER メッセージ関数を追加し
適当なきっかけで
UINT_PTR tm; tm = SetTimer(1,100,NULL); を設定タイマー番号1で,一秒間に100回。
OnTimer関数内に必要な処理を追加
適当なきっかけで
KillTimer(1); を記述
また,ちらつきを防ぐには,WM_ERSEBKG メッセージを追加し OnEraseBkgrd関数内で return 0 とする。
F:\program\VCPP_2000\RelegionGame PictCntDlg を参照
また参考 http://odn.okweb.ne.jp/kotaeru.php3?q=958753
ゲームのように、きれいにフェードアウトしたいのですが、どうすればいいですか? よろしくお願いします。 #include class Picture { // ここに、いろいろな変数、関数があります // 描画すると、ちらつきます void Draw(CDC *pDC) { // (CImage)image,(CDC)*imageDC,SpDCは、クラスの宣言、この関数の外 // (CBitmap)cbmp,*oldcbmp 同上 // (CBrush)Brush 同上 imageDC=CDC::FromHandle(image.GetDC()); BLENDFUNCTION bf; bf.BlendOp=AC_SRC_OVER; bf.AlphaFormat=0 ; bf.BlendFlags=0; bf.SourceConstantAlpha=(BYTE)GetImageAlpha(); // 255〜徐々に減少 SpDC.FillRect(CRect(0,0,GetImageSize().cx,GetImageSize().cy),&Brush); // CSize GetImageSize(){return imageSize;} イメージの高横 SpDC.AlphaBlend(0,0,GetImageSize().cx,GetImageSize().cy,imageDC,0,0,GetImageSize().cx,GetImageSize().cy,bf); pDC->BitBlt(0,0,GetImageSize().cx,GetImageSize().cy,&SpDC,0,0,SRCCOPY); image.ReleaseDC(); // デストラクタにて、SpDC.SelectObject(oldcbmp);cbmp.DeleteObject();SpDC.DeleteDC();Brush.DeleteObject(); } }; //補足ですが、SetTimer()でInvalidate()しています。
BOOL CFadeOutView::OnEraseBkgnd(CDC* pDC) {
return 0; }
としましたら、きれいに描画されました。
[VC++] ツールバーを消す 2005 10 14
CMainFrame の Create で指定
http://www.athomejp.com/goldfish/mfc/button/clrbutton.asp 今回は、下のようなボタンを作成します。
まず、MFCアプリケーションWizardでダイアログアプリケーションを作成し、 下のようなダイアログを作成します。 次に、CButtonクラスの派生クラスを作成します。 メニューの挿入-クラス新規作成 を選択しプロジェクトに追加してください。 ここでは、派生クラス名をCColorButtonクラスとします。 CColorButtonクラスヘッダー もしくは、プロジェクトワークスペースの右クリックで、 COLORREFとCRectのメンバ変数を追加します。
class CColorButton : public CButton { ・・・ // インプリメンテーション public: COLORREF m_color; CRect m_innerRc; virtual ~CColorButton(); } Class Wizard (Ctrl + W) もしくは、プロジェクトワークスペースで右クリックをし、 以下のメソッドをオーバーライドします。 ( Class Wizard の画面 ) CColorButtonクラスのコンストラクタで、COLORREF m_color メンバの初期化を行います。 CColorButton::CColorButton() :m_color( ::GetSysColor( COLOR_BTNFACE)) // デフォルトのボタンの表面の色を取得 { } また、Create()メソッドとPreSubclassWindow()メソッドは、
BOOL CColorButton::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { // TODO: この位置に固有の処理を追加するか、 //または基本クラスを呼び出してください dwStyle |= BS_OWNERDRAW; // OWNERDRAWスタイルを追加 return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext); } void CColorButton::PreSubclassWindow() { // TODO: この位置に固有の処理を追加するか、 // または基本クラスを呼び出してください // ボタンのスタイルを取得 DWORD style = GetStyle(); if( ( style & BS_OWNERDRAW ) != BS_OWNERDRAW) { ModifyStyle( 0, BS_OWNERDRAW); } CButton::PreSubclassWindow(); }
DrawItem()メソッドは、(ちょっと長いですが・・・)
void CColorButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // TODO: 指定されたアイテムを描画するためのコードを //追加してください // DrawItemStruct構造体からFromHandleを取得 CDC * dc = CDC::FromHandle( lpDrawItemStruct->hDC); // ディバイスコンテキストを保存 dc->SaveDC(); // 再描画する領域を取得 CRect rc = lpDrawItemStruct->rcItem; // 指定された文字の色を設定する // ここでは白に設定します dc->SetTextColor( RGB( 255,255,255)); // 描画動作が全体の再描画もしくは、 // 選択状態が変化した場合 if( lpDrawItemStruct->itemAction & ( ODA_DRAWENTIRE | ODA_SELECT )) { // DrawFrameControl()メソッドのフラグを設定 // コントロールの境界線の大きさ、かつ、 // 押されていないボタン UINT flg = DFCS_ADJUSTRECT | DFCS_BUTTONPUSH; // コントロールの状態が選択された状態の場合 if( lpDrawItemStruct->itemState & ODS_SELECTED ) { // フラグに押されたボタンのフラグを追加 flg |= DFCS_PUSHED; } // コントロールを再描画する範囲を決定 dc->DrawFrameControl( rc, DFC_BUTTON, flg); // 背景色のブラシを作成 CBrush brush( m_color); // 再描画するボタンの縁を一回り小さめにする rc.DeflateRect( 1, 1, 3, 2); // クリックされている状態の場合 if( lpDrawItemStruct->itemState & ODS_SELECTED ) { // 座標を右下にずらす rc.OffsetRect( 1, 1); } // 指定したブラシで指定範囲を塗りつぶし dc->FillRect( rc, &brush); // 座標を一時的に覚える m_innerRc = rc; // 指定されたボタンのテキストを描画する CRect rrc( rc); CString strtxt; // 作成時に指定されたボタンの表面文字の取得 GetWindowText( strtxt); if( strtxt.IsEmpty() != TRUE ) { // バックカラーは変更なし dc->SetBkMode( TRANSPARENT); // 文字を書く範囲を作成 CRect drc( rc); // 文字を書く dc->DrawText( strtxt, &drc, DT_SINGLELINE | DT_CALCRECT); // 文字の座標を計算 CPoint topleft( rc.left + ( rc.Width() - drc.Width()) /2, rc.top + ( rc.Height() - drc.Height())/2); UINT flg = 0; // ボタンが非使用の場合 if( lpDrawItemStruct->itemState & ODS_DISABLED) { flg |= DSS_DISABLED; } // 文字を再描画 dc->DrawState( topleft, CSize(0,0), strtxt, flg, TRUE, strtxt.GetLength(), (CBrush *)NULL); } } // フォーカスが着たとき // もしくはフォーカスがあるときは、 //アクティブの縁を描画する if( (lpDrawItemStruct->itemState & ODS_FOCUS) || (lpDrawItemStruct->itemAction & ODA_FOCUS) ) { CRect frc = m_innerRc; // 縁のシステムサイズをシステムから取得し、 //描画する座標を計算 frc.DeflateRect( ::GetSystemMetrics( SM_CXBORDER), ::GetSystemMetrics( SM_CYBORDER)); // フォーカスの四角枠を描画する dc->DrawFocusRect( frc); } // ディバイスコンテキストを元に戻す dc->RestoreDC( -1); } あとは、色を設定するメソッドを追加します。 プロジェクトワークスペースから、関数の追加を選択し、 SetColor()メソッドを作成します。
BOOL CColorButton::SetColor(COLORREF color) { m_color = color; this->RedrawWindow(); return TRUE; } これで、表面色が設定できるボタンクラスが完成しました。 ダイアログリソースを表示し、実際にボタンを作成してみましょう。 InitDialog()に以下のコードを追加します。 BOOL CBtn6Dlg::OnInitDialog() { ・・・ // TODO: 特別な初期化を行う時はこの場所に // 追加してください。 m_pbtn = new CColorButton; CRect rect( 1,1,100,100); m_pbtn->m_color = RGB( 0,100,100); m_pbtn->Create( "BUTTON", "test", WS_CHILD|WS_TABSTOP|WS_VISIBLE|WS_TABSTOP, rect, this,0,NULL); ・・・ } 「白に変更」と名前をつけたボタンのクリックイベントに以下のコードを追加します。 void CBtn6Dlg::OnButton1() { // TODO: この位置にコントロール通知ハンドラ用の //コードを追加してください m_pbtn->SetColor( RGB( 255,255,255)); }
後は、コンパイルを行い動作してみてください。 CColorButtonクラスのヘッダーをインクルードするのを忘れずに! また、上記のコードだとボタン表示文字の色が白固定なので、 変更しなければなりません。
[etc 6] ベクトルを引数として関数に渡す
#include #include
using namespace std;
void myadd(std::vector <int> &v, int x){ v.push_back(x); }
int main(){ } vector<int> v; for(int i = 0; i < 5; i++) v.push_back(i);
int x = 6;
vector<int>::iterator pv = v.begin();
while(pv != v.end()){ cout << *pv++ << ' '; if(x < 10){ cout << x << "in loop" << endl; myadd(v,x++); } cout << endl;
return 0;
[perl 3] ディレクトリとファイル名の取得
sub Dir{ my($path) = @_; # print $path."\t";
opendir(DIR, $path) or die "opendir $path failed: $!"; while($entry = readdir DIR){ next if( $entry =~ /^\./); $flag = -d "$path/$entry" ? 1 : 0; if($flag){ if( ("$path/$entry" eq "./.") || ("$path/$entry" eq "./..") || ("$path/$entry" eq "$path" ) ){ } else{ #print "$path$entry\t"; push(@path, "$path/$entry"); # &Dir("$path/$entry");#これだとすべてのディレクトリをさらわない。 } } else { push(@files, "$path/$entry"); } } close( DIR ); }
foreach $newpath (@path){ #print $newpath; &Dir("$newpath"); }
[perl 4] タグの削除
$TagRegex_ = q{[^"'<>]*(?:"[^"]*"[^"'<>]*|'[^']*'[^"'<>]*)*(?:>|(?=<)|$(?!\n))}; #'}}}} $Comment_TagRegex = '<!(?:--[^-]*-(?:[^-]+-)*?-(?:[^>-]*(?:-[^>-]+)*?)??)*(?:>|$(?!\n)|--.*$)'; $TagRegex = qq{$Comment_TagRegex|<$TagRegex_};
while($str = <>){ $str =~ s/(&#\d\d\d\d\;)//g; $text_regex = q{[^<]*}; $result = ''; while ($str =~ /($text_regex)($TagRegex)?/gso) { last if $1 eq '' and $2 eq ''; $result .= $1; $tag_tmp = $2; if ($tag_tmp =~ /^<(XMP|PLAINTEXT|SCRIPT)(?![0-9A-Za-z])/i) { $str =~ /(.*?)(?:<\/$1(?![0-9A-Za-z])$TagRegex_|$)/gsi; ($text_tmp = $1) =~ s/</</g; $text_tmp =~ s/>/>/g; $result .= $text_tmp; } } print $result;
# $result =~ s/ +/ /g; # if($result =~ /^[ \t]*[\r\n\f]$/){ # } # else { # print $result; # } }
[VC++] CStudioFile? の癖 2006 01 24
林 Visual C++ 6, p.365, p. 372
CStudioFile fin(m_filename, CFile::modeRead | CFile::typeBinary);
char ss[256]; fin.ReadString(ss, 256); // 配列に余裕があれば "復帰改行記号" と "\0" を入れる。 すなわち文字列の後に "\n" (0x0a) が入る。ちなみに "\0" (NULL) 文字は 文字数に入らない。
char ss; fin.ReadString(ss); // こちらは "復帰改行記号" は入らない。
ただし Visual C++ の 「EditBox での "復帰改行記号"」 は "\n" ではなく、 CR (0x0d) LF (0x0a) である。
[VC++] Dialog におけるフォントの設定 2006 01 26
BOOL CCDlgFontDlg::OnInitDialog() { CDialog::OnInitDialog(); ...
CFont myFont; static LOGFONT mySetFont; strcpy(mySetFont.lfFaceName,"MS 明朝"); mySetFont.lfWidth=0; mySetFont.lfHeight=16; mySetFont.lfCharSet= SHIFTJIS_CHARSET; mySetFont.lfWeight=700;//400なら標準書体 myFont.CreateFontIndirect(&mySetFont); m_text.SetFont(&myFont,1);//m_text は static text のコントロール変数
myFont.DeleteObject(); UpdateData(FALSE); //表示の開始 return TRUE; }
[JavaLinux?] ファイル入出力,Vector, Hashtable, 正規表現 2006 02 13
public static void main(String[] args) { String line; int max; Vector v = new Vector(); Vector lv = new Vector(); Hashtable h = new Hashtable(); String filename = "test.vec";//オリジナルトークンのベクター String listfile = "list.txt"; // オリジナルベクターファイルの読み込み try { FileReader fr = new FileReader(filename); BufferedReader br = new BufferedReader(fr); try { while((line = br.readLine()) != null){ String newline = new String(line.trim()); v.addElement(newline); //System.out.println(newline); } } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } // リストベクター ファイルの読み込み try { FileReader fr2 = new FileReader(listfile); BufferedReader br2 = new BufferedReader(fr2); try { while((line = br2.readLine()) != null){ String newline = new String(line.trim()); lv.addElement(newline); //System.out.println(newline); } } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } MyRandomize ran = new MyRandomize(v); Vector resV = ran.getVec(); /** * ランダム化されたトークンベクターと * リストベクターの要素を比較する */ Enumeration e = resV.elements(); String letter; String list; // Perl5Util p5u = new Perl5Util(); Integer i; //System.out.println("before first while"); while(e.hasMoreElements()){//ランダム化されたベクトルの要素と letter = (String) e.nextElement(); System.out.println("letter = " + letter); Enumeration el = lv.elements(); while(el.hasMoreElements()){ list = (String) el.nextElement();//リストの要素を Pattern p = Pattern.compile("^" + list + "$"); Matcher reg = p.matcher(letter); System.out.println("list = " + list ); if(reg.find()){ System.out.println("matched"); if(h.containsKey(letter)){ i = (Integer) h.get(letter);//登録済みならカウントアップ int myint = i.intValue(); myint++; i = new Integer(myint); h.put(letter,i); }else{ i = new Integer(1);//新規登録 h.put(list,i); } }else{ System.out.println("not matched"); } } } // 登録されたトークンと頻度の対応を表示 Enumeration eh = h.keys(); System.out.println("before hash table number = " + h.size()); while(eh.hasMoreElements()){ String word = (String) eh.nextElement(); Integer i1 = (Integer) h.get(word); String i2 = i1.toString(); System.out.println(word + " " + i2); } }
Eclipseでmain関数に引数を与える方法 2006 02 13
メニュー->Run->Run... New を設定して ->Arguments
[etc 9] 64ビットランダム関数の生成
#include < boost/random.hpp> #include < ctime> #include < iostream> #include < limits> using namespace std; using namespace boost; typedef unsigned long long uint64; int main(){
mt19937 gen; uniform_int< uint64> dst1(0,(uint64)(pow(2.0,64.0)-1.0)); uniform_int< uint64> dst2(0,numeric_limits< uint64>::max()); variate_generator< mt19937,uniform_int<uint64> > rand1(gen,dst1); variate_generator< mt19937,uniform_int<uint64> > rand2(gen,dst2); for (int i = 0;i < 10; i++) cout << rand1() << ' ' << rand2() << '\n'; }
で、自分のノートPCだとrand1,rand2とも正しく動きます。動いてしまいます。 しかし、研究室のマシン(64ビット)だと、rand1は0しか生成しません。 (uint64)(pow(2.0,64.0)-1.0)が、「numeric_limits< uint64>::max()」になるか、 「(2^64がオーバーフローした1)-1」=「0」となるかの違いです。
研究用のコードで、rand1のような書き方をしてたのです…。 こんな書き方しちゃ駄目ですよね。
[コメント]
2^64がオーバーフローして1になる」のような書き方をしましたが、 この段階ではdoubleなのでオーバーフローはしません…。
本当の原因は、long doubleとdoubleの違いによる丸め誤差です。
#include < cmath> #include < ctime> #include < iostream> #include < limits>
using namespace std;
typedef unsigned long long uint64;
int main(){ cout.precision(100); cout << "numeric_limits:" << numeric_limits< uint64>::max() << endl; cout << "pow(2.0,64.0) :" << pow(2.0,64.0) << endl; cout << (uint64)(pow(2.0,64.0)-1.0) << ' ' << (uint64)(pow(2.0,64.0)-(long double)1.0) << endl;
}
のようなプログラムを自分のPCと研究室のサーバーで実行したところ、
--自分のPC(WindowsXP,Cygwin,g++ 3.4.4)-- numeric_limits:18446744073709551615 pow(2.0,64.0) :18446744073709551616 18446744073709551615 18446744073709551615 ---------------------------------------- --研究室のサーバー(Turbolinux(64bit),g++ 3.2.2)--
numeric_limits:18446744073709551615 pow(2.0,64.0) :1.8446744073709552e+19 0 18446744073709551615 ----------------------------------------- となりました。要するに、pow(a,b)と書いたときに、 デフォルトで呼び出されるのが「long double pow(double,double)」か 「double pow(double,double)」かの違いです。で、 「double pow(double,double)」だと、丸め誤差のせいでnumeric_limits< uint64> を大きく上回ってしまい、そのためキャストしたときに0になってしまうようです。
どちらが正しい動作なのかは知りませんが…。
しかし、この程度のことがすぐに分からないとは情け無いです。よくこれで連続系の単位来たな…。
[eclipse CDT] Standard Make Projectと Managed Make Projec 2006 02 16
http://www.yks.ne.jp/~tsurucha/ChangeLog/cat_eclipse20cdt.html
CDTのプロジェクトとして 以下の2つから 選ぶことになる Standard Make Projectと Managed Make Project Standard Make Projectは、開発者みずから Makefileを書く形式 (従来形式?) Managed Make Projectは、CDTが勝手にMakefileを作ってくれてる。 更にGCCのコンパイルオプションをGUIで選ぶことができる。 (面倒なことはやりたくない人向け?) CDTでもコーディング&デバッグが、JDTとほとんど同じ操作で行える。 便利、便利 ただし ちょっとした落とし穴がある ソース中に Shift_JISで全角文字を使う場合、一部の文字が化けることがある 昔からC言語をやっている人には、お馴染みの問題ではあるが 全角文字の一部の文字の文字コードに エスケープ文字である \のコード0x5c が 含まれているものがあるため printf("構造体\n"); が 想定どおりに出力されない 対処方法としては、MinGW向けの 開発小部屋のパッチを使うしかない *ソースが公開されているWindowsアプリケーションをGCCでコンパイルを行う場合、 日本語の表示部分をリソースファイルとして分離しているのは、 この問題が影響しているため 文字コードがEUC-JPの場合、この問題は発生しない。 しかし Windowsにおいて日本語が想定どおりに表示されない。
[etc 10] ファイル分割した場合の処理 2006 02 17
分割した場合は g++ main.cpp sub.cpp 等とする。 ~/research/program/cpp に見本
[etc 11] Tcl Tk サンプルプログラム 2006 02 18
/* サンプル234(main関数をもつプログラム) */ #include #include "tcl.h" #include "tk.h"
//using namespace std;
int main(int argc, char* argv[]){ Tcl_Interp* interp; char bun[256];
interp = Tcl_CreateInterp();
Tcl_FindExecutable(argv[0]); if(Tcl_Init(interp) != TCL_OK){ fprintf(stderr, "Tcl initialization error: %s\n", Tcl_GetStringResult(interp)); return 1; } if(Tk_Init(interp) != TCL_OK){ fprintf(stderr, "Tk initialization error: %s\n", Tcl_GetStringResult(interp)); return 1; }
strcpy(bun, "label .laba -text {Hello, World} -rel groove -bd 3\n\ button .cmda -text {Quit} -command exit\n\ pack .laba .cmda"); Tcl_Eval(interp, bun); Tk_MainLoop(); return 0; } /* end. */
Makfike は以下 ######### sample:sample.cpp cc -o sample -I/usr/local/include -I/usr/X11R6/include \ -L/usr/local/lib -L/usr/X11R6/lib \ sample.c -ltk8.3 -ltcl8.3 -lm ######### なお -lX11 は自動的にリンクされるので不要
なお、目的のライブラリ関数が、どのライブラリに入っているかは nm コマンドで探すとよい。 % nm -o /usr/lib/*.a /usr/X11R6/lib/*.a | grep sin (コマンド nm *,ar *,) なお Turbo に libX11.a がないことについては以下に http://www.m17n.org/mule-ja-archive/1992-8/msg00168.html 「FAQ.Mule.jp に以下のような記述があるのですが、うちの Mule は shared library で動いているようです。 不思議だ。
B-2: X Window System で動く Mule を作るにはどうすればいいですか? $MULE/src/config.h の中で HAVE_X_WINDOWS というマクロを define すれ ばできます。また、HAVE_X_SELECTION を定義することにより X の SELECTION を使った cut&paste が出来るようになります。 ただし、Mule はスタティックリンクで構築されますので、スタティックリ ンク用の libX11.a が必要です。特に Sun 用の X11R5 では、普通にやると 共有ライブラリ用のものしかできないので、X を構築するさいに #define ForceNormalLib YES を追加して、スタティックリンク用の libX11.a を作る必要があります。」
file:/home/ishida/source/gethml/www.geocities.co.jp/SiliconValley/4137/dir4/tapi29.html ●main関数をもつ実行プログラムを作る場合 Makefileはこのようになります。 ここでは sample.cをコンパイルして、sampleを作ります。
CC = gcc CFLAGS = -O2 -I/usr/local/include LIBS = -L/usr/local/lib -ltcl8.4 -lm .c.o: $(CC) -c $(CFLAGS) $*.c sample: sample.o $(CC) -o $@ sample.o $(LIBS)
-Iと-Lには、それぞれtcl.hがあるディレクトリとlibtcl8.3.so があるディレクトリを指定します。 SunOS、FreeBSDなど一部のUNIXでは「libtcl83.a」 となっていることがあるので、 その場合は「-ltcl8.3」を「-ltcl83」とします。 いくつかのUNIX系OSでは、 リンクのときに「-lm」 の他にいくつかのライブラリもリンクする必要があります。 例えばSolarisなら「-lnsl -lsocket」、 Linuxなら「-ldl」、 HP-UXなら「-ldld」などです。
●Tkを使い、main関数をもつ実行プログラムを作る場合 Makefileはこのようになります。 ここでは sampletk.cをコンパイルして、sampletkを作ります。
CC = gcc CFLAGS = -O2 -I/usr/local/include -I/usr/X11R6/include LIBS = -L/usr/local/lib -ltk8.4 -ltcl8.4 \ -L/usr/X11R6/lib -lX11 -lm .c.o: $(CC) -c $(CFLAGS) $*.c sampletk: sampletk.o $(CC) -o $@ sample.o $(LIBS)
今度はTkのライブラリと Xウィンドウシステムのライブラリをリンクする必要があります。
●共有ライブラリを作る場合 Makefileは下のようになります。 ここではsample.cをコンパイルして、 libsample.soを作ります。
CC = gcc SHLD = gcc -shared CFLAGS = -O2 -fPIC -I/usr/local/include LIBS = .c.o: $(CC) -c $(CFLAGS) $*.c libsample.so: sample.o $(SHLD) -o $@ sample.o $(LIBS)
共有ライブラリを作るときのコンパイラやリンカーのオプションはOS と処理系によって 全く違います。 ここでは万国共通なフリーのコンパイラgccを使っているので 、 どのOSでもほぼ共通です。Tclのライブラリは、 動的ロードが可能なOSの場合は 上のようにリンクしなくても構いません。 gccを使う場合は、コンパイラのオプションに 「-fPIC」をつけ、 リンカーのオプションに「-shared」をつけます。 ヒューレットパッカードの HP-UXなど一部のOSでは、 -sharedでリンクする全ての オブジェクトモジュールが必ずロケーション独立 (-fPICをつけてコンパイルしたもの) でなくてはいけません。 また、できあがる共有ライブラリの拡張子は 、 そのOSの標準のものにする必要があります。 大部分のOS(SunOS,Solaris,IRIX,Linux, FreeBSDなど)は上のように「.so」 ですが、HP-UXの「.sl」のように例外もあります。 なお、gccではなくシステムのccコンパイラを使う場合はコンパイルオプションを マニュアルなどで調べてください。 一例をあげると、シリコングラフィックスのIRIXで は コンパイラオプションは特になしでリンカーに「-shared」をつけます。 FreeBSDは ccコンパイラのスイッチはgccと同じでリンカーの起動を 「ld -Bshareable -x」と します。 HP-UXではコンパイラオプションに「+z」または「+Z」をつけます 。 最後にLinuxはccコンパイラはイコールgccコンパイラですから、 どちらを使っても全く同じになります。
また「Xlibを使ったものがコンパイルできない」として file:/home/ishida/source/turbo/tl7.htmlに以下と書いてあるが不要。 「コンパイルの際に、「/usr/bin/ld: cannot find -lX11」等のエラーが出る場合は libX11.a にデフォルトで pathが通っていないのが原因。 オプションを指定するか、 # ln -s /usr/X11R6/lib/libX11.a /usr/lib などとシンボリックリンクしてしまうとよい。」
[etc 12] Static リンクと Dynamic リンク 2006 02 18
file:/home/ishida/source/program/gcc/HowToBoost/chapter_001.html
boost::regex を例に。 boost::regex ライブラリは、 バイナリのライブラリファイルを リンクする必要があります。ここでは 22 行目に示すように、 リンク時に libboost_regex-gcc.a を直接リンク(スタティックリンク)しました。 通常の UNIX であれば、拡張子が .a のものがスタティックライブラリですので、 これと同様にして実行可能です。 この場合は実行プログラム run.x に必要な関数がすべて含まれるので 、 run.x を別の場所に移動しても実行できます。
一方、ダイナミックリンクという方法もあります。 通常の UNIX なら、ライブラリファイルのありかを -L/usr/local/lib のようにリンカオプションで指定し、 さらに利用するライブラリを -lboost_regex-gcc のように(これもリンカオプション) 指定すれば、 実行プログラム中には必要な関数が含まれませんが、 実行時にダイナミックリンクされ、実行できるようになります (この場合、libboost_regex-gcc.so というシェアドオブジェクトを探せるように、 環境変数 LD_LIBRARY_PATH に /usr/local/lib が含まれている必要があります)。
また file:/home/ishida/source/command.html に
ld リンクエディタ
(コマンド ldd)
ldconfig 共有クライブラリを検索するパスを設定
lddで説明したダイナミックリンクは、 ライブラリがどのディレクトリに置いてあるかという情報が必要になる。 一般的には /usr/lib、/usr/X11R6/lib、/usr/local/libなどに 共有ライブラリが置かれている。 (コマンド ldd)
ldd ダイナミックリンクの関係を表示
プログラムを作成する場合、既に用意してあるライブラリを利用することが多い。 例えばほとんどのプログラムでは printf(3) を使うが、 だからといってほとんどのバイナリに printf(3) のコードを埋め込むのは ディスクスペースの無駄である。そこでコンパイル時にライブラリを リンクするのではなく、実行時に動的にリンクを行うこともできる。 lddはコマンドがどのランタイムライブラリを参照しているか表示する。
% ldd /usr/X11R6/bin/kterm /usr/X11R6/bin/kterm: -lXt.6 => /usr/X11R6/lib/libXt.so.6.0 (0x806f000) -lX11.6 => /usr/X11R6/lib/libX11.so.6.1 (0x80bd000) -lXmu.6 => /usr/X11R6/lib/libXmu.so.6.0 (0x805f000) -lSM.6 => /usr/X11R6/lib/libSM.so.6.0 (0x8153000) -lICE.6 => /usr/X11R6/lib/libICE.so.6.0 (0x815b000) -lgnumalloc.2 => /usr/lib/libgnumalloc.so.2.0 (0x816d000) -ltermcap.2 => /usr/lib/libtermcap.so.2.1 (0x8171000) -lc.2 => /usr/lib/libc.so.2.2 (0x8175000) ダイナミックリンクは、バイナリのサイズが少なくなることとひきかえに、 そのバイナリ単独での実行が不可能になるという欠点がある。
この例ではktermは8つのランタイムライブラリを実行時に必要とし、 1つでも欠けると実行することはできない。 もしOSの起動時に何か不具合があってシングルユーザモードで起動したとき 、/bin/lsや/bin/mountが/usr/lib/libc.*を必要としたとしても 、/usrがマウントされていないと復旧作業はできなくなってしまう。 そのため、/bin、/sbinなどのコマンドはランタイムライブラリを 必要としないように作られている。
ktermのようなリンク方式を、ダイナミックリンク・動的リンクと言い、 lsのリンク方式をスタティックリンク・静的リンクという。 静的にリンクされたバイナリをlddで見ると % ldd /bin/ls ldd: /bin/ls: not a dynamic executable となる。 (コマンド ar,ld,ldconifg) (環境変数 LD_LIBRARY_PATH)
[etc 13] LD_LIBRARY_PATH 2006 02 18
http://www.turbolinux.co.jp/world/oldbbs/index2220.html に次のような意見あり
研究室の Solaris マシンに日本語環境を一からコンパイルしていれた私としては、 (slackware に日本語環境を一から構築するようなものね)、LD_LIBRARY_PATH とかを 設定しないと動かないバイナリなんて、クソだと思ってます。おそらくビルドした人が 環境変数に LD_LIBRARY_PATH とか LD_RUN_PATH とかをいれてたんだと思いますけど、 パッケージを提供する人間はそういう環境変数を設定してはいけません。 また、LD_LIBRARY_PATH とか設定してると、自分の作ったバイナリも腐っちゃう 恐れがあるので、/etc/ld.so.conf をいじって ldconfig をやり直した方がいいです。 普通は gcc 等でバイナリをつくるときに -R オプションをつけて ライブラリのある場所をバイナリに教えてやるものです。
また2チェンネルには
LD_LIBRARY_PATHに/usr/local/libを設定しておけば? see, man ld.so
LD_LIBRARY_PATH は必ずしも必要ないよ。 リンク時に -L/path/to/lib -lname に加えて -R/path/to/lib も 指定しておけば、環境変数を指定しなくても /path/to/lib から 探してリンクしてくれる。 その Oracle のプログラムは、ダイナミックリンクできないの?
というか、LD_LIBRARY_PATHが必要になるようなバイナリは makeに失敗したバイナリと見るべき。 LD_LIBRARY_PATHはデバッグ用以外で使わないこと。
[Boost] boost:regex のサンプル 2006 02 18
詳しくは file:/home/ishida/source/program/gcc/HowToBoost/以下のファイル
#include #include #include using namespace std;
int main(int argc, char *argv[]) { const boost::regex reg_exp(".*abc.*"); // 正規表現("abc" を含む文字列) string str; // 判定対象文字列 cout << "判定したい文字列を入力 : "; while(getline(cin, str)) { if (regex_match(str, reg_exp)) { cout << "一致しました\n"; } else { cout << "一致しませんでした\n"; } cout << "判定したい文字列を入力 : "; } return(0); }
その2 const regex reg_exp("\\A\\s*\\(\\s*(-?\\d+)\\s*,\\s*(-?\\d+)\\s*\\)\\s*\\Z"); // 正規表現 const string replace("x=$1, y=$2"); // 置き換え文字列 string result; // 置き換え結果
cout << "判定したい文字列を入力 : "; while(getline(cin, str)) { result = regex_replace(str, reg_exp, replace); cout << result << endl; }
その3
http://www.kmonos.net/alang/boost/classes/regex.html
Makefile は以下のように作成
BOOST_INC = /usr/local/include/boost-1_32 BOOST_LIB = /usr/local/lib
CC = g++ OPT = -O3 DEBUG = -g -Wall CFLAGS = $(DEBUG) TARGET = run.x SRCS = main.cpp OBJS = main.o
INCDIR = -I$(BOOST_INC)
.SUFFIXES: .cc .cpp .o .x
$(TARGET): $(OBJS) $(CC) -o $@ $(OBJS) $(BOOST_LIB)/libboost_regex-gcc.a 2>&1 | c++filt
.cpp.o: $(CC) $(CFLAGS) $(INCDIR) -c $<
.cc.o: $(CC) $(CFLAGS) $(INCDIR) -c $<
clean: rm -f $(OBJS) *~ $(TARGET) core
[etc 15] GCC option 2006 02 18
file:/home/ishida/source/command.html gcc GNU Cコンパイラ
FreeBSD、Linuxなどは標準のCコンパイラがgccになっている。
-E プリプロセス後終了。コンパイルをしない -g バイナリにシンボルテーブルを付属させる。デバッガを使う場合は シンボルテーブルが必要になるので、-gオプションを付ける。 バイナリからシンボルテーブルを削除するには strip を使う。 (コマンド nm,strip) -S コンパイル後終了。アセンブルをしない -c リンクを実行しない。*.oというオブジェクトファイルを生成した時点で ストップする。 -o 生成する実行ファイル名を指定。-oを指定しないとa.outが生成される。 % cc -o bar foo.c とすると生成されるバイナリは barとなる。 % cc foo.c とするとa.outが生成される。 -v バーボーズモード。 マクロ、インクルードパス、プリプロセッサ、アセンブラ、リンカに渡すオプション を全て表示する。 -pipe テンポラリファイルを作らず、パイプで処理する。 コンパイルにかかる時間が短縮されるが、より多量のメモリが必要。 -ansi ANSI Cに準拠する。 よってGNU C独自の拡張機能、asm、inline、typeofが使えなくなる。 -trigraphs ANSI Cのトライグラフを認識する -traditional 伝統的なCの文法を認識する -w ワーニングを表示しない -W... 各種のワーニングを表示するかどうか設定する -Wall -Wスイッチで指定できる全てのワーニングを表示する -O 最適化したコードを生成する。 実行速度が速くなったり、バイナリのサイズを減らすことができる。 -O2 -O3などと最適化の段階を指定することができる。 数字が大きいほど賢い最適化を行う。 最適化を行うとコンパイルに時間がかかるので、デバッグ終了後に行うとよい。 -I インクルードファイルのパスを指定 インクルードファイルを取り込む場合は、ソースの中に #include <stdio.h> #include <sys/stat.h> #include <X11/Xutil.h> など書く。インクルードファイルが /usr/include/ 以下にあるなら、 -I オプション(大文字の i)を指定しなくても /usr/include/stdio.h、/usr/include/sys/stat.h がインクルードされる。 しかし、X11/Xutil.h は、/usr/X11R6/include/X11/Xutil.h なので、 -I/usr/X11R6/include としなければならない。
-l ライブラリを指定(小文字の L) 例・-lm -lnsl -lX11 例えば、ソース中で sin() を使った場合、sin() のライブラリを指定しないと リンク時にエラーとなる。sin() のライブラリは /usr/lib/libm.a なので、「libm.a」 から「lib」と「.a」を取り除いて「-lm」と指定する。 /usr/lib/libtermcap.a をリンクしたい場合は -ltermcapとすればよい。 printf、strlen などの基本的な関数は、全て /usr/lib/libc.a という ライブラリに含まれているが、libc.a は標準でリンクされるので -lc と指定する必要はない。
-L ライブラリのパスを指定 例・-L/usr/X11R6/lib 上で説明したライブラリのあるディレクトリにパスが通っていなかった場合、 そのディレクトリを-Lオプションで指定する。 例えば X11関係の関数を使用した場合、/usr/X11R6/lib/libX11.a をリンクする必要があるので-lX11とする、 しかし標準設定では /usr/X11R6/libがライブラリの検索対象となっていないので、 -L/usr/X11R6/lib とする必要がある。
(コマンド cc,cpp)
[etc 16] C++/Tk を実験 2006 02 18
http://cpptk.sourceforge.net/
/home/ishida/source/tcl.tk/withC/cpptk/cpptk-1.0.2/test [ishida@amd test]$
ここの Makefile (for tcktl8.4) と Makefile8.3.orig (for tcktl8.3) を参照 8.3 だとエラーが出るので 8.4 をインストールして, Makefile および /etc/ld.so.cache を更新した。
[Boost] Boost で日本語処理の例 2006 02 20
稲葉 p.52 にワイド文字列を使う必要とあるが,
// ワイド文字列 wstring 版 wregex wre(L"第([1-9])号"); wstring wstr = L"第2号"; wstring wreplaced = regex_replace(wstr, wre, L"第$1巻"); if(wreplaced == L"第2巻") wcout << "OK = " << wreplaced << endl; // Linux では wrepalced は表示されない cout << endl;
// 通常の string 版 regex re("第([1-9])号"); string str = "第2号"; string replaced = regex_replace(str, re, "第$1巻"); if(replaced == "第2巻") cout << "OK = " << replaced << endl; // Linux でも replaced は表示される。 else cout << "not founded" << endl;
なお以下の文書を参考 file:/home/ishida/source/program/boost.japanese.txt
reg_expressionは古い名前なので、代わりにbasic_regexを使えばOKです。
boost::basic_regex regex = "([a-zA-Z])(.*)[a-zA-Z]"; boost::regex regex = "([a-zA-Z])(.*)[a-zA-Z]"; //これでもOK。
[etc 18] ワイド文字列とマルチバイトの変換 2006 02 21
/research/program/boost/sample2.cpp を参照
他に http://hw001.gate01.com/eggplant/tcf/cpp/wchar_t_trap.html /home/ishida/source/gcc/strcnv.hpp
を参照
http://www.tietew.jp/cppll/archive/4783
wstringの絡んだアプリ/テスト書くとなれば string <-> wstring の相互変換は あちこちで使う
std::string narrow(const std::wstring& input) { char* buffer = new char[input.size() * MB_CUR_MAX + 1]; wcstombs(buffer, input.c_str(), input.size() * MB_CUR_MAX); std::string result = buffer; delete[] buffer; return result; }
std::wstring widen(const std::string& input) { wchar_t* buffer = new wchar_t[input.size() + 1]; mbstowcs(buffer, input.c_str(), input.size()); std::wstring result = buffer; delete[] buffer; return result; }
inline CppUnit::OStringStream& operator<<(CppUnit::OStringStream& strm, const std::wstring& x) { strm << narrow(x); return strm; }
[etc 19] C++ によるファイル処理,トークン処理 2006 02 22
fstream は入出力両方を扱う
/home/ishida/research/program/cpp/corpus/FileTokenizer.cpp
#include #include #include
using namespace std;
int main(int arg, char *argv[]){ string finame, foname; // string ss; strtok を使う場合は,読み込んだ行はchar 変数におさめる char ss[256]; ifstream fin; ofstream fout;
finame = argv[1]; foname = argv[2];
fin.open(finame.c_str()); if(!fin) return 1; fout.open(foname.c_str()); if(!fout) return 1;
char seps[] = " ,.?\t\n"; char crlf[] = "\r\n"; char *token;
while(fin >> ss){ // while(fin.getline(ss,256)){ // ifstreamクラスの メンバー関数, ss は char*型 // while(getline(fin,ss)){ //iostream (=stdio.h) クラスの メンバー関数fin は読み込み先のポインタ, ss は char * /* これについては林新C++基本機能 p.382
token = strtok((char *)(const char *)ss, seps); while( token != NULL ) { //"string" にトークンがなくなるまで繰り返し char *m_token = token; //リストへ表示し fout << m_token << endl; // 次のトークンを取得します。 token = strtok( NULL, seps ); } // fout << ss << endl; } fin.close(); } } }
[etc 20] ヘッダファイルの多重インクルード 2006 02 24
classA.H を例えば次のように宣言する
#ifndef __CLASSA_H // 多重インクルード防止 #define __CLASSA_H class ClassA // クラス宣言 private: // インスタンス変数 (データメンバ) : 通常は公開しない int Dat; ... ; // 最期はかならず ; を付ける #endif
classA.C は、classA.H を include する
#include #include #include "classA.H" // クラスの定義ファイル
このあと,コンストラクタやここの関数類を実装する。
[etc 21] Makefile での 2>&1 2006 02 25
標準出力の記録とエラー履歴を一緒に取るためにコマンドラインで次のような記述 をすると思います。
$ command >foo 2>&1
この動作を追いかけてみます。 リダイレクト機能表でも分かるように >& の 働きは、左側に書かれたファイルディスクリプタの出力を 右側に書かれたファイルディ スクリプタに変更することです。 シェルは標準入力・標準出力・エラー出力の3つのファイルをオープンしています。 そして、それらをファイルディスクリプタ0、1、2として管理しています。 ですから 2>&1 はファイルディスクリプタ2を1に、つまりエラー出力を標準 出力に 変更することになります。 さらに、>foo として標準出力がfooにリダイレク トされていますから、f ooには標準出力とエラー出力がマージされたものが書き出され ることになります。
リダイレクトのメカニズムを理解する上で大切なことは、コマンドラインで記述された ものが 右から左の順 に実行されるということです。エラー出力を標準出力にマージする この例では、まず最初に 2>&1 が実行されてから >foo が実行されます。 もし、コマンドラインで
$ command 2>&1 >foo
と書いたならば違った結果になってしまいます。どうなるかはご自分でお試しください。
[etc 22] 関数オブジェクトとは 2006 02 25
関数オブジェクトと random_shuffle については file:/home/ishida/source/gethtml/etc/spt3.html file:/home/ishida/source/gethtml/etc/13_4.htm
random_shuffle の乱数については file:/home/ishida/source/gethtml/etc/reverse_etc.html
random_shuffleの第3パラメータとして関数オブジェクトを指定します。 ところが、メンバ関数を関数オブジェクトにしようと思うと、
bind1st(mem_fun1_t(CApp::myrand),this)
のように、bind1stとmem_fun1_tと組み合わせる必要が出てきます。 このへんが非常にめんどうくさい。 さらに、そのあと関数をどこかに書かないといけません。 別の関数にせずその場で、ささっと書く。
例) int (int x,int y) { return x+y; }
と入力すれば、2数をとり、それを合計したものを返す関数オブジェクトを 作成します。(以下のように出力されます)
// lambdaクラスの定義 class lambda030416093804_0153 { public: int operator()(int x,int y) { return x+y; } }; // 関数オブジェクト lambda030416093804_0153() /** // 元ソース int (int x,int y) { return x+y; } */
この関数を用いて、
int c = lambda030416093804_0153()(10,25);
とすれば、10+25で35がcに代入されます。
[etc 23] vector, map の使い方
以下がサンプルプログラム < #include <iostream> #include <fstream> #include <string> #include <map> #include <vector> #include <ctime> #include <functional> #include <algorithm>
using namespace std;
class Random { public: // コンストラクタ Random(){ srand( (unsigned int)time(NULL) ); } unsigned int operator()(unsigned int max) { double tmp = static_cast<double>( rand() ) / static_cast<double>( RAND_MAX ); return static_cast<unsigned int>( tmp * max ); } };
int main(){ string filename = "file.cpp.test"; string str; vector<string> v; map<string, int> m1; pair<string, int> p; // ファイル操作 柏原基礎知識実践編 p.74 ifstream ifs(filename.c_str());// ファイルを開き if(!ifs){ cout << "cant find file" << endl; } else{ cout << "find file" << endl; while(!ifs.eof()){ ifs >> str; v.push_back(str);//すべての行をベクトルに代入 cout << str << endl; } } cout << "ランダム化の実行" << endl; Random r; random_shuffle(v.begin(), v.end(), r); cout << "ランダム語の表示" << endl; for(int i = 0; i < v.size(); i++){ cout << v[i] << endl; } cout << "map への登録" << endl; for(int i = 0; i < v.size(); i++){ //cout << v[i] << endl; if( (m1.find(v[i]))->second > 0){//すでにマップにあるのなら cout << "find" << endl; (m1.find(v[i]))->second = ( (m1.find(v[i]))->second) + 1; //二つ目の数値を加算 } else{// そうでないなら,データを挿入 p.first = v[i]; p.second = 1; m1.insert(p); // cout << "find " << endl; } // map の要素すべてにアクセスする cout << "map の内容の表示" << endl; map<string, int>::iterator itr; itr = m1.begin(); int n = (int)m1.size(); for (int i = 0; i < n; i++) { cout << itr->first << " " << itr->second << endl; itr++; } } }
[etc 24] メルセンヌ・ツィスター乱数 2006 02 25
#include<iostream> #include<boost/random.hpp> using namespace std; using namespace boost;
int main(){ variate_generator< mt19937, uniform_int<> > rand(mt19937(static_cast<uint64_t>(time(0))), uniform_int<> (0,1000)); vector<int> v; for(int z = 0; z < 11; ++z){ v.push_back(rand()); } cout << v.size() << endl; for(unsigned int i = 1; i <= v.size() ; ++i){ cout << v[i] ; }
}
[etc 25] ifstream から一文字読み込む 2006 03 23
柏原 標準 C++ 基礎知識実践編 p.82
ifs.get(chr);
while(!ifs.eof()){ string chr2 = chr; ifs.clear(); cout << chr << endl; ifs.get(chr); }
[etc 26] 大文字小文字を変換 2006 03 24
http://www9.plala.or.jp/sgwr-t/c/sec07.html
tolower toupper
を使う。
[etc 27] boost_replace によるタグ除去 2006 03 25
#include <iostream> #include <fstream> #include <string> #include <boost/regex.hpp> using namespace std; using namespace boost;
regex e1; regex tag_exp("<[^>]*>", regbase::normal | regbase::icase); regex amp_exp("(<)|(>)|(&)|(")|(«)|(»)|" "(ä)|(Ä)|(ö)|(Ö)|(ü)|(Ü)|" "(ß)|( )|(ここに)");// 日本語もここでは使える
const char* amp_format = "(?1<)(?2>)(?3&)(?4-)(?5-)(?6-)" "(?7ae)(?8Ae)(?9oe)(?10Oe)(?11ue)(?12Ue)" "(?13sz)(?14 )(?15あそこに)";
void load_file(string& s, istream& is) { s.erase(); s.reserve(is.rdbuf()->in_avail()); char c; while(is.get(c)) { if(s.capacity() == s.size()) s.reserve(s.capacity() * 3); s.append(1, c); } }
int main(int argc, char** argv) { string s;
for(int i = 1; i < argc; ++i) { cout << "Converting " << argv[i] << " to text:" << endl; ifstream is(argv[i]); load_file(s, is); s = regex_merge( s, tag_exp, ""); ostream_iterator<char> out(cout); regex_replace( out, s.begin(), s.end(), amp_exp, amp_format, match_default | format_all); } return 0; }
稲葉 boost p.60
[etc 28] cvs の設定 2006 03 28
.bash_profile に以下を追加
export CVSROOT=:local:/home/ishida/research/program/.CVS #export CVS_RSH=/usr/bin/ssh
[ishida@amd program]$ cvs -d /home/ishida/research/program/.CVS init
[ishida@amd boostProgram]$ cvs import -m "boost regex japanese" boostJapanese ishida start N boostJapanese/inaba52 N boostJapanese/inaba52.cpp N boostJapanese/inaba52.make I boostJapanese/inaba52.o N boostJapanese/japanese N boostJapanese/japanese.cpp N boostJapanese/japanese.make I boostJapanese/japanese.o
No conflicts created by this import
[ishida@amd boostProgram]$ cd ../ [ishida@amd cpp]$ rm -Rf boostProgram/ [ishida@amd cpp]$
[etc 29] PCL-CVS ファイルの追加 2006 03 30
編集を終えた新規ファイルを追加するには
M-e で状態を確認し, added というファイルの上で a を指定する。 このあと, c で commit しなければならない。
[etc 30] Boost Regex wstring, replace, iterator 2006 04 02
//wstring 入出力設定
// Unix 用のロケール設定
wcout.imbue(std::locale("ja_JP.eucJP")); wcin.imbue(std::locale("ja_JP.eucJP"));
// VC7(windows) 用には wcout.imbue(std::locale("japanese")); wcin.imbue(std::locale("japanese"));
//setlocale(LC_CTYPE, "") というして方法もある
// マッチした部分を、前後に#を付けた文字列で置換する wregex r2( L"(\\w+) (\\w+) (\\w+)" ); // L が必要 wstring str2 = L"これは 本 です";//スペースは半角であること { wcout << regex_replace( str2, r2, L"#$0# #$1# #$2# #$3#", boost::format_all ) << endl; //$0 はマッチした行全体、$1,$2,$3 は個別のマッチした箇所 } /////////////////////////////////////////////////// // ある条件にマッチしたところをループ表示 wregex target(L"(.)れは"); wstring str = L"これはペンです。this is a park それは公園です。あれは本です。"; // 発見した箇所すべてを表示するための変数//例えば VC7 では有効 // Linux では表示はされない wstring::const_iterator it = str.begin(), end = str.end(); while(it != end){ wsmatch result; // typedef match_results wsmatch; として定義されている // http://boost.cppll.jp/HEAD/libs/regex/doc/match_results.html if(!regex_search(it, end, result, target)) break;
wcout << result.str() << endl; it = result[0].second; }
[etc 31] カタカナをローマ字に変換 2006 04 11
C++ では http://svn.xiph.org/tags/vorbisacm_20020708/src/hmc/string.cpp /home/ishida/source/gcc/string.cpp
Perl では kana2roma.pl /home/ishida/source/perl/skktools-1.2/convert2skk/obsolete/kana2roma.pl
[etc 32] 授業用データベースプログラムの設定 2006 04 18
[ishida@amd 2006]$ cvs import -m "sql database for jyugyo" jyugyo ishida start N jyugyo/student2006.csv N jyugyo/upload.php N jyugyo/joho06.sql N jyugyo/joho.pl N jyugyo/seiseki_show.inc N jyugyo/seiseki.inc
No conflicts created by this import
[ishida@amd 2006]$ cvs checkout jyugyo cvs checkout: Updating jyugyo U jyugyo/joho.pl U jyugyo/joho06.sql U jyugyo/seiseki.inc U jyugyo/seiseki_show.inc U jyugyo/student2006.csv U jyugyo/upload.php
2006 ディレクトリ直下の元ファイルは削除
[perl 5] perl でのファイル名の処理 2006 07 24
sub argcut{
my($file) = @_; if(-e $file){ if($file =~ /(\w+)\.(\w+)$/){ $newfile = $1.&quot;.csv&quot;; } else{ $newfile = $file.&quot;csv&quot;; }
} else { print &quot;cant find $file\n&quot;; } return $newfile; }
[Boost] Fedora5 での Boost Makefile 2006 12 11
特に赤い部分を注意すること
BOOST_LIB = /usr/lib64 BOOST_INC = /usr/include/boost CC = g++ OPT = -O3 DEBUG = -g -Wall CFLAGS = $(DEBUG) TARGET = boost.test SRCS = boost.test.cpp OBJS = boost.test.o
INCDIR = -I$(BOOST_INC)
.SUFFIXES: .cc .cpp .o .x
$(TARGET): $(OBJS) $(CC) -o $@ $(OBJS) $(BOOST_LIB)/libboost_regex.a 2>&1 | c++filt
.cpp.o: $(CC) $(CFLAGS) $(INCDIR) -c $<
.cc.o: $(CC) $(CFLAGS) $(INCDIR) -c $<
clean: rm -f $(OBJS) *~ $(TARGET) core
[Java on Linux] MySQL 接続 2006 12 14
Eclipse で作成
[ishida@amd64 DataBaseTest]$ pwd /home/ishida/workspace/DataBaseTest [ishida@amd64 DataBaseTest]$ MySqlTest.class MySqlTest.java
/** * */ import java.sql.*;
/** * @author ishida * */ public class MySqlTest {
/** * @param args */ private static Connection con = null; static String url = "jdbc:mysql://localhost/books"; static String param = "?useUnicode=true&characterEncoding=EUC-JP"; static String usr = "ishida"; static String pwd = "mn"; private static Statement stmt =null; public static void main(String[] args) { // TODO Auto-generated method stub try { Class.forName("com.mysql.jdbc.Driver").newInstance(); try { con = DriverManager.getConnection(url + param, usr, pwd); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }catch(InstantiationException e){ } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { stmt = con.createStatement(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } String sql = "SELECT * FROM author"; System.out.println("SELECT * FROM author"); ResultSet rs; try { rs = stmt.executeQuery(sql); while(rs.next()){ // フィールド名を指定して値を取得 int no = rs.getInt("Num"); // フィールド Name の値を取得 String name = rs.getString("Name"); // 表示 System.out.println(no + " " + name); } // データベースから切断 stmt.close(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } try { con.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }
}
}
[Java on Linux] Java による正規表現 2006 12 14
/home/ishida/workspace/RegexTest/RegexTest.java
import java.util.regex.*;
public class HelloWorldRegex { public static void main(String[] args) { Pattern pattern; Matcher matcher; /* パターンマッチ */ System.out.println("<パターンマッチ>"); pattern = Pattern.compile("^Java.*"); matcher = pattern.matcher("JavaでHello World"); boolean b = matcher.matches(); System.out.println(b); /* 文字列の分割 */ System.out.println("<文字列の分割>"); pattern = Pattern.compile(" "); String[] strs = pattern.split("Java Hello World"); for (int i=0;i<strs.length;i++) { System.out.println(strs[i]); } /* 文字列の置換(最初にマッチしたもののみ) */ System.out.println("<文字列の置換(最初にマッチしたもののみ)>"); pattern = Pattern.compile("正規表現"); matcher = pattern.matcher("正規表現でHello World,正規表現でHello World"); System.out.println(matcher.replaceFirst("Java")); /* 文字列の置換(一括) */ System.out.println("<文字列の置換(一括)>"); pattern = Pattern.compile("正規表現"); matcher = pattern.matcher("正規表現でHello World,正規表現でHello World"); System.out.println(matcher.replaceAll("Java")); /* 文字列の置換(一つ一つ順々に) */ System.out.println("<文字列の置換(一つ一つ順々に)>"); pattern = Pattern.compile("正規表現"); matcher = pattern.matcher("正規表現でHello World,正規表現でHello World"); StringBuffer sb = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sb, "Java"); } matcher.appendTail(sb); System.out.println(sb.toString()); } }
<パターンマッチ> true <文字列の分割> Java Hello World Java Hello World <文字列の置換(最初にマッチしたもののみ)> JavaでHello World,正規表現でHello World <文字列の置換(一括)> JavaでHello World,JavaでHello World <文字列の置換(一つ一つ順々に)> JavaでHello World,JavaでHello World
Tomcat5 test on fedora5 AMD64 2006 12 19
[root@amd64 tmp]# mv /usr/share/tomcat5/webapps/bbs/WEB-INF/classes/articles.csv ./
[root@amd64 tmp]# cd /usr/share/tomcat5/webapps/bbs/WEB-INF/classes/ [root@amd64 classes]# /usr/java/jdk1.5.0_08/bin/javac -classpath /usr/share/java/servlet.jar:/usr/share/tomcat5/webapps/bbs/WEB-INF/lib/jakarta-commons-lang-2.0.jar BBS.java BBS.java
[ishida@amd64 ~]$ cat /usr/share/tomcat5/webapps/bbs/WEB-INF/web.xml <?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>BBS Example</display-name> <description> Small BBS Example </description>
<servlet> <servlet-name>BBSServlet</servlet-name> <servlet-class>BBS</servlet-class> </servlet>
<servlet-mapping> <servlet-name>BBSServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> [ishida@amd64 ~]$ cat /usr/share/tomcat5/webapps/bbs/WEB-INF/classes/BBS.java import java.io.*; import java.text.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import org.apache.commons.lang.StringEscapeUtils;
public class BBS extends HttpServlet {
/* * プロパティから取得するのが望ましいが、手抜きをして定数として定義 */ /* File.separator は UNIX 環境では "/"、Windows では "\" となる */ static final String ARTICLEFILE = File.separator + "tmp" + File.separator + "articles.csv"; // static final String ARTICLEFILE = "articles.csv"; /* 記事の最大数。これを超えた投稿があると古いものから削除される */ static final int MAXARTICLES = 100;
/* * GET リクエスト */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { doIt(request, response); }
/* * POST リクエスト */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { doIt(request, response); }
/* * POST/GET で処理はほとんど共通 */ public void doIt(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { /* 出力文字コード系を UTF-8 にする */ response.setContentType("text/html;charset=EUC-JP"); //response.setContentType("text/html;charset=UTF8"); /* 入力文字コード系も UTF-8 にする */ //request.setCharacterEncoding("UTF8"); request.setCharacterEncoding("EUC-JP"); /* PrintWriter の取得 */ PrintWriter out = response.getWriter(); /* HTML ヘッダ等の出力 */ printHTMLHeader(out); /* 記事保存用ファイルの作製 */ File articleFile = makeArticleFile(); if (request.getMethod().equals("POST")) { /* POST リクエスト時は、記事を追加 */ postArticle(out, request, articleFile); /* そうでなければ全て GET リクエストを仮定 (ホントは駄目) */ } /* 投稿用フォームを表示 */ printForm(out); /* 投稿された記事を表示 */ printArticles(out, articleFile); /* HTML フッタの表示 */ printHTMLFooter(out); }
/* * HTML のヘッダ部などの共通部分を出力 */ protected void printHTMLHeader(PrintWriter out) { out.println("<html>"); out.println("<head>"); out.println("<title>Java Servlet Sample BBS</title>"); out.println("</head>"); out.println("<body>"); }
/* * HTML のボティ部の閉じタグ等を出力 */ protected void printHTMLFooter(PrintWriter out) { out.println("</body>"); out.println("</html>"); }
protected synchronized void postArticle(PrintWriter out, HttpServletRequest r, File articleFile) throws IOException { int number; String[] articles = new String[MAXARTICLES];
/* 投稿された名前と本文をサニタイズする */ String name = StringEscapeUtils.escapeHtml(r.getParameter("name")); String text = StringEscapeUtils.escapeHtml(r.getParameter("text"));
/* 投稿された記事から改行コードとカンマを取り除く */ name = name.replaceAll("\r\n", ""); name = name.replaceAll("\n", ""); name = name.replaceAll(",", ","); name = name.trim(); text = text.replaceAll("\r\n", "<br>"); text = text.replaceAll("\n", "<br>"); /* 全ての記事をファイルから読みだす */ BufferedReader br = new BufferedReader(new FileReader(articleFile)); for (int i = 1; i < MAXARTICLES; i++) { if ((articles[i] = br.readLine()) == null) { break; } } br.close(); /* 最新の記事の番号を得る */ if (articles[1] == null) { number = 1; } else { number = Integer.parseInt(articles[1].split(",")[0]) + 1; } /* 先頭に投稿された記事を追加 */ articles[0] = number + "," + name + "," + text; /* 全ての記事をファイルに書き出す */ PrintWriter pw = new PrintWriter(new FileWriter(articleFile)); for (int i = 0; i <MAXARTICLES; i++) { if (articles[i] == null) { break; } else { pw.println(articles[i]); } } pw.close(); }
/* * 記事保存用ファイルオブジェクトの作製 * もしファイルが無ければここでファイルを作製する */ protected File makeArticleFile() throws IOException { File articleFile = new File(ARTICLEFILE); articleFile.createNewFile(); return articleFile; }
/* * 投稿用フォームの表示 */ protected void printForm(PrintWriter out) { out.println("<h1><center>Java サーブレット掲示板</center></h1>\n"); out.println("<form method=\"POST\" style=\"background-color: #d0f0ff; padding: 5pt\">"); out.println(" 名前:<input type=text name=\"name\"><br>"); out.println(" 本文:<textarea name=\"text\" cols=70 raws=4></textarea><br>"); out.println(" <input type=submit value=\"送信\">"); out.println("</form>"); }
/* * 記事の表示 */ protected synchronized void printArticles(PrintWriter out, File articleFile) throws IOException { String line;
BufferedReader br = new BufferedReader(new FileReader(articleFile)); for (int i = 0; i < MAXARTICLES; i++) { if ((line = br.readLine()) == null) { break; } else { String[] article = line.split(",", 3); out.println(article[0] + "名前:" + article[1] + "<br>"); out.println("<blockquote>"); out.println(article[2]); out.println("</blockquote>"); } } br.close(); } }
[Java on Linux] jvm は UTF8 以外ではエスケープを認めない 2006 12 19
[ishida@amd64 tmp]$ pwd /home/ishida/tmp 始めから UTF-8 で作成するか [ishida@amd64 tmp]$ cat test2.java public class test2{ public static void main(String []args){ public static void main(String []args){ System.out.println("ここにユニコード数値が表示される\"); } }; [ishida@amd64 tmp]$ [ishida@amd64 tmp]$ javac -encoding test2.java[UTF8] [ishida@amd64 tmp]$ java test2 こん"にちは(とユニコードで出力) [ishida@amd64 tmp]$
あるいは
[ishida@amd64 tmp]$ iconv -f EUC-JP -t UTF-8 < test.java > work/test.java [ishida@amd64 tmp]$ javac -encoding work/test.java[UTF-8] [ishida@amd64 tmp]$ cd work/ [ishida@amd64 work]$ java test こ"んにちは (とユニコードで出力) [ishida@amd64 work]$ cd ../
これについては http://www.asahi-net.or.jp/~wg5k-ickw/html/online/gcj-3.2.1/gcj-ja_3.html
Javaプログラミング言語では一貫してUnicodeが使われます。 gcjは、他のロケールも適切に統合することに努めていて、ほとんどすべてのエンコーディングを 使って`.java'ファイルを書くことができます。 gcjは、これらのエンコーディングをコンパイル 時に内部エンコーディングに変換する方法を知っています。 --encoding=NAMEオプションを使って、 ソースファイルにおいて使われている(特定の文字セットの)エンコーディングを指定することができます。 このオプションが指定されていないときは、その時点におけるカレントロケールがデフォルトの エンコーディングとなります。ホストシステムに十分なロケールサポートがない場合、 gcjは、デフォルトエンコーディングがUnicodeの`UTF-8'エンコーディングであるものと想定します。 --encodingを実装するために、 gcjは単に、ホストプラットフォームのiconv変換ルーチンを 使っているだけです。このことは、 gcjができることは、そのホストプラットフォームにできる範囲に 事実上限定されていることを意味しています。 --encodingの引数に指定することのできる名前は プラットフォームによって異なります (標準が存在しないからです)。しかし、 gcjは`UTF-8'という 名前のエンコーディングを内部的に実装していますので、ソースファイルにおいて このエンコーディングを使うことにすれば、すべてのホスト上で動作することが保証されます。
[Java on Linux] tomcat5 pc4041 に設置したBBS.java のコンパイル 2006 12 20
[root@pc4041 ~]# cd /usr/local/tomcat/webapps/bbs/WEB-INF/classes/ [root@pc4041 classes]# javac -cp /usr/local/tomcat/common/lib/servlet-api.jar:/usr/local/tomcat/webapps/bbs/WEB-INF/lib/commons-lang-2.2.jar BBS.java -encoding EUC-JP
[Java on Linux] Tomcat アプリケーションで jar を追加 2006 12 20
$CATALINA/common/lib webapps/program/WEB-INF/lib の両方に置く
なお pc4041 は jdk1-5 を自動解凍プログラムからインストールした後, alternatives で優先度を変え,
次に tomcat を始め,以下のホームページにしたがって mod_jk + workers.properties での接続を設定したが,
http://honana.com/cat_tomcat_55
後に mod_jk2 + workers2.propertiesでの接続に変更した.
http://kajuhome.com/tomcat5.shtml
ただし, 自動起動スクリプト (ただし chckconfig on は未実行) は前者にならっている.
最終的には以下を参考にした(/usr/local/tomcat/conf/workers.propertiesファイルの作成はまだ行っていない)
http://www.ayaori.net/software/osx/tomcat5Primer/step05.htm
[Java on Linux] Java における static キーワード 2006 12 29
オブジェクト指向言語では、データ(フィールド)とそのデータを処理するコード(メソッド) を一塊にして考えています。例えば、MyClassというクラスがあった時にそのオブジェクト (JAVAではインスタンスと言ったかな?)を用意する宣言は
MyClass dt1 , dt2 , dt3; dt1 = new MyClass(); dt2 = new MyClass(); dt3 = new MyClass();
のように宣言します。この時、3個のインスタンス(MyClassの実体)をメモリ上に用意した ことになります。
MyClassには、例えばdataというフィールドがあったとします(public扱いとします)。
dt1.data = 10; dt2.data = 20; dt3.data = 30;
のように使えます。つまり、メモリ上には各々異なる場所に、dataのフィールドを記憶する 3個の領域が取られるわけですね。
次にMyClassには、例えばmethodという引数なしのpublicのメソッドがあり、何か処理した 後に、関数値はdataフィールドの値を返すものとしましょう。 ret = dt1.method(); //10が得られる ret = dt2.method(); //20が得られる ret = dt3.method(); //30が得られる
さてここで、問題があります。
methodメソッドは、何か処理するプログラムです(機械語コードと考えてもいいです)。 このプログラム部分も、メモリ上にインスタンスの個数分だけ用意しますか?
常識から考えて、3個も同じプログラムを用意するバカなシステムはありません。MS-DOSの ようにプログラム実行時に自分自身を書き換える恐ろしいプログラムはJAVAにはありません ので、当然methodメソッドのコードはメモリ上に1個あって、それをみんなで使えば十分です。
class MyClass { public int data; public int method() { 何かの処理 return data; } }
さて、次に理解して欲しいことは、上のMyClassをコンパイラが翻訳する時の不思議さ(トリック) です。
JAVAやC++などでは、クラス単位でコンパイル出来ますね。上のクラスをコンパイルする時 のdataフィールドは、どこに用意されるのでしょうか?
上の話でもわかるように、フィールドはインスタンスの個数分だけ用意されます。 ということは、クラスをコンパイルする時にはdataフィールドをメモリに取ることは、ちょっと無理だ と思いませんか? プログラム実行時に何個インスタンスが必要になるかは、クラス側のプログラムでは知る方法は ありません。 つまり、このクラスのインスタンス(実体)を宣言したプログラムが、フィールドの記憶場所を用意 するわけです。 では、このクラスをコンパイルする時に、どうして、フィールドの記憶場所がわかるのでしょうか?
また、同じように、methodメソッドの機械語?コードは、メモリ上に1個しかないのに、どうして複 数個のインスタンスを正しく相手出来るのでしょうか?なぜ、正しくインスタンスのdataフィールドを 識別できるのでしょうか?
この答えが、JAVAでいう this です(C++では、thisポインタと言うやつです)
JAVAではC言語でいうポインタが無くなってしまったのでポインタという語句を入れて解説して はいけないのですが、要するに、プログラムをコンパイルする時に、コンパイラがメソッドの引数 の中に、インスタンス自身のポインタ(記憶場所)を入れているのです!! この操作は暗黙のうちに行われるので、メソッドの引数に追加されていることを意識しませんが、 たまたまメソッドの中で、this キーワードを使うと、このthisが、実質的にはインスタンス自身の ポインタ(メモリの記憶場所)を表しています。
つまりJAVAで dt1.method(); をC言語的に書けば method( &dt1 ); のような感じです。メソッドの コンパイル時に、オブジェクト自身のアドレスが一番最初の引数にあるとしてコンパイルされます。 (C++では、一番最初の引数に、オブジェクト自身のアドレスが渡されますがJAVAも似たように思えます)。 引数があるメソッド dt1.method2( x ); は、 method2( &dt1 , x ); のような感じです。
このことによって、メソッドのコードは、次のようになるはずです。 [java] [C言語風] int method(){ int method( MyClass *tp ) { 何か処理 何か処理 return data; return tp->data; } }
~~~~~~~~~~~~~ staticメソッドの解説です
staticメソッドは、引数に、このthisが渡されない特別なメソッドである
と考えて下さい。メソッドの宣言にstaticをつけると、コンパイラがプログラムをコンパイルする時に、 暗黙に追加していたインスタンスのアドレスを渡さなくなります。 となると、このstaticメソッドの中では、thisが渡らなくなるので、クラスのインスタンス(実体)で用意 されたフィールドを一切触ることが出来ないわけです。記憶場所を知る手段がないのです。
public class CBug { int field; public static void main( String argv[] ) { field = 0; } }
fieldを触っていますが、このfieldは、クラスのインスタンス(実体)ごとにメモリに取られます。しかし mainメソッドがstaticなため、このようなことは出来ません。 ですから CBug.java:7: Can't make a static reference to nonstatic variable field in class CBug. field = 0; ^ 1 error というエラーが出てしまうのです。
同じような理屈から、staticメソッドの中で呼び出せるメソッドは、staticなメソッドに限られるわけです。
以上の話から、staticなメソッドの中で触ることが出来るフィールド(変数)は、インスタンスに関係の ないものに限られます。そうです。フィールド宣言を行う時に、staticを付けたものに限り、操作する ことが出来ます。 JAVAでいう、クラス変数っていうやつです。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ では、なぜクラス変数が必要なのでしょうか? 同じクラスのインスタンス全体を通して、何か管理をする変数が時には必要になります。 例えば、今何個のインスタンスがメモリの中に存在するか知りたい場合などです。 また、クラス特有の定数を宣言する時にも有ると便利です。例えば、円のクラスを考える時の円周率 は、インスタンスすべてに共通です。final static 宣言を行う、staticです。
クラス変数やクラスメソッドは、クラスに関係するため、インスタンスの名前ではなく、クラス名を付けて 表現することができます。MyClass.field のように、左側がクラス名です。
次のプログラムを実行すれば、staticキーワードが理解出来るでしょう
// //static keyword Test // public class CTest { public static void main( String argv[] ) { CSt dt1; dt1 = new CSt(); System.out.println( "Object cnt=" + dt1.getcnt() ); CSt dt2; dt2 = new CSt(); System.out.println( "Object cnt=" + CSt.getcnt() ); // ClassName.method
CSt.cnt_static = 0; // ClassName.Field CSt dt3; dt3 = new CSt(); System.out.println( "Object cnt=" + CSt.getcnt() ); show(); // static method } static void show() { System.out.println( "show cnt=" + CSt.getcnt() ); CSt.cnt_static = 0; System.out.println( "show cnt=" + CSt.getcnt() ); } }
class CSt { static int cnt_static = 0; CSt() { cnt_static++; } public static int getcnt() { return cnt_static; } }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[Java on Linux] JFrame, JButton, ActionListener? の実装例 2006 12 29
import java.awt.BorderLayout; import java.awt.Container; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JPanel;
public class TextAreaGui extends JFrame{
/** * @param args */
JButton sendButton; JTextArea textArea; public TextAreaGui(){ setSize(400,300); setDefaultCloseOperation(EXIT_ON_CLOSE);
/* addWindowListener(new WindowAdapter(){ public void windowClosing (WindowEvent e){ System.exit(0); } }); */
textArea = new JTextArea(10,35); textArea.setLineWrap(true); textArea.setEditable(true); sendButton = new JButton("転送"); JScrollPane scrollPane = new JScrollPane(textArea); MyJPanelButton myJPanelButton = new MyJPanelButton(); Container c = getContentPane(); c.setLayout(new BorderLayout()); c.add(scrollPane, BorderLayout.CENTER); c.add(myJPanelButton, BorderLayout.NORTH); myJPanelButton.add(sendButton); sendButton.addActionListener(myJPanelButton); // Button オブジェクトのイベントを処理するオブジェクトを登録する } class MyJPanelButton extends JPanel implements ActionListener{ public void actionPerformed(ActionEvent e ){ String s = textArea.getText(); //textArea.setEditable(true); System.out.println(s); } } public static void main(String[] args) { // TODO Auto-generated method stub Frame w = new TextAreaGui(); w.setVisible(true);
//w.show();//非推奨 deprecated
}
}
CVS
CVS 2007 03 31
まず当該プロジェクトの収まったディレクトリで
[ishida@amd64 hoge]$ cd newporject [ishida@amd64newporject] cvs import -m "project" newproject vendorTag start
[ishida@amd64newporject] cd ../
[ishida@amd64 hoge]$rm -Rf newproject
[ishida@amd64 hoge]$ cvs checkout newproject
ファイルを追加したら
[ishida@amd64 hoge]$ cvs add addedFileName
リポジトリの最新内容 (他人が修正済かもしれない) を作業コピーに反映させる
[ishida@amd64 hoge]$ cvs update modifiedFile
自分の作業コピー内容をレポジトリに反映させる
[ishida@amd64 hoge]$ cvs commit modifiedFile
http://www.gfd-dennou.org/library/cc-env/cvs/
150.59.60.47 にリポジトリを作成
150.59.60.47 で [ishida@pc1047 ~]$ export CVSROOT=/home/ishida/CVS [ishida@pc1047 ~]$ cvs -d /home/ishida/CVS init ishida@pc1047 CVS]$ pwd /home/ishida/CVS [ishida@pc1047 CVS]$ mkdir springer
local で [ishida@amd64 ~]$ export CVSROOT=:ext:150.59.60.47:/home/ishida/CVS [ishida@amd64 ~]$ export EDITOR=vi [ishida@amd64 ~]$ vi ~/.cvsrc $HOME/.cvsrc に書くもの cvs -q diff -u up -dP
最初は,モジュールの中身は空なので,クライアントからインポートします. インポートしたいファイルのあるディレクトリを,$CLIENT_WORK_DIR とします. $ cd $CLIENT_WORK_DIR $ cvs import -m 'initial' dir1/module1 semblog_org initial
チェックアウトする
[ishida@pc1047 CVS]$ mkdir DasGeheimnis [ishida@pc1047 CVS]$ pwd /home/ishida/CVS [ishida@pc1047 CVS]$ ls CVSROOT DasGeheimnis everitt
[ishida@amd64 work]$ pwd /home/ishida/tmp/work
[ishida@amd64 work]$ cvs import -m 'Das Geheimnis des kuerzestedn Weges' DasGeheimnis DasGeheimnis initial Enter passphrase for key '/home/ishida/.ssh/id_rsa':
...
[ishida@amd64 ~]$ cd research/Tex/paper/springer/Gritzmann/ [ishida@amd64 Gritzmann]$ ls original_pdf work_old [ishida@amd64 Gritzmann]$
[ishida@amd64 work]$ cvs import -m 'gritzmann' springer/gritzmann gritzmann initial [ishida@amd64 work]$ ssh -l ishida 150.59.60.47 Enter passphrase for key '/home/ishida/.ssh/id_rsa': Last login: Mon Mar 26 11:25:18 2007 from 150.59.18.67 [ishida@pc1047 ~]$ cd CVS/springer/ [ishida@pc1047 springer]$ ls gritzmann [ishida@pc1047 springer]$ cd gritzmann/ [ishida@pc1047 gritzmann]$ ls chapter0.tex,v chapter05.tex,v main.bbl,v main.log,v note.txt,v chapter01.tex,v chapter06.tex,v main.blg,v main.lot,v preface.tex,v chapter02.tex,v chapter07.tex,v main.dvi,v main.pdf,v svtbk13.clo,v chapter03.tex,v chapter08.tex,v main.idx,v main.tex,v svtbook.cls,v chapter04.tex,v main.aux,v main.lof,v main.toc,v
[ishida@amd64 Gritzmann]$ pwd /home/ishida/research/Tex/paper/springer/Gritzmann [ishida@amd64 Gritzmann]$ mv -f work work_old [ishida@amd64 Gritzmann]$ ls original_pdf work_old
[ishida@pc1047 CVS]$ mkdir everitt [ishida@pc1047 CVS]$ ls CVSROOT everitt springer test [ishida@pc1047 CVS]$
[ishida@amd64 everitt]$ cvs import -m 'everitt' everitt everitt initial Enter passphrase for key '/home/ishida/.ssh/id_rsa':
No conflicts created by this import
インポートしたら,チェックアウトします. チェックアウト先のディレクトリが,今後の作業ディレクトリとなります. なお,インポートに使用したディレクトリは,そのまま使えないので退避します.
$ cd $CLIENT_WORK_DIR/../ $ mv -f $CLIENT_WORK_DIR ${CLIENT_WORK_DIR}_old # とりあえず,名前を変えておく $ mkdir $CLIENT_WORK_DIR # 新しく,作業用ディレクトリを用意 $ cvs co -d $CLIENT_WORK_DIR dir1/module1 # 作業ディレクトリにチェックアウト
作業ディレクトリの下のすべてのディレクトリに,CVS/ というディレクトリができているはずです.
[ishida@amd64 ~]$ cd research/Tex/paper/springer/Gritzmann/ [ishida@amd64 Gritzmann]$ ls original_pdf work_old [ishida@amd64 Gritzmann]$ cvs checkout DasGeheimnis Enter passphrase for key '/home/ishida/.ssh/id_rsa':
...
[ishida@amd64 Gritzmann]$ ls DasGeheimnis original_pdf work_old
[ishida@amd64 Gritzmann]$ cvs checkout springer/gritzmann Enter passphrase for key '/home/ishida/.ssh/id_rsa':
[ishida@amd64 Gritzmann]$ ls original_pdf springer work_old [ishida@amd64 Gritzmann]$ cd springer/gritzmann/ [ishida@amd64 gritzmann]$ ls CVS chapter04.tex main.aux main.lof main.toc chapter0.tex chapter05.tex main.bbl main.log note.txt chapter01.tex chapter06.tex main.blg main.lot preface.tex chapter02.tex chapter07.tex main.dvi main.pdf svtbk13.clo chapter03.tex chapter08.tex main.idx main.tex svtbook.cls
[ishida@amd64 Everitt]$ pwd /home/ishida/research/Tex/paper/springer/Everitt [ishida@amd64 Everitt]$ mv everitt everitt_old
[ishida@amd64 Everitt]$ cvs checkout everitt Enter passphrase for key '/home/ishida/.ssh/id_rsa':
U everitt/svtbook.cls [ishida@amd64 Everitt]$
[ishida@amd64 work]$ ssh -l ishida 150.59.60.47 Enter passphrase for key '/home/ishida/.ssh/id_rsa': Last login: Mon Mar 26 11:53:00 2007 from 150.59.18.67 [ishida@pc1047 ~]$ cd CVS/ [ishida@pc1047 CVS]$ ls CVSROOT everitt test [ishida@pc1047 CVS]$ rm -Rf test
RSA 認証の接続確認 ssh-agent を起動
ローカルで X を起動し, ssh-agent の後ろにターミナルを起動のコマンド (xterm, kterm, rxvt 等) をくっつけて ssh-agent な (?) ターミナルを起動する
$ ssh-agent kterm
ssh-add による認証
そのターミナル上で以下のコマンドを入力する.
$ ssh-add
すでにターミナルが起動しているなら ishida@@ ishida$ eval `ssh-agent -s` ; ssh-add
すると, 秘密鍵, 公開鍵作りで入力したパスフレーズを聞かれるので入力する.
Enter passphrase for /home/hero/.ssh/id_dsa: [先ほどのパスフレーズ] (認証されたら) Identity added: /home/hero/.ssh/id_dsa (/home/hero/.ssh/id_dsa)
認証
認証後は, そのウィンドウ上, もしくはそのウィンドウ上から起動したソフトウェアからなら, ノンパスでログインが可能となる. 既に起動後のターミナルから ssh-add で認証を行ないたい場合 [ishida@amd64 Gritzmann]$ ssh-add Enter passphrase for /home/ishida/.ssh/id_rsa: Bad passphrase, try again for /home/ishida/.ssh/id_rsa: Identity added: /home/ishida/.ssh/id_rsa (/home/ishida/.ssh/id_rsa) Identity added: /home/ishida/.ssh/id_dsa (/home/ishida/.ssh/id_dsa) Identity added: /home/ishida/.ssh/identity (ishida@server) [ishida@amd64 Gritzmann]$ emacs & [1] 4222 [ishida@amd64 Gritzmann]$
プロジェクトを削除する場合には,以下の作業で削除するとよい.
$ cvs release -d "ディレクトリ名" ふんたらかんたら yes
[ishida@amd64 tmp]$ cvs release -d "test" Enter passphrase for key '/home/ishida/.ssh/id_rsa': Enter passphrase for key '/home/ishida/.ssh/id_rsa': You have [0] altered files in this repository. Are you sure you want to release (and delete) directory `test': yes
CVSで
cvs -n update -d 2> /dev/null
とかやって、コンフリクトが発生することがわかったら、
C hoge/foo.txt ↑ 例えば、hoge/foo.txtでコンフリクトが発生する時は、 こんな様に表示されると思う。
cvs diff hoge/foo.txt > /tmp/cvslog
上のように入力して、どこか別のファイルに差分を書き出して、 (この例では、/tmp/cvslog に書き出すことにする。)
vim /hoge/foo.txt
vimエディタで /hoge/foo.txt ファイルを開いてから、 (この例では、hoge/foo.txt でコンフリクトが発生したと仮定する。)
:diffpatch /tmp/cvslog
:diffpatchコマンドで、先ほど生成したパッチを取り込んで、 違いを表示、2つのウィンドウを比べながらマージする。
http://www.ne.jp/asahi/hishidama/home/tech/cvs/usage.html
qkc を利用して,UNIX 用に変換する 2007 03 29
文字コードおよび改行コードを変更するには, qkc もしくは nkf の 2.0 以降を --overwrite オプション付きで使います.
qkc を利用して,UNIX 用に変換するには以下のようにします.
$ qkc -u -e <ファイル名>
qkc を利用して,Windows 用に変換するには以下のようにします.
$ qkc -m -s <ファイル名>
[CVS 2] 古いファイルを復活させる方法
一時的に古いファイルを復活させる方法
一時的に古いファイルの内容を復活させ、必要なくなったら元(最新版)に戻すことが出来る。
$ cvs log ファイル ←リビジョン番号の確認 $ cvs update -r リビジョン ファイル
こうすると、ファイルがそのリビジョンの内容に置き換わる。 そして、そのファイルにはstickyというオプションだかフラグだかラベルだかが貼り付けられる。これが「このファイルは古いバージョンだよ」という情報になる。 stickyが付いている間は、そのファイルを修正してもコミットできなくなる。
元に戻すには、以下のコマンドを実行する。(これにより、stickyが外れる)
$ cvs update -A ファイル U ファイル
なお、stickyが付いているかどうかはstatusで確認できる。
一時的にではなく 古いファイルを復活させるには、一旦古いファイルの内容を取り出し、新しい修正としてコミットするしかない。 (人間から見て古いバージョンであっても、CVSから見れば「一度確定(コミット)されている以上、内容が古くなったとしても新しいバージョンである」という思想)
$ cvs log ファイル ←リビジョン番号の確認 $ cvs update -r リビジョン ファイル $ mv ファイル ファイル~ ←別名で退避させると同時に、ファイルを消す $ cvs update -A ファイル U ファイル ←ファイルが復活する $ mv ファイル~ ファイル ←古い内容で上書きする $ cvs update ←あとは普通に更新・コミット M ファイル $ cvs commit
途中で「cvs update -A」とするのがポイント。単なる「cvs update」だと、(statusで見れば分かる通り)古いソースがそのまま取得されるだけでstickyが解除されないので、コミットすることが出来ない。
[perl 6]ディレクトリからファイルを読み込み行列を作る 2007 06 14
/home/ishida/research/Tex/paper/p2006/Altmann/altmann.results.pl
#!/usr/bin/perl
open(OUT, ">/home/ishida/research/Tex/paper/p2006/Altmann/goodness/results.csv");
opendir(DIR, "/home/ishida/research/Tex/paper/p2006/Altmann/goodness");#goodness @file = readdir(DIR); closedir(DIR);
foreach $target (@file) { next if( $target =~ /^\./ or $target =~ /^result/); open(IN, "/home/ishida/research/Tex/paper/p2006/Altmann/goodness/$target") or die "cant access $target\n"; while($each_row = <IN>){ chomp($each_row); $each_row =~ s/ //g; if($first == 0 and $each_row =~ /^Distribution/){ next; } elsif($each_row =~ /^(\S+)\t(\S+)\t(\S+)\t(\S+)\t(\S+)\t(\S+)/){ ## print $each_row."\n"; $dist{$1} = 0;# "$2\t\$3\t$4\t$5\t$6"; } } close(IN); }
print OUT "\t"; foreach $key (sort keys %dist){ print OUT $key."\t"; } print OUT "\n";
######### noch mal ########
foreach $target (@file) { next if( $target =~ /^\./ or $target =~ /^result/); open(IN, "/home/ishida/research/Tex/paper/p2006/Altmann/goodness/$target") or die "cant access $target\n"; print OUT "$target\t"; while($each_row = <IN>){ chomp($each_row); $each_row =~ s/ //g;
if($each_row =~ /^Distribution/){ next; } elsif($each_row =~ /^(\S+)\t(\S+)\t(\S+)\t(\S+)\t(\S+)\t(\S+)/){ if(exists $dist{$1}){ $dist{$1} = "$2,$3,$4,$5,$6"; } else{ $dist{$1} = "NA"; } } } foreach $key (sort keys %dist){ print OUT $dist{$key}."\t"; $dist{$key} = "NA"; } print OUT "\n"; }
close(OUT);
[c++] ヘッダファイルとライブラリの場所 2007 07 10
cc がデフォルトで検索するヘッダファイルとライブラリの場所は、 以下のコマンドで確認することが出来ます。
gcc -print-search-dirs
確認していないので分かりませんが、まあ、基本的には (gcc のインストール先)/include:/usr/include だと思います。
他のディレクトリにインストールされているヘッダファイルを検索するためには -I または -I- オプションを指定する必要があります。 (-I- オプションを使っているところは見たことがありません)
(ex.1) ヘッダファイルが /usr/local/include に存在する場合
gcc -I/usr/local/include ...
(ex.2) ヘッダファイルが /usr/local/include と /opt/app/include に存在する場合
gcc -I/usr/local/include -I/opt/app/include ...
> gccとccの違いも知りたいです。
Unix では gcc と cc は全く別物ですが、Linux では cc が gcc へのシンボリックリンク またはハードリンクとして作成されていることがほとんどなので、 基本的には同じと考えて問題ありません。
茶筅の C プログラム 2007 07 10
// コンパイル方法 gcc prog.c -lchasen -lstdc++ #include <stdio.h> #include "chasen.h" int main () { char *res; res = chasen_sparse_tostr("食べさせられなかった"); printf("%s\n", res); return 0; }
[perl 7] 日本語を対象とした Perl 正規表現 2007 07 11
#!/usr/bin/perl $str = 'これはテストです'; $pattern = '好'; if ($str =~ /$pattern/) { print "マッチした\n"; } if($str =~ /^(w)/){ print $1."\n"; } if($str =~ /([\x21-\x3B\x3D\x3F-\x7E])/){ print $1."\n"; } if($str =~ /^([\x80-\xFF])([\x80-\xFF])/){ print $1.$2."\n"; } $eng = "this is a pen"; if($eng =~ /^(\w)/){ print $1."\n"; } ~ [ishida@amd64 Perl]$ ./test.pl マッチした こ t
[perl 8] Perl で UTF-8 文字コードを使って正規表現<
#!/usr/bin/perl
use encoding 'utf8'; $hoge = "ほげ"; print length(hoge); print "\n"; for $i (split//,$hoge){ print $i, "\n"; }
if($hoge =~ /^(\w)(\w)/){ print "1 = $1 2 = $2 \n"; }
print utf8::is_utf8($hoge) ? 'utf 8\n' : 'not utf 8 \n';
[ishida@amd64 tmp]$ export LANG=ja_JP.UTF-8 ちなみにこの時,コンソールのメニュー設定も変更すること
[ishida@amd64 tmp]$ ./utf8.pl 4 ほ げ 1 = ほ 2 = げ utf 8\n[ishida@amd64 tmp]$
euc-jpだと反応しない
#!/usr/bin/perl
$hoge = "ほげ"; if($hoge =~ /(\w)(\w)/){ print "1 = $1 2 = $2\n"; }
ファイルを読み込む必要があるなら #!/usr/bin/perl
use encoding 'utf8'; #open(IN, "kumo.csv"); #$test = "これはテストです"; # print $test."\n";
open(IN, "<:utf8", "chasenUTF8.txt"); $count = 0; while($w = <IN>){ chomp; # print $w; if($w =~ /^(\w+)\s+(\w+)\s+(\w+)\s+(\w+)/){ # print $4."\n"; # $test = $4; if($4 =~ /^名詞/){ $count++; print "count = $count : $4\n"; } } } close(IN);
perl 5.8からは、utf8を内部コードに採用しているようなので、全部utf-8で書くと、 日本語の正規表現も普通に使えます。 頭に、 use Encode; use Encode::Guess qw/utf8 euc-jp shiftjis 7bit-jis/; use open ":utf8"; binmode ":utf8"; binmode STDOUT, ":utf8"; use utf8; をつけて、そのスクリプト自体や扱うファイルなどをすべてutf8にします。 これで、open文を介してアクセスするファイルなどの文字コードは気にしなくて良くなり、 日本語の正規表現も使えます。「use encoding 'utf8';」は、併用すると相性が悪いです。 open以外の、SQLとのやりとりなどでは自動変換してくれないので、 $str = Encode::decode('utf8',$str); とやって、内部コードにデコードします。 この場合は、utf-8の部分が文字コードで、$strは、読み込んだ文字列です。 もし、コードが分からない場合は、"Guess" とすると、 「Encode::Guess qw/utf8 euc-jp shiftjis 7bit-jis/;」で指定した文字コードを順番に試してくれます。 しかし、なぜか UTF-16LEやUTF-32LEなど、指定していないコードだと誤判別することがあります。 原因は分かりません。しかも、このままだと、正規表現を行ったときに内部関数で暴走してしまいます。 この場合、signalで割り込んでも反応せず、KILLするしかありません。 デバッガにも帰ってこないので、最悪のバグです。 エンコードは、ご察しの通り、 $str = Encode::encode('utf8',$str); です。 メールに送るときはJISなので、 $str = Encode::encode('7bit-jis',$str); としてJISに変換してからsendmailなりに渡します。
Cannot load the example native code. java.library.path への対処 2007 08 20
Cannot load the example native code. Make sure your LD_LIBRARY_PATH contains '.' java.lang.UnsatisfiedLinkError: no MeCab in java.library.path
It means your applicaton missing some libraries. For eclipse, you can do follow this. 1. Add "-Djava.library.path=<path of missing libraries>" to Eclipse -> "Run" menu -> "Run" submenu -> "Arguments" tab -> "VM arguments" text field. Or: 2. First add the path of native libraries to $PATH, then restart eclipse, eclipse should find them under $PATH.
すなわち su で ldconfig を実行して,インストールしたライブラリを認識させる
[Java on Linux] mecab ライブラリエラー 2007 08 20
[Linux] MeCabのjavaバインディング
mecab-javaのMakeは成功するも、よく分からないエラー(Can't load IA 32-bit .so on a IA 32-bit platform)が。。(参考ページ)
[tf0054@localhost mecab-java-0.96]$ make test env LD_LIBRARY_PATH=. /usr/java/jdk1.5.0_12/bin/java test Cannot load the example native code. Make sure your LD_LIBRARY_PATH contains '.' java.lang.UnsatisfiedLinkError: /home/tf0054/mecab-java-0.96/libMeCab.so: Can't load IA 32-bit .so on a IA 32-bit platform make: *** [test] Error 1 [tf0054@localhost mecab-java-0.96]$
でも、よく調べると普通にライブラリがロードできていないだけだった(LD_LIBRARY_PATHで解決)。 なんかjavaって、いつもこんな風な分かり難いラーを返す気がします。。
[tf0054@localhost mecab-java-0.96]$ ldd libMeCab.so linux-gate.so.1 => (0xffffe000) libmecab.so.1 => not found libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7f0a000) libm.so.6 => /lib/libm.so.6 (0xb7ee1000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7ed5000) libc.so.6 => /lib/libc.so.6 (0xb7d80000) /lib/ld-linux.so.2 (0x80000000) [tf0054@localhost mecab-java-0.96]$
coLinuxだから?、MeCabはsunのJVMで動かそうとしていて、 でもGCJ(GNU Compiler for the Java)も入ってるからこんがらがってんの?等々結構はまったのでメモ。
そのほかのエラー
http://lists.sourceforge.jp/mailman/archives/mecab-devel/2007-July/000066.html
すなわち su で ldconfig を実行して,インストールしたライブラリを認識させる
char *) data, "=&"