在 Pascal 中比较两个字符串的许多方法对我不起作用
Many ways of comparing two strings in pascal doesn't work for me
我在 Pascal
上做作业。除了尝试比较两个字符串以检查游戏是否完成之外,我几乎完成了所有事情。但是当我在 guess
过程中比较它们时,即使 encryption
字符串已经与 theWord
字符串相同,它也始终为假。我不太明白 Pascal 是如何处理字符串的。然后,我尝试在 main
中比较它们,输出 true
。我真的很困惑。我试了SameStr
、CompareText
、=
,结果都是一样的
代码:
program hangman;
Uses sysutils;
const
times = 6;
var
theWordSize,i : integer;
theWord,encryption : string;
function encrypt (): string;
var
list : string;
begin
for i := 1 to theWordSize do
list[i] := '*';
encrypt := list;
end;
procedure reveal(letter: char);
begin
for i := 1 to theWordSize do
if (theWord[i] = letter) then
encryption[i] := theWord[i];
end;
procedure guess();
var
letter : char;
j : integer;
begin
writeln('hello');
j := times;
while (j > 0) do
begin
writeln('Guess a letter( ':16, j:1, ' times left ): ':15);
readln(letter);
if pos(letter,theWord)<>0 then // guess correctly
begin
reveal(letter);
writeln('Correct! Word: ':15, encryption:7);
writeln(SameText(theWord,encryption));
if SameText(theWord,encryption) then
begin
writeln('You win! The correct word: ':28, theWord:7);
exit
end;
inc(j)
end
else if (j > 1) then // guess wrong
writeln('Wrong! Word: ':15, encryption:7)
else
writeln('You lose! The man is dead. Correct Word: ':43, theWord:7);
dec(j)
end
end;
{* Main program: *}
begin
theWord := 'mystery';
theWordSize := byte(theWord[0]);
//writeln(theWord[i]=='m');
writeln('Weclome to Hangman game:');
encryption := encrypt();
writeln('Mystery Word: ':14, encryption:theWordSize);
guess();
for i := 0 to theWordSize do
encryption[i] := theWord[i];
writeln(SameText(theWord,encryption));
end.
部分 运行 结果:
Guess a letter( 6 times left ):
e
Correct! Word: m*ste**
FALSE
Guess a letter( 6 times left ):
r
Correct! Word: m*ster*
FALSE
Guess a letter( 6 times left ):
y
Correct! Word: mystery
FALSE
Guess a letter( 6 times left ):
a
Wrong! Word: mystery
Guess a letter( 5 times left ):
a
Wrong! Word: mystery
Guess a letter( 4 times left ):
a
Wrong! Word: mystery
Guess a letter( 3 times left ):
a
Wrong! Word: mystery
Guess a letter( 2 times left ):
a
Wrong! Word: mystery
Guess a letter( 1 times left ):
a
You lose! The man is dead. Correct Word: mystery
TRUE
SO 有一种荣誉准则,即涉及作业时,我们不
只告诉你答案。因此,我将向您展示使用 Lazarus 的方法
调试器自己找出问题的原因。问题是,像 fpc 这样的编译器如果不能正确地进行字符串比较就不会存活很长时间,所以像 SameText 这样的函数失败的原因一定是因为你正在比较的字符串实际上并不相等。问题是 "why not?",找出调试的全部内容。
如果您还没有安装 Lazarus,请立即安装并在其中打开您的项目。如果,
第一次在其中编译 Hangman 时出现错误
Hangman.lpr(64,56) Error: Element zero of an ansi/wide- or longstring cannot be accessed, use (set)length instead
那是因为 Lazarus 假设您使用的是所谓的 "Huge strings",它
大小可达 2Gb,而您显然打算使用传统
Pascal "ShortStrings" 是最多 255 个字符的数组,前面有一个长度字节。
要强制 Lazarus 使用 ShortStrings,添加
$mode objfpc}{$H-}
就在`程序 Hangman 的下方。另外,当你在做的时候,改变
theWordSize := byte(theWord[0]);
到
theWordSize := Length(theWord);
因为不管 HugeStrings 还是 ShortStrings 都会起作用
没有关于字符串内部结构的假设。
下一步我要将设置 theWord
的行更改为
theWord := 'm'; //'mystery';
以尽量减少调试期间的输入量。然后,放一个调试器
行上的断点
if SameText(theWord,encryption) then
通过在装订线的左边缘附近单击(具有源代码行号的区域
在里面)。
编译并运行程序,一旦控制台window出现,输入
mReturn
完成后,调试器将在断点处停止。按F8
单步执行调试器,您会发现它转到
inc(J);
很明显 SameText
失败了,这就是你用 q 进来的地方。毫无意义
继续使用当前的 运行 应用程序,因此请按 Ctrl-F7 终止它并重置调试器。
再次运行 app,仔细看
行执行结果
writeln('Mystery Word: ':14, encryption:theWordSize);
你会注意到它没有显示任何值
encryption
。这是出了什么问题的重要线索。 'm'你
输入没有错,所以 encryption
不能有相同的值。唯一的
剩下要做的就是找出它实际具有的价值。请注意
如果您尝试使用 F7 计算 encryption
,它会显示空白,
不是您期望的星号。
下一位,在行上打断点
for i := 1 to theWordSize do
在encrypt
函数中,将代码window拖到屏幕右侧。然后,按
打开Watches
window,如有必要,将其拖入space,通过移动代码window释放,并在其中输入以下表达式
list[0]
和
list[1]
这是为了让您能够观察到列表的长度字节和第一个字符中的值。
运行 应用程序直到 encrypte
断点,然后单步绕过
for
循环。你会发现
的值
list[0]
不会改变,即使 list[1]
的值已设置为 'm'。
所以,encrypt
返回的是一个空字符串,QED,我相信你会意识到
如何修复它。对不起,如果这已经相当累人,但至少它应该
让您了解如何系统地调试您 运行 遇到的下一个问题。
我在 Pascal
上做作业。除了尝试比较两个字符串以检查游戏是否完成之外,我几乎完成了所有事情。但是当我在 guess
过程中比较它们时,即使 encryption
字符串已经与 theWord
字符串相同,它也始终为假。我不太明白 Pascal 是如何处理字符串的。然后,我尝试在 main
中比较它们,输出 true
。我真的很困惑。我试了SameStr
、CompareText
、=
,结果都是一样的
代码:
program hangman;
Uses sysutils;
const
times = 6;
var
theWordSize,i : integer;
theWord,encryption : string;
function encrypt (): string;
var
list : string;
begin
for i := 1 to theWordSize do
list[i] := '*';
encrypt := list;
end;
procedure reveal(letter: char);
begin
for i := 1 to theWordSize do
if (theWord[i] = letter) then
encryption[i] := theWord[i];
end;
procedure guess();
var
letter : char;
j : integer;
begin
writeln('hello');
j := times;
while (j > 0) do
begin
writeln('Guess a letter( ':16, j:1, ' times left ): ':15);
readln(letter);
if pos(letter,theWord)<>0 then // guess correctly
begin
reveal(letter);
writeln('Correct! Word: ':15, encryption:7);
writeln(SameText(theWord,encryption));
if SameText(theWord,encryption) then
begin
writeln('You win! The correct word: ':28, theWord:7);
exit
end;
inc(j)
end
else if (j > 1) then // guess wrong
writeln('Wrong! Word: ':15, encryption:7)
else
writeln('You lose! The man is dead. Correct Word: ':43, theWord:7);
dec(j)
end
end;
{* Main program: *}
begin
theWord := 'mystery';
theWordSize := byte(theWord[0]);
//writeln(theWord[i]=='m');
writeln('Weclome to Hangman game:');
encryption := encrypt();
writeln('Mystery Word: ':14, encryption:theWordSize);
guess();
for i := 0 to theWordSize do
encryption[i] := theWord[i];
writeln(SameText(theWord,encryption));
end.
部分 运行 结果:
Guess a letter( 6 times left ):
e
Correct! Word: m*ste**
FALSE
Guess a letter( 6 times left ):
r
Correct! Word: m*ster*
FALSE
Guess a letter( 6 times left ):
y
Correct! Word: mystery
FALSE
Guess a letter( 6 times left ):
a
Wrong! Word: mystery
Guess a letter( 5 times left ):
a
Wrong! Word: mystery
Guess a letter( 4 times left ):
a
Wrong! Word: mystery
Guess a letter( 3 times left ):
a
Wrong! Word: mystery
Guess a letter( 2 times left ):
a
Wrong! Word: mystery
Guess a letter( 1 times left ):
a
You lose! The man is dead. Correct Word: mystery
TRUE
SO 有一种荣誉准则,即涉及作业时,我们不 只告诉你答案。因此,我将向您展示使用 Lazarus 的方法 调试器自己找出问题的原因。问题是,像 fpc 这样的编译器如果不能正确地进行字符串比较就不会存活很长时间,所以像 SameText 这样的函数失败的原因一定是因为你正在比较的字符串实际上并不相等。问题是 "why not?",找出调试的全部内容。
如果您还没有安装 Lazarus,请立即安装并在其中打开您的项目。如果, 第一次在其中编译 Hangman 时出现错误
Hangman.lpr(64,56) Error: Element zero of an ansi/wide- or longstring cannot be accessed, use (set)length instead
那是因为 Lazarus 假设您使用的是所谓的 "Huge strings",它 大小可达 2Gb,而您显然打算使用传统 Pascal "ShortStrings" 是最多 255 个字符的数组,前面有一个长度字节。
要强制 Lazarus 使用 ShortStrings,添加
$mode objfpc}{$H-}
就在`程序 Hangman 的下方。另外,当你在做的时候,改变
theWordSize := byte(theWord[0]);
到
theWordSize := Length(theWord);
因为不管 HugeStrings 还是 ShortStrings 都会起作用 没有关于字符串内部结构的假设。
下一步我要将设置 theWord
的行更改为
theWord := 'm'; //'mystery';
以尽量减少调试期间的输入量。然后,放一个调试器 行上的断点
if SameText(theWord,encryption) then
通过在装订线的左边缘附近单击(具有源代码行号的区域 在里面)。
编译并运行程序,一旦控制台window出现,输入
mReturn
完成后,调试器将在断点处停止。按F8 单步执行调试器,您会发现它转到
inc(J);
很明显 SameText
失败了,这就是你用 q 进来的地方。毫无意义
继续使用当前的 运行 应用程序,因此请按 Ctrl-F7 终止它并重置调试器。
运行 app,仔细看
行执行结果writeln('Mystery Word: ':14, encryption:theWordSize);
你会注意到它没有显示任何值
encryption
。这是出了什么问题的重要线索。 'm'你
输入没有错,所以 encryption
不能有相同的值。唯一的
剩下要做的就是找出它实际具有的价值。请注意
如果您尝试使用 F7 计算 encryption
,它会显示空白,
不是您期望的星号。
下一位,在行上打断点
for i := 1 to theWordSize do
在encrypt
函数中,将代码window拖到屏幕右侧。然后,按
打开Watches
window,如有必要,将其拖入space,通过移动代码window释放,并在其中输入以下表达式
list[0]
和
list[1]
这是为了让您能够观察到列表的长度字节和第一个字符中的值。
运行 应用程序直到 encrypte
断点,然后单步绕过
for
循环。你会发现
list[0]
不会改变,即使 list[1]
的值已设置为 'm'。
所以,encrypt
返回的是一个空字符串,QED,我相信你会意识到
如何修复它。对不起,如果这已经相当累人,但至少它应该
让您了解如何系统地调试您 运行 遇到的下一个问题。