这段程序错在哪里?(5分)

  • 主题发起人 主题发起人 programsky
  • 开始时间 开始时间
P

programsky

Unregistered / Unconfirmed
GUEST, unregistred user!
在字符表'1','2','3'上,生成一个由该字符表上的字符组成、含n个字符的序列,但要求生
成的序列中没有两个相邻子序列是相同的,(Pascal)
程序及注解:
program ed;{最严重的问题大于15的数没有输出}
var a:array[1..1000]of integer;n:integer;
function pd(m,nw:integer):boolean;{判断条件是否成立,其中nw是试验值是为函数设计的,开始没有设计这个参数}
var i,j{循环变量},k{检验是否全相等},temp{临时存放实验值所放位置的原数}:integer;p:boolean;
begin
i:=1;temp:=a[m];
a[m]:=nw;
repeat
p:=true;
k:=0;
for j:=1 to ido
if a[m-j+1]=a[m-j-i+1] then
k:=k+1;
if k=i then
p:=false;
i:=i+1;
until (i*2>n)or(p=false);
pd:=p;
a[m]:=temp;
end;
function max(m:integer):integer;
var i1:integer;{测试值}p1:boolean;{暂时保存测试结果}
begin
p1:=false;i1:=3;
repeat
p1:=pd(m,i1);
if p1 then
max:=i1;
i1:=i1-1;
until p1;
end;
proceduredo
ing;
var i2,j2:integer;p2:boolean;{i2是当前值的指针}
begin
i2:=1;
while (i2<>0) and (a[i2]<>4){这个判断可能有问题}do
begin
a[i2]:=a[i2]+1;
if pd(i2,a[i2]) then
begin
if i2<n then
begin
i2:=i2+1;
a[i2]:=0;
end
else
begin
p2:=true;
for j2:=1 to ndo
{去除含有4的错误结果}
if a[j2]=4 then
p2:=false;
if p2 then
begin
for j2:=1 to ndo
write(a[j2]);
writeln;
end;
while a[i2]>=max(i2)do
i2:=i2-1;
end;
end;
end;
end;
begin
readln(n);
doing;
readln;
end.
按照开始的想法程序的结果中是不该出现4的,但后来不得不筛掉4.
 
begin
i:=1;temp:=a[m];
a[m]:=nw;
repeat
p:=true;
k:=0;
for j:=1 to ido
if a[m-j+1]=a[m-j-i+1] then
k:=k+1;
if k=i then
p:=false;
i:=i+1;
until (i*2>n)or(p=false);
pd:=p;
a[m]:=temp;
end;
这段程序不论输入什么,a[m]一定没有变呀。再说,j和i多于了。用一个就行。
 
这段程序只是一个判断,具体操作不在这里进行。
 
在字符表'1','2','3'上,生成一个由该字符表上的字符组成、含n个字符的序列,但要求生
成的序列中没有两个相邻子序列是相同的,(Pascal)
没看明白。要求的是一个‘序列’?比如字符表为从1..20,N=3
那么123,234,456都是符合要求的序列?
你要的是不是全排列?
 
如n=4,答案为
1213
1231
1232
1312
1321
1323
2123
2131
2132
2312
2313
2321
3121
3123
3132
3212
3213
3231
 
并不是说这个序列是有序序列
 
搞定,我没看你的程序,自已写了一个以供参考,可以自定义"字符表"及要找的数字的位数,
关键在于判断数字内两个相邻子序列不能相同比较难办,我想到的方法可能不是最好的,但肯
定是有效的,下面代码在Wind2000+D6下运行通过.....................................
不过,说句实话,你给的分也太少了,我就是照书敲这么长的代码也不只值这5分啊...:)
const
SA: array of String;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
GetNumbers('123', 4);
end;

//GetNumbers:得到符体条件的数字
//s:字符表,如'123'
//iLen:要得到的数字的位数,如:4位数
procedure TForm1.GetNumbers(s: string;
iLen: integer);
var
i, j, k, h, isLen, iMinLen, iMaxLen:integer;
slStr: TStrings;
sTmp, s0, s1: string;
bIn: boolean;
begin
slStr := TStringList.Create;
isLen := Length(s);
SetLength(SA, isLen);
for i := 1 to isLendo
//取到单个字符
SA[i - 1] := s;
iMinLen := GetMinNumber(iLen);
//位数的最小值
iMaxLen := GetMaxNumber(iLen);
//位数的最大值
for i := iMinLen to iMaxLendo
begin
bIn := True;
sTmp := IntToStr(i);
for j := 1 to iLendo
if not ChkIns(sTmp[j]) then
//判断数字是否以s中的字符组合而来的?
begin
bIn := False;
Break;
end;
if not bIn then
Continue;
{两个相邻子序列是否相同?}
h := Round(iLen / 2);
for j := 1 to hdo
begin
s0 := Trim(Copy(sTmp, 1, j));
for k := 1 to Length(sTmp)do
begin
s1 := Trim(Copy(sTmp, 1 + k * j, j));
if Length(s1) < Length(s0) then
Break;
//说明已经到了字符串尾了,不用比较了,退出
if s0 = s1 then
begin
bIn := False;
Break;
end
else
s0 := s1;
end;
if not bIn then
Break;
end;
if not bIn then
Continue;
slStr.Add(IntToStr(i));
end;
Showmessage(slStr.Text);
//显示得到的数字
// ListBox1.Clear;
// ListBox1.Items.Assign(slStr);
slStr.Free;
end;

