删除Pascal字符串中的短字

时间:2017-05-01 18:31:54

标签: string delphi pascal lazarus freepascal

我需要删除以点结尾的字符串中的短字(短三个符号)。然后显示没有这些单词的字符串。

所以我们需要一个来自用户的字符串作为这样的输入:“这是一个人类型的简单字符串。”在该字符串中,程序应删除每个短于三个符号的单词。在我们的字符串中,这些是:“是,a,a”。所以输出应该是“这个简单的字符串人类型。”

这是我编程课程的Pascal / Delphi任务。

我一直在考虑这个简单的问题几天,显然已经没有想法如何解决它并寻求你的帮助。我尝试了主要部分的不同循环,基本上在空格之间找到少于三个符号的序列。我试图调试它已经有一段时间了,但没有结果。

我使用Lazarus 1.6.2,FPC 3.0和Mac OS X v10.11(El Capitan)。我的代码如下:

 VAR
   UserString: string;
   i, n: byte;    // Counters for the symbols in the string. 'i' counts every symbol.
   again: boolean;   // In case we need to repeat the program again
   UserAnswerRepeat: char;
   label repeat_again;

 BEGIN
   again:=false;
 repeat_again:                 // Label to repeat the program
   Writeln('Enter your string (ended by a dot):');
   Readln(UserString);

   // MAIN LOOP:
   n:=1;              // 'n' counts symbols in the words
   for i:=1 to length(UserString) do
   begin
     while (UserString[i] <> ' ') do inc(n); // Here I have Range Check Error. Don't know how to get rid of it.
     if (UserString[n] <> ' ') and (n<3) then
     begin
       delete(UserString, i-n, n);
       n:=1
     end;
   end;

   Writeln('The result is: ', UserString);

   Writeln('Do you want to repeat the program? (Y/N)');
   Readln(UserAnswerRepeat);
   if (UserAnswerRepeat = 'Y') or (UserAnswerRepeat = 'y')  then
     again:=true;
   if (again = true) then
     goto repeat_again;
 END.

另一个小问题是:如何在成功运行后重新启动控制台应用程序?在这里,我使用标签和转到。也许还有另一种好方法可以再做一次吗?

4 个答案:

答案 0 :(得分:2)

在这种情况下,请查找单词分隔符。在你的情况下,它是空间&#39;。此外,计算点之前的最后一个单词,因为它没有跟随&#39;空格&#39;。

编写主循环的一种方法是:

var
  lastpos, I: integer;
  tmp, userstring: string;
begin
  lastpos: = 1;
  tmp: = '';
  for I: = 1 to length(userstring) do
  begin
    if (userstring[I] = ' ') or (I = length(userstring)) then
    begin
      if I-lastpos>=3 then tmp: = tmp + copy(userstring, lastpos, I-lastpos+1);
      lastpos: = I + 1;
    end;
  end;
  userstring: = tmp; 
end;

答案 1 :(得分:1)

控制变量的Platform循环开始值和结束值仅评估一次。您将结束值设置为字符串的长度。但是,在循环期间,您从字符串中删除部分,因此结束值超过字符串的结尾。尝试使用for循环或while循环。

错误的实际原因在

repeat .. until

循环会持续多久?循环结束了什么?

您还需要重新考虑使用 while (UserString[i] <> ' ') do inc(n); 计算字符的方式。

答案 2 :(得分:1)

再次感谢大家指出正确的方向。我终于想出了我最初想要的解决方案,这样程序实际上删除了短(少于3个符号)的单词。这就是我得到的:

VAR
UserString: string; //должна быть строка на 40 символов и точку в конце
i, n: byte;

BEGIN
Writeln('Enter the string:');
Readln(UserString);

i:=0;
n:=1;    

repeat       //MAIN LOOP:

  inc(i);
  if (UserString[i] = ' ') or (UserString[i] = '.') then

     begin
        if (i-n<3)then
        begin
        delete(UserString, n, i-n+1);
        i:=n-1;
        end;
        n:=i+1
     end

until (UserString[i] = '.') or (i>length(UserString));

Writeln('Result String: ', UserString);
END.

欢迎任何建议!还有一个关于在控制台模式下重复程序的问题。标签是最好的方法吗(参见问题部分的第一个代码)?

答案 3 :(得分:1)

另一种方法:

uses classes;

var v : TStringlist;
    i : integer;
begin
 v :=TStringlist.create;
 v.strictdelimiter:=true;
 v.delimiter:=' ';
 v.delimitedtext:='This is a simple string a man types';
 for i:=v.count-1 downto 0 do
    if length(v[i])<3 then
       v.delete(i);
 writeln(v.delimitedtext);
 v.free;
end.