kidneyball大侠请进,昨天的那个函数问题,其他人就不要来了,谢谢.(50分)

  • 主题发起人 主题发起人 m911
  • 开始时间 开始时间
M

m911

Unregistered / Unconfirmed
GUEST, unregistred user!
还是昨天的那个函数的问题, 都怪我没说明白
我需要的是从某组开始替换,结果我说成了从某位开始替换
比如
const
MaxGroup = 10; //最大组数
CharMap : array[1..MaxGroup, 1..2] of string[16] =
(('FE98BA54761032DC', '89EFCD23016745AB'),
('543210FEDCBA9876', 'DCBA9876543210FE')
..................
);
[red] 我想对整个串字符从上面任意一组开始循环替换 该怎么改下面的代码?[/red]

const
MaxGroup = 10; //最大组数
CharMap : array[1..MaxGroup, 1..2] of string[16] = //改变MaxGroup时需要同时改变转换表定义
(('FE98BA54761032DC', '89EFCD23016745AB'),
('543210FEDCBA9876', 'DCBA9876543210FE'),
('SD354DSF6SD53F4S', 'S38D4FSD35F4S3DF'),
('54DF354DFG354G3D', 'SDF354SD32S1FDSD'),
('35SD4F4DS5FSD3FG', '2354SDF35DSF3DS5'),
('357DSF351SDF354S', '0254AS1SD534SDF4'),
('124S412SDF54SDED', '354SDF345SDF4DS5'),
('354S53F4SFD34SDS', '358435S1DF35SFDS'),
('3584S35DF1DS35F4', 'TR354GF354HGF54G'),
('834S35F4SD54FEEE', '35XDV354SDF35SD4')
);

var
Form1: TForm1;
CharMappingTable : array[1..MaxGroup, 1..2, 48..122] of char;

implementation

{$R *.dfm}

procedure MakeTable; //建立映射表,只需在开始运行一次,转换期间不用运行
var i, j, k : integer;
begin
for i := 1 to MaxGroup do
for j := 1 to 2 do
for k := 1 to 16 do
begin
if (k<=6) then
begin
CharMappingTable[i,j,byte('a')-1+k] := CharMap[i,j,k];
CharMappingTable[i,j,byte('A')-1+k] := CharMap[i,j,k];
end
else CharMappingTable[i,j,k-7+byte('0')] := CharMap[i,j,k]
end;
end;

procedure Convert(var s : string); //为了照顾效率, 采用直接写变量参数的的做法. 最后结果在传入的参数中
var i, k : integer;
begin
//MakeTable; //建立映射表
//因已在Form.OnCreate建立了映射表, 这里不用重复建立
i := 1; //字符指针
k := 1; //当前用的转换表组号
while i <= length(s) do
begin
s := CharMappingTable[k, 1 , Byte(s)];
inc(i); //指向第二个字符, 若s符合格式, 必定不会出界
s := CharMappingTable[k, 2, Byte(s)];
inc(i,2); //跳过空格, 到下一组第一个字符
if k < MaxGroup then inc(k) else k:=1;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var s : string;
begin
//转换
s := self.cmbSource.Text;
Convert(s);
self.memResult.Text := s;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
MakeTable; //建立全局映射表

//初始化调试数据
self.cmbSource.Items.Add('62 C7 2C A2 92 0E DC 85 98 EE 63 C6 2D A3 93 0F DD 84 99 EF 60 C5 2E A0 90 0C DE 87 9A EC 61 C4 2F A1 91');
self.cmbSource.ItemIndex := 0;
end;



另外可以顺便问个问题吗?
象这样的去掉空格的步骤 怎样做成函数?
var
str:string;
index,j:integer;
begin
str:='12 23 56 54 12 85 68';
j:=length(str);
while j>0 do
begin
index:=pos(' ',str);
delete(str,index,1);
j:=j-1;

kidneyball 大侠 我的分不多啦,还有N多问题要问,所以出了50分,请谅解! 谢谢
 
这样吧, 我把Convert部分改一下, 现在可以接收三个参数: 第一个是要转换的字符串.第二个是在源串中起始的组号, 默认为1. 第三个是对指定的组号匹配的映射表号,默认为1.

例如, 你要对测试数据中的2C, 用第3组转换表开始转换, 就Convert(s, 2, 3). 注意这时2C之前的部分不作变动. 如果你确实只需要从源串中第一组开始转换, 可以把Convert中关于StartSourceGroup的部分删掉. 把
i := (StartSourceGroup-1) * 3 + 1; //字符指针 3为每组(连分隔符)字符数 ******
这句改为 i := 1;就行了

unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
cmbSource: TComboBox; //在Form上放个ComboBox作为输入
memResult: TMemo; //在Form上放个Memo作为输出
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject); //在Form上放个按钮触发运算
private
{ Private declarations }
public
{ Public declarations }
end;

const
MaxGroup = 10; //最大组数
CharMap : array[1..MaxGroup, 1..2] of string[16] = //改变MaxGroup时需要同时改变转换表定义
(('FE98BA54761032DC', '89EFCD23016745AB'),
('543210FEDCBA9876', 'DCBA9876543210FE'),
('SD354DSF6SD53F4S', 'S38D4FSD35F4S3DF'),
('54DF354DFG354G3D', 'SDF354SD32S1FDSD'),
('35SD4F4DS5FSD3FG', '2354SDF35DSF3DS5'),
('357DSF351SDF354S', '0254AS1SD534SDF4'),
('124S412SDF54SDED', '354SDF345SDF4DS5'),
('354S53F4SFD34SDS', '358435S1DF35SFDS'),
('3584S35DF1DS35F4', 'TR354GF354HGF54G'),
('834S35F4SD54FEEE', '35XDV354SDF35SD4')
);

var
Form1: TForm1;
CharMappingTable : array[1..MaxGroup, 1..2, 48..122] of char;

implementation

{$R *.dfm}

procedure MakeTable; //建立映射表,只需在开始运行一次,转换期间不用运行
var i, j, k : integer;
begin
for i := 1 to MaxGroup do
for j := 1 to 2 do
for k := 1 to 16 do
begin
if (k<=6) then //k<=6时,映射源对应A-F 或 a-f
begin
CharMappingTable[i,j,byte('a')-1+k] := CharMap[i,j,k]; //建立a-f映射表
CharMappingTable[i,j,byte('A')-1+k] := CharMap[i,j,k]; //建立A-F映射
end
else CharMappingTable[i,j,k-7+byte('0')] := CharMap[i,j,k] //建立0-9映射
end;
end;

procedure Convert(var s : string;
StartSourceGroup : integer = 1;
StartMappingTable : integer = 1);
{ StartSourceGroup 指定从源串中第几组开始转换
StartMappingTable 指定使用第几组映射表去转换StartSourceGroup位置的串。
并对后续的各源串,用递增超界循环的方式匹配映射表进行转换
}
var i, k : integer;
begin
if StartSourceGroup < 1 then Exit; //起始位置超界
if (StartMappingTable < 1) or (StartMappingTable > MaxGroup) then Exit; //防止起始映射表号超界
if (length(s) mod 3) = 1 then s := s + ' '; //若s长度会造成算法中下标超界,则调整s的长度 (错位的空格会被映射为#0)

i := (StartSourceGroup-1) * 3 + 1; //字符指针 3为每组(连分隔符)字符数 ******
k := StartMappingTable; //当前用的转换表组号 ******
while i <= length(s) do
begin
s := CharMappingTable[k, 1 , Byte(s)];
inc(i); //指向第二个字符, 若s符合格式, 必定不会出界
s := CharMappingTable[k, 2, Byte(s)];
inc(i,2); //跳过空格, 到下一组第一个字符
if k < MaxGroup then inc(k) else k:=1;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var s : string;
begin
//转换
s := self.cmbSource.Text;
Convert(s);
self.memResult.Text := s;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
MakeTable; //建立全局映射表

//初始化调试数据
self.cmbSource.Items.Add('62 C7 2C A2 92 0E DC 85 98 EE 63 C6 2D A3 93 0F DD 84 99 EF 60 C5 2E A0 90 0C DE 87 9A EC 61 C4 2F A1 91');
self.cmbSource.ItemIndex := 0;
end;

end.
 
关于第二个问题? 没看太懂, 象你这样delete就可以了呀. 套个function...begin...end就没问题了. 不过这样顺序delete其实很慢, 因为每次delete都要把后面的字符复制上来. 这里提供个改良版, 用直接在传入参数上修改的方法:

procedure RemoveSpaces(var s : string);
var WritePos, ReadPos : integer;
begin
WritePos := 1;
for ReadPos := 1 to length(s) do
if s[ReadPos] <> ' ' then
begin
s[WritePos] := s[ReadPos];
inc(WritePos);
end;
SetLength(s, WritePos - 1);
end;
 
大哥 你太厉害了啊! 两个问题都一次性解决! 厉害啊!
 
谢谢你啊 !!!! 加分
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
687
import
I
I
回复
0
查看
843
import
I
I
回复
0
查看
763
import
I
后退
顶部