以下の様な、検索の為に使う半角→全角変換ソフト
(最終的には、検索に埋め込む関数にする予定)を作ってます。
環境は、WinXP SP3 TurboDelphi2006(無償版)です。
(ただ、Delphi3(OS:VistaビジネスSP1)でも使うことを前提に作ってます。)
半角→全角は問題無く動くまで出来たのですが、
全角を入力すると、s2{中身・} := sp^[i2{中身1}]{中身あ};
の部分が誤作動して、文字化けがおきてしまいます。
なので、全角文字を一文字ずつ識別して、
そこだけ変換せずにスルーする方法を探しています。
今の所、一文字づつ全角文字を抽出する方法が判らず、
立ち往生しています。
何か良い方法は無いでしょうか?
お知恵をお貸し頂けると助かります。
それではよろしくお願いしますm(__)m。
var
Form1: TForm1;
PS: pchar;
//...省略
function allocpchar(s: string): pchar;
begin
ps := stralloc(length(s) + 1);
allocpchar := strpcopy(ps, s);
end;
//...省略
procedure TForm1.Button1Click(Sender: TObject);
var
i1,i2,i3,i4:integer;
s1,s2,s3,s4,s5:string;
sp:^string;
begin
i1 := length(edit1.Text) + 1;
s1 := edit1.Text;
sp := @s1;
s4 := '';
i2 := 1;
i3 := 0;
i4 := Ord('ン');
while i1 > i2 do begin
s2 := sp^[i2];
while i4 > i3 do begin
s3 := allocpchar(char(i3));
case sp^[i2] of
'0': s5 := '0';
'1': s5 := '1';
'2': s5 := '2';
'3': s5 := '3';
'4': s5 := '4';
'5': s5 := '5';
'6': s5 := '6';
'7': s5 := '7';
'8': s5 := '8';
'9': s5 := '9';
//...省略
end;
if s2 = s3 then begin
s4 := s4 + s5;
edit1.text := s4;
end;
i3 := i3 + 1;
end;
i2 := i2 + 1;
i3 := 0;
end;
end;
発想の転換でこんなのは如何でしょうか?
[半角を全角に変換する]
http://www.wwlnk.com/boheme/delphi/tips/tec1310.htm
どうしても自前でやりたければ、SysUtils.LeadBytes変数を使って、
if (s[i] in LeadBytes) then
のように、漢字の1バイト目かどうかを判断しながら処理を行うといいと思います。
自前でやる場合の一つの案ということで。
文字列をWideStringで扱うとマルチバイトの1バイト目かどうかというような判断をする必要がなくて楽です。
procedure Form1.Button1Click(Sender: TObject);
var
i: Integer;
ls_Src: WideString;
begin
ls_Src := WideString(Edit1.Text);
for i := 1 to Length(ls_Src) do begin
case (ls_Src[i]) of
'0': ls_Src[i] := WideString('0')[1];
'1': ls_Src[i] := WideString('1')[1];
'2': ls_Src[i] := WideString('2')[1];
'3': ls_Src[i] := WideString('3')[1];
'4': ls_Src[i] := WideString('4')[1];
'5': ls_Src[i] := WideString('5')[1];
'6': ls_Src[i] := WideString('6')[1];
'7': ls_Src[i] := WideString('7')[1];
'8': ls_Src[i] := WideString('8')[1];
'9': ls_Src[i] := WideString('9')[1];
//...省略
end;
end;
Edit1.Text := ls_Src;
end;
この場合、いちいちWideStringでキャストして添え字をつけないといけないのがわずらわしですが。
あと、LCMapStringは'\'だけは全角に変換されないのでLCMapStringで変換後さらにStringReplaceなどを使って'\'を'¥'に変換しないとなりません。
https://www.petitmonte.com/bbs/answers?question_id=5611
> 自前でやる場合の一つの案ということで。
> 文字列をWideStringで扱うとマルチバイトの1バイト目かどうかというような判断をする必要がなくて楽です。
そうですね。ラウンドトリップ問題を無視できる場合にはDさんの方法が楽でいいです。
[Ansi->Unicode->Ansi変換をやっちゃ駄目ってどういう事?]
http://homepage1.nifty.com/ht_deko/tech013.html#tech039_20
DEKOさん、Dさんありがとうございます。
PCのセットアップが落ち着いたので、レスにきました。
驚くほど短い文の方法があるんですね。
凄い勉強になります。
Dさんの方法も、とても参考になります。
Delphi3での動作も問題なく、色々使えそうです。
一日で解決するとは思いませんでした。
困った時はAPIですね^^。
Vistaの件と変換の件、本当にありがとうございましたm(__)m。
明日早速関数にして組み込みたいと思います。
DEKOさんDさん、重ねてありがとうございました。
参考までにお聞きしたいのですが、
http://www.wwlnk.com/boheme/delphi/tips/tec1310.htm
の方法って、「¥」の全角、半角切り替えがうまくいかないように思えます。
これを含めて置換できる方法って何かありましたっけ?
自分では「AnsiPos」で「¥」を見つけて全角半角入れ代えをやってます。
> これを含めて置換できる方法って何かありましたっけ?
Dさんが仰っていたように、LCMapString 後に
S := Stringreplace(S, '\', '¥', [rfReplAll]);
すればいいと思います。
誤: S := Stringreplace(S, '\', '¥', [rfReplAll]);
正: S := Stringreplace(S, '\', '¥', [rfReplaceAll]);
皆さんありがとうございます、
>S := Stringreplace(S, '\', '¥', [rfReplaceAll]);
を改良していくと、全角→半角にも出来そうなので、
そちらの方も作りはじめました。
試しで一文字目の変換が成功した所です。
Dさんの方法も参考にしながら、
この調子で組み上げていきたいです。
半角→全角はDEKOさんのおかげで簡単に成功しました。
改めてありがとうございました。
自己レスです。
procedure TForm1.Button3Click(Sender: TObject);
var
s,s2:string;
i:integer;
begin
s := edit3.Text;
s2 := '';
for i := 1 to Length(s) do begin
if (s[i] in LeadBytes) then begin
if s[i] + s[i+1] = '0' then begin
s2 := s2 + '0';
if (s[i+2] in LeadBytes) then begin
//s2 := s2 +s[i+2]+s[i+3];
end else begin
s2 := s2 + s[i+2];
end;
end;
if s[i] + s[i+1] = '1' then begin
s2 := s2 + '1';
if (s[i+2] in LeadBytes) then begin
//s2 := s2 +s[i+2]+s[i+3];
end else begin
s2 := s2 + s[i+2];
end;
end;
//...省略
end;
end;
edit3.Text := s2;
end;
全角→半角変換の試作も無事、出来ました。
あとはコピー&ペーストしながら文字を登録して、出来たら移植用に仕上げるだけです。
ほぼ全部何とかなりました。
ありがとうございましたm(__)m。
老婆心ながら、、。
わかっててやってるのだったらごめんなさい。
>全角→半角変換の試作も無事、出来ました。
>あとはコピー&ペーストしながら文字を登録して、出来たら移植用に仕上げるだけです。
LCMapString APIは半角を全角にするだけでなく、全角を半角にすることもできます。
それだけでなく大文字⇔小文字、ひらがな⇔カタカナなどの変換もできます。
他にもエンディアンの変換など色々できるようです。
http://msdn.microsoft.com/ja-jp/library/cc448052.aspx
>Dさん
情報ありがとうございます、
助かります^^。
全く知りませんでした^^;
半角→全角だけだと思っていました。
使っている市販の業務用請求書ソフトに、そのような機能があり、
それに近づけたいと思っていました。
どうやって変換してるのだろう?と興味津々でしたが、
APIにそういう機能があったのですね^^;
そうとも知らず、昨日は上のを書いた後、
動作を調べたら案の定バグバグで苦労してました^^;
リンクもありがとうございます、
早速APIの参考書と一緒に早速調べてみます(API超初心者です^^;)。
ありがとうございました。
参考にしてください。
APIをラップした関数群やAPIに依存しない変換を行っています。
>Fusaさん
情報ありがとうございます。
早速見てみたのですが、自分のスキルを大幅に超えていて、
全然判りませんでした^^;
でも貴重な情報ありがとうございましたm(__)m。
学習を兼ねて、切り貼りしながら参考にしてみたいと思います。
ツイート | ![]() |