Shift-jis⇔2進数 ができる関数

解決


シロウ斗  2009-10-15 14:37:01  No: 35888

仮に、

「た」  ⇔  「01001001」みたいに相互変換する方法か、もしくは関数が知りたいです。

2進数、という呼び方でいいのかもわからない素人ですけど、要は0と1のstring型で戻り値が欲しいのです。

どなたかお願いします。


Ru  2009-10-15 19:04:46  No: 35889

一発変換はないと思います。
下記で文字→2進数はできました。逆は調べていません。
あと考え方間違ってればどなたかつっこみお願いします。
※「た」  をいれると  1000001010111101  が帰ってきます。

文字→16進数
https://www.petitmonte.com/bbs/answers?question_id=6468

16進数→10進数
IntToStr関数
※変換したい16進数に $ を付けてください。

10進数→2進数
http://www2.big.or.jp/~osamu/Delphi/tips.cgi?index=0225.txt


シロウ斗  2009-10-16 02:05:16  No: 35890

この方のサイトに16進数を2進数にする関数がありまして、これによりますと、私もRuさんと同じく、「た」は1000001010111101となりました。

http://www.tanaka-software.jp/tips-d003.php

ここで、1000001010111101から16進数にするには、上記サイトのBinToHex関数を使わせてもらうとして、今度は16進数から文字列に戻す方法でいきづまっている所です。
文字列を16進数にする方法はWeb上で多く見られるのですが、逆はなかなか見つかりません。
テーブル引き?  になるんでしょうか?

いわば、HexToString関数のようなものがあればいいのですが、ググってもPHP用のしかみつけられませんでした。

キャストしたりする方法はないんでしょうか?


ttt  2009-10-16 02:23:02  No: 35891

16進→数値: 頭に'$'を付けてStrToIntとかValとか
数値→文字: Chr
2バイト文字だと上位と下位に分けて変換してからくっつける必要があるかも。
(分けるのはシフト演算使ってもいいですが、Lo, Hi で手軽にできます)


totonica  2009-10-16 04:33:16  No: 35892

こんにちは。

以下のような物でどうでしょうか?

function StrToBin(S: String): String;
var
  i: Integer;
  Buf: String;
  ii: Integer;
begin
  //SJIS -> 2進数
  Result := '';
  for i := 1 to Length(S) do
  begin
    SetLength(Buf,8);
    for ii := 8 downto 1 do
    begin
      Buf[ii] := IntToStr((Ord(S[i]) shr (8-ii)) mod 2)[1];
    end;
    Result := Result + Buf;
  end;
end;

function BinToStr(S: String): String;
var
  i: Integer;
  Buf: Byte;
begin
  //2進数 -> SJIS
  Result := '';
  Buf := 0;
  if Length(S) mod 8 = 0 then
  begin
    for i := 1 to Length(S) do
    begin
      if i mod 8 = 1 then Buf := 0;

      if S[i] = #$31 then
      begin
        if i mod 8 = 0 then
        begin
          Buf := Buf + 1;
        end
        else
        begin
          Buf := Buf + Trunc(Power(2,8 - (i mod 8)));
        end;
      end;

      if i mod 8 = 0 then Result := Result + AnsiChar(Buf);
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  S,BS: String;
begin
  //使用例
  S := 'た';
  BS := StrToBin(S);
  ShowMessage(BS);//1000001010111101
  ShowMessage(BinToStr(BS));//た
end;

D2007までのDelphiを前提にしています。
D2009以降だと確実にコケます。
2進数 -> SJIS変換は途中に余計な文字があるとコケます。
(スペース等がある場合は事前にStringReplace等で取り除いてください)


monaa  2009-10-16 05:28:56  No: 35893

では私はUnicode対応という事で、守備範囲はD6-D2010です。
こういうの見るとムラムラするんですよね。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Edit2: TEdit;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//文字列を二進数文字列に--------------------------------------------------------
function ByteToStr(b:Byte):Char; begin
  if b=0 then Result := '0' else Result := '1';
end;
function WordToBinStr(w:Word; b:Byte):WideString;
var i: Integer;
begin
  SetLength(Result,b);
  for i := 1 to b do
    Result[i] := ByteToStr(Byte((w shr (b-i)) and $1));
end;
function WideCharToBinStr(wc:WideChar):WideString;
begin //WideCharは16bit = UNICODE
  Result := WordToBinStr(Word(wc),SizeOf(wc)*8);
end;
function AnsiCharToBinStr(ac:AnsiChar):WideString;
begin //AnsiCharは8bit = Shift-JIS
  Result := WordToBinStr(Word(ac),SizeOf(ac)*8);
