Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 20.12.2011, 11:13   #1
Form_13
Форумчанин
 
Регистрация: 25.04.2011
Сообщений: 107
По умолчанию

Почему не работает, не понимаю!!


Код:
Program курсовая;

{$APPTYPE CONSOLE}

{$R *.res}

 Uses
  System.SysUtils;

Var flag:boolean;
     l:string;

Procedure prob (var s:string);
  var flag:boolean;
      i:integer;
  begin
   i:=0;
   while i<length(s) do
    begin
     inc(i);
     if not (s[i]=' ') then flag:=false;
     if s[i]=' ' then
      if flag then delete(s,i,1)
       else flag:=true;
     if (s[i]='!') or (s[i]='.') or (s[i]='?') then
      begin
       if s[i-1]=' ' then delete(s,i-1,1);
       if not (s[i+1]=' ') then delete(s,i+1,1);
      end;
    end;
  end;

begin
 l:='   Ча  ча     ча ча!';
 prob(l);
 writeln(l);
 readln;
end.
Выводит точно такую же строку, единственное что удаляет пробел до знака или после, но не если 2-3 пробела рядом.

Я так понимаю, у меня while i<length(s) не меняется по значению, то есть строка то моя увеличивается или уменьшается, а он. Хм.

Я тут попробовал её переделать, всё равно херня получилось.

Код:
Procedure prob (var s:string);
  var flag:boolean;
      i,k:integer;
      s1:string;
  begin
   i:=0; k:=0;
   s1:=s;
   while i<length(s1) do
    begin
     inc(i);
     if not (s[i]=' ') then flag:=false;
     if s1[i]=' ' then
      if flag then
       begin
        delete(s1,i,1);
        dec(i);
        continue;
       end
              else flag:=true;
     if (s1[i]='!') or (s1[i]='.') or (s1[i]='?') then
      begin
       if s1[i-1]=' ' then
        begin
         delete(s1,i-1,1);
         dec(i);
         continue;
        end;
       if not (s1[i+1]=' ') then
        begin
         delete(s1,i+1,1);
         dec(i);
         continue;
        end;
      end;
     if s1[i]='.' then
      begin
        if k=3 then
                begin
                 delete(s1,i,1);
                 dec(i);
                 continue;
                end
               else inc(k);
      end
                 else k:=0;
    end;
    s:=s1;
  end;

Последний раз редактировалось artemavd; 20.12.2011 в 17:32.
Form_13 вне форума Ответить с цитированием
Старый 20.12.2011, 12:15   #2
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,528
По умолчанию

Держи
Код:
      i:=1;
   while i<length(s)-1 do
   begin
     if s[i]=' ' then begin
       case s[i+1] of
       ' ', '?', '.', '!': Delete(s,i,1); //удаляем пробел ПЕРЕД перчисленными знаками
//После удаления индексы всех знаков после удаленного уменьшаются 
//поэтому нам снова надо проверять s[i] стало быть нельзя делать inc(i)
//иначе мы пропустим (не проверим) какой-нибудь знак.
// Это твоя основная ошибка. 
       else inc(i); // передвигаемся если не было удаления (единственный пробел)
       end;
     end
     else inc(i); //или вообще не пробел    
   end;
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 20.12.2011 в 12:24.
evg_m вне форума Ответить с цитированием
Старый 20.12.2011, 12:23   #3
Form_13
Форумчанин
 
Регистрация: 25.04.2011
Сообщений: 107
По умолчанию

В очередной раз убеждаюсь насколько я глуп. Благодарю за краткий и эффективный код)

Да, я уже разобрался, где именно ошибся.
Я ещё добавил:
Код:
if (s[i]=' ') or (s[i]='.') or (s[i]='!') or (s[i]='?') then  begin
       case s[i+1] of
чтобы удалял лишние точки, восклицательные знаки и вопросительные.

Код:
Program курсовая;

{$APPTYPE CONSOLE}

{$R *.res}

 Uses
  System.SysUtils;