//检测数字的每个字符是否包含在"字符表"中
function TForm1.ChkInS(str: string):boolean;
var
i : integer;
begin
Result := False;
for i := 0 to High(SA)do
if str = SA then
begin
Result := True;
Break;
end;
end;

//得到iLen位数的最大值,如:4位数最大值为9999
function TForm1.GetMaxNumber(iLen: integer): Longint;
const
s = '9';
var
i : integer;
sRst: String;
begin
Result := 0;
if iLen = 0 then
Exit;
sRst := '';
for i := 0 to iLen - 1do
sRst := sRst + s;
Result := StrToInt(sRst);
end;

//得到iLen位数的最小值,如:4位数最大值为1000
function TForm1.GetMinNumber(iLen: integer): Longint;
var
i : integer;
begin
Result := 1;
for i := 1 to iLen - 1do
Result := Result * 10;
end;
 
最好不要用整型做,范围太小了。
 
那你只要改一下类型就行了,根据你的所需自已改嘛,我提供的是一种算法!
var
iMinLen, iMaxLen:longint;
//主要是改这两个变量的类型
 
var SA:array of char;
 
var SA:string;也可以,
你领会了题目的意思,在
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1228615
领取50分奖励。
 
做记号先,明早来看。
 
to programsky:
你说的对,直接定义sa为字符串(string) 就行了,string本身就是一个数组,写程序时考虑的
不够细,你自已改改吧,还有范围的问题,把下面这句变量定义改写:
var
i, j, k, h, isLen, iMinLen, iMaxLen:integer;
改成:
var
i, iMinLen, iMaxLen: longint;//你想取更大范围的话只要将这里的类型改成更大范围的就行了
j, k, h, isLen: integer;
 
刚才又试了一下,将SA定义成 SA:String;发现不是很好用,下面这段代码会出错,必须修改,
所以建议定义成 SA: array of char;
这样其它地方都不需要更改了。
//检测数字的每个字符是否包含在"字符表"中
function TForm1.ChkInS(str: string):boolean;
var
i : integer;
begin
Result := False;
for i := 0 to High(SA)do
{这里会出错}
//for i := 1 to Length(SA)do
{我改成这样也不行,程序会没反应}
if str = SA then
begin
Result := True;
Break;
end;
end;
 
str的类型也要改
 
一个char的数组和一个char是不会相等的。
 
我发现问题了,现把改过的源程序贴在下面。
program ed;{最严重的问题大于15的数没有输出}
var a:array[1..1000]of integer;n:integer;
function pd(m,nw:integer):boolean;{判断条件是否成立,其中nw是试验值是为函数设计的,开始没有设计这个参数}
var i,j{循环变量},k{检验是否全相等},temp{临时存放实验值所放位置的原数}:integer;p:boolean;
begin
i:=1;temp:=a[m];
a[m]:=nw;
repeat
p:=true;
k:=0;
for j:=1 to ido
if a[m-j+1]=a[m-j-i+1] then
k:=k+1;
if k=i then
p:=false;
i:=i+1;
until (i*2>n)or(p=false);
pd:=p;
a[m]:=temp;
end;
function max(m:integer):integer;
var i1:integer;{测试值}p1:boolean;{暂时保存测试结果}
begin
p1:=false;i1:=3;
repeat
p1:=pd(m,i1);
if p1 then
max:=i1;
i1:=i1-1;
until p1;
end;
proceduredo
ing;
var i2,j2:integer;p2:boolean;{i2是当前值的指针}
begin
i2:=1;
while i2<>0{的确是这个判断出的问题问题因为后面已经筛掉四了所以判断条件很不必要}do
begin
a[i2]:=a[i2]+1;
if pd(i2,a[i2]) then
begin
if i2<n then
begin
i2:=i2+1;
a[i2]:=0;
end
else
begin
p2:=true;
for j2:=1 to ndo
{去除含有4的错误结果}
if a[j2]=4 then
p2:=false;
if p2 then
begin
for j2:=1 to ndo
write(a[j2]);
writeln;
end;
while a[i2]>=max(i2)do
i2:=i2-1;
end;
end;
end;
end;
begin
readln(n);
doing;
readln;
end.
还是思考不够严密。造成重复。
 
多人接受答案了。
 
后退
顶部