end;
function WideStringToBinStr(wStr:WideString):WideString;
var i:Integer;
begin
  for i := 1 to Length(wStr) do
    Result := Result + WideCharToBinStr(wStr[i]);
end;
function AnsiStringToBinStr(aStr:AnsiString):WideString;
var i:Integer;
begin
  for i := 1 to Length(aStr) do
    Result := Result + AnsiCharToBinStr(aStr[i]);
end;
//二進数文字列を文字列に--------------------------------------------------------
function BinAnsiCharToWord(var bChar:AnsiChar):Word; begin
  if bChar='1' then Result := 1 else Result := 0;
end;
function BinWideCharToWord(var bChar:WideChar):Word; begin
  if bChar='1' then Result := 1 else Result := 0;
end;
function BinChar8ToChar(var ptChar:PAnsiChar):AnsiChar;
var
  bSize : Byte;
  i: Integer;
  w: Word;
begin
  w := 0;
  bSize := SizeOf(AnsiChar)*8;
  for i := 0 to bSize - 1 do
  begin
    w := (w Shl 1) or BinAnsiCharToWord(ptChar^);
    inc(ptChar);
  end;
  Result := AnsiChar(w);
end;
function BinChar16ToChar(var ptChar:PWideChar):WideChar;
var
  bSize : Byte;
  i: Integer;
  w: Word;
begin
  w := 0;
  bSize := SizeOf(WideChar)*8;
  for i := 0 to bSize - 1 do
  begin
    w := (w Shl 1) or BinWideCharToWord(Char(ptChar^));
    inc(ptChar);
  end;
  Result := WideChar(w);
end;
function Bin8StrToString(str:AnsiString):AnsiString;
var
  ptChar:PAnsiChar;
begin
  ptChar  := @str[1];
  repeat
    Result := Result + BinChar8ToChar(ptChar);
  until ptChar^=Char(0);
end;
function Bin16StrToString(str:WideString):WideString;
var
  ptChar:PWideChar;
begin
  ptChar  := @str[1];
  repeat
    Result := Result + BinChar16ToChar(ptChar);
  until ptChar^=Char(0);
end;
//------------------------------------------------------------------------------
//汎用関数
//Shift-JIS -> 2進数文字列
function ShiftJISToBinStr(str:string):string;begin
  Result := AnsiStringToBinStr(str);
end;
//2進数文字列 -> Shift-JIS
function BinStrToShiftJIS(str:string):string;begin
  Result := Bin8StrToString(str);
end;
//Unicode -> 2進数文字列
function UnicodeToBinStr(str:string):string;begin
  Result := WideStringToBinStr(str);
end;
//2進数文字列 -> Unicode
function BinStrToUnicode(str:string):string;begin
  Result := Bin16StrToString(str);
end;
//------------------------------------------------------------------------------
//用例
procedure TForm1.Button1Click(Sender: TObject);
begin
  //Shift-JIS -> 2進数文字列
  Edit2.Text := ShiftJISToBinStr(Edit1.Text);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
  //2進数文字列 -> Shift-JIS
  Edit1.Text := BinStrToShiftJIS(Edit2.Text);
end;

end.

ご覧の通り最適化の余地はふんだんにあります、
可読性を重視しました。


totonica  URL  2009-10-16 07:21:28  No: 35894

こんにちは。

2進数 -> SJISを修正しました。
Mathユニットが不要になります。

function BinToStr(S: String): String;
var
  i: Integer;
  Buf: Byte;
begin
  //2進数 -> SJIS
  Result := '';
  Buf := 0;
  if Length(S) mod 8 = 0 then
  begin
    for i := 1 to Length(S) do
    begin
      if i mod 8 = 1 then Buf := 0;

      if S[i] = #$31 then
      begin
        if i mod 8 = 0 then
        begin
          Buf := Buf + 1;
        end
        else
        begin
          Buf := Buf + 1 shl (8 - (i mod 8));
        end;
      end;

      if i mod 8 = 0 then Result := Result + AnsiChar(Buf);
    end;
  end;
end;


シロウ斗  2009-10-17 00:56:37  No: 35895

ありがとうございます。

ベテランの方々のおかげで大変、充実した資料を得ることができました。
と、同時にすごく勉強になりました。

一発で変換できる関数まで示してくれたので大変たすかります。

重ねてありがとうございます。


シロウ斗  2009-10-17 00:57:20  No: 35896

解決の入れ忘れです…。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加