//односвязный список
 Type
  p=^elem;
  elem = record
         data:string;
         sled:p;
         end;
 Var ykaz:p;
     flag:boolean;
     l:string;

 //процедура чтения файла в динамический список
 Procedure read;
  var next:p;
      F:textfile;
  begin
   Assign(F,'text.txt');
   Reset(F);
   next:=ykaz;                           //делаем временный указатель, для прохождения по списку
   while not EoF(F)  do                 //пока, не конец файла
    begin
     readln(F,next^.data);              //читаем строку в поле data
     if next^.data='' then              //если файл пустой, то...
      begin
       flag:=true;                      //...запоминает это, и..
       exit;                            //...выходим из подпрограммы.
      end;
     new(next^.sled);                   //если всё хорошо, выделяем память под следущий элемент списка
     next:=next^.sled;                  //переходим на него (присваиваем его основному указателю)
    end;
   close(F);                            //прекращаем работу с файлом
  end;
 //процедура записи в файл из динамического массива
 Procedure write;
  var F:textfile;
      yk,l:p;
  begin
   if flag then exit;                    //если мы выяснили при чтении, что файл пустой, выходим из подпрограммы
   Assign(F,'text.txt');
   Rewrite(F);
   yk:=ykaz;
   while (yk<>nil) do   //если текущий указатель имеет непустое значение, то..
    begin
     Writeln(F,yk^.data);     //записываем в файл строку, и ..
     l:=yk^.sled;
     dispose(yk);       //уничтожаем текущий элемент списка
     yk:=l;            //переходим на следущий указатель
    end;
   close(F);                  //закрываем файл.
  end;
 //процедура чистки лишних пробелов
 Procedure prob (var s:string);
  var i:integer;
  begin
   i:=1;
   while i<length(s)-1 do
   begin
     if (s[i]=' ') or (s[i]='.') or (s[i]='?') or (s[i]='!')then begin
       case s[i+1] of
       ' ', '?', '.', '!': Delete(s,i,1); //удаляем пробел перед перчисленными знаками
       else inc(i); // передвигаемся если не было удаления (единственный пробел)
       end;
     end
     else inc(i); //или вообще не пробел
   end;
  end;
 //процедура поиска и замены слов
 Procedure main;
  var yk:p;
  begin
   yk:=ykaz;
   while (yk<>nil) do
    begin
     prob(yk^.data);
     yk:=yk^.sled;
    end;
  end;

begin
 new(ykaz);
 read;
 main;
 write;
end.
Вот я воткнул процедуру свою основную программу, но почему-то в файл записываются неизменённые значения.

По-моему он не записывает, то есть до prob(yk^.data); - всё нормально. Он не меняет внутри списка ничего, или не записывает даже, я не знаю.

Нашёл косяк. Где была проверка пустой строки, ведь последняя строка всегда пустая, и видимо он её проверяет, а потом процедуре записи подаётся сигнал, что весь файл пустой. Как бы сделать проверку пустого файла, но чтоб проверял до текста, а не после.

Сделал так:

Код:
while not EoF(F)  do                 //пока, не конец файла
    begin
     readln(F,next^.data);              //читаем строку в поле data
     if not (next^.data='') then flag1:=true;
     if (next^.data='') and (not (flag1)) then              //если файл пустой, то...
      begin
       flag:=true;                      //...запоминает это, и..
       exit;                            //...выходим из подпрограммы.
      end;
     new(next^.sled);                   //если всё хорошо, выделяем память под следущий элемент списка
     next:=next^.sled;                  //переходим на него (присваиваем его основному указателю)
    end;
Код:
Procedure prob (var s:string);
  var i:integer;
  begin
   i:=1;
   while i<length(s) do
   begin
     if (s[i]=' ') or (s[i]='.') or (s[i]='?') or (s[i]='!') or (s[i]=',') then
      begin
       case s[i+1] of
       ' ', '?', '.', '!':
        begin
         Delete(s,i,1);
         if not (s[i+2]=' ') then
                              begin
                              insert(' ',s,i+2);
                              dec(i);
                              end;
        end;  //удаляем пробел перед перчисленными знаками
       else inc(i); // передвигаемся если не было удаления (единственный пробел)
       end;
      end
     else inc(i); //или вообще не пробел
   end;
  end;
я вставил в процедуру, проверку пробела перед новым предложением, лагнуло. посмотри ещё раз.

Последний раз редактировалось artemavd; 20.12.2011 в 17:33.
Form_13 вне форума Ответить с цитированием
Старый 23.12.2011, 11:48   #4
Johnson
кривокодер ;)
Форумчанин
 
Аватар для Johnson
 
Регистрация: 20.06.2008
Сообщений: 707
По умолчанию

Я, конечно, понимаю, что большинство сдешних профессионалов не любители простых путей...

Код:
while Pos('  ',S)>0 do StringReplace(S, '  ', ' ');
Да, этот код процентов на 20% медленнее предыдущего. Но, проще и эффективнее. Небось, не на 8086 процссорах работаем...

Кстати, возможно цикл даже и не нужен. Сейчас под рукой нет компилятора, но вроде бы, в StringReplace тоже есть цикл. Надо его исходники глядеть.



Есть ещё такой вариант. Написан на коленке за минуту, могут быть ошибки.
Код:
for I:=length(S) downto 1 do begin
	if (S[I]=' ') then if (I=1) or ((I>1)and(S[I-1]<>' ') ) then Delete(S,I,1);
	// Сдесь такие же конструкции для других символов
end;
"А как написать праграму?, "ришыти задачьку очинь нада" ©с форума. Жить становится интереснее, жить становится веселее...
{Быть или не быть} {Неуспешный суицид}

Последний раз редактировалось Johnson; 23.12.2011 в 11:59.
Johnson вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
удаление лишних пробелов или знаков '_' из MaskEdit Blood_ghosT Компоненты Delphi 6 07.12.2011 20:23
Процедура очистки listbox detalik Помощь студентам 1 15.04.2011 17:41
Удаление лишних пробелов. Lucky777 Помощь студентам 0 01.12.2010 21:49
Удаление лишних пробелов. qwertytol Общие вопросы C/C++ 5 16.05.2010 15:43