Страница 1 из 4

Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 10:52:58
ZWolol
Я всегда на С++ определял досрочный выход из цикла по 'break' проверкой значения i

for i := 0 to 8 do ...;
if i <= 8 then ... // был выход по break

Но здесь оказалось, что в конце цикла i=8 и не возможно определить был ли break на последнем элементе.
Это особенность Паскаля или Лазаруса?

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 11:10:43
Seenkao
Паскаля.
Используй While. Только не понимаю смысла проверки.

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 11:48:37
ZWolol
Заменить 'for' на следующее не представляет проблемы:
i:=0;
while i < slGRUP.Count do
begin
i:=i+1;

Только i:=0 и i+1 делает 'for', иначе зачем он тогда нужен...

А смысл в том, что я ищу в массиве элементы удовлетворяющий условиям.
Проверки различны в зависимости от типа элемента. Я делаю 'break' когда элемент соответствует.
Но 'break' на последнем элементе равнозначен не найденному.
Нужно либо перед брейком присваивать переменной поиска труе, либо использовать вайл...

Описание работы for для паскаля мягко говоря не соответствует действительности.

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 12:33:52
xchgeaxeax
ZWolol, действие цикла for i := 0 to 8 do соответствует работе цикла for (int i = 0; i <= 8; ++i). В данном случае счетчик цикла существует только в пределах цикла. Значение счетчика не имеет значения после цикла и не сохраняется.

В данном случае эти две программы будут работать идентично, но на Pascal это будет длиннее
Код: Выделить всё
#include <iostream>

int main(int argc, char *argv[]) {
    int i = 5;
    for (int i = 0; i <= 8; ++i) std::cout << i << " ";
    std::cout << std::endl << i << std::endl;
    for (int i = 0; i <= 8; ++i) {
      if (i == 8) break;
      std::cout << i << " ";
    }
    std::cout << std::endl << i << std::endl;
    return 0;
}
Код: Выделить всё
program test_prog;

uses
  SysUtils;

var
  i: LongInt;

procedure For1();
var
  i: LongInt;
begin
  for i := 0 to 8 do Write(i, ' ');
end;

procedure For2();
var
  i: LongInt;
begin
  for i := 0 to 8 do begin
    if i = 8 then break;
    Write(i, ' ');
  end;
end;

begin
  i := 5;
  For1;
  WriteLn(#13, #10, i);
  For2;
  WriteLn(#13, #10, i);
end.


ZWolol писал(а):Описание работы for для паскаля мягко говоря не соответствует действительности.

Смотря где вы читаете.

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 13:12:58
Seenkao
ZWolol, используй цикл по последний элемент включительно и тебе без разницы будет был break или нет.

xchgeaxeax писал(а):Значение счетчика не имеет значения после цикла и не сохраняется.

значение счётчика после выхода из цикла определено. И, если пользователь/программист не менял сам это значение, то всегда можно сказать какое это будет значение по выходу из цикла.

Если хочешь то можешь привести пример, когда значение не определено для значения счётчика по выходу из цикла.

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 13:25:14
ZWolol
int i = 5;
for (int i = 0; i <= 8; ++i) ...;

Это объявление локальной переменной в пределах цикла.
К ней не может быть обращение вне цикла.
После цикла, по моему, даже i сохранит 5.

int i = 5;
for (i = 0; i <= 8; ++i) ...;
А здесь используется объявленная переменная и i станет равно 9.
В паскале то же используется объявленная переменная, только значение будет 8.
Я могу ошибаться, 10 лет уже не писал...

Описаний паскаля много всяких разных, есть даже в виде функциональных блоков для работы for.
Но либо умалчивается про результат i, либо не правильное.
Наверняка есть и правильное, но это не суть важно.

>ZWolol, используй цикл по последний элемент включительно и тебе без разницы будет был break или нет.
Перебирать 50 тыс элементов, если найден десятым, я не вижу смысла.
И мне нужно определить в конце цикла, найден элемент или нет.

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 13:48:53
Sergei I. Gorelkin
Компилятор может оптимизировать цикл for. Например, если значение управляющей переменной не используется внутри тела цикла, то задача компилятора - сгенерировать код, повторяющий тело цикла заданное количество раз, а как именно - это его проблемы. Т.е. компилятор имеет право превратить "for i:=0 to 7 do" в "for i:=1000 to 1007 do" или "for i:=7 downto 0 do", и переменная после цикла действительно не определена.

Другой пример - если в цикле ведется перебор элементов массива, то для получения более быстрого кода компилятор может добавить т.н. induction variable:
Код: Выделить всё
for i:=0 to 7 do arr[i] := arr[i]+25;

превратится в что-то такое (если считать, что arr - массив элементов типа integer)
Код: Выделить всё
var tmp: PInteger;
tmp := @arr[0];
for i:=0 to 7 do
begin
  tmp^ := tmp^+25;
  inc(tmp);
end;

И здесь значение управляющей переменной тоже перестает использоваться.

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 13:52:56
xchgeaxeax
ZWolol писал(а):Перебирать 50 тыс элементов, если найден десятым, я не вижу смысла.
И мне нужно определить в конце цикла, найден элемент или нет.

Код: Выделить всё
var
  i, k: LongInt;
begin
  k := -1;
  for i := 0 to 50000 do if i = 10 then begin k := i; break end;
  if k < 0 then WriteLn('не найден') else WriteLn(k);
  WriteLn(i);
end;
Хотя в таком простом цикле i останется равным 10.

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 14:17:04
Seenkao
Sergei I. Gorelkin, да, тут моя вина, но если пользователь/программист будет использовать счётчик цикла вне цикла, то значение цикла будет учтено.



ZWolol писал(а):int i = 5;
for (int i = 0; i <= 8; ++i) ...;

по сути там не должно сохраняться i = 5, по простой причине, что данная переменная задействована. Какова правильная реализация в Си, не знаю. В Паскале не сохранится.

ZWolol писал(а):Перебирать 50 тыс элементов, если найден десятым, я не вижу смысла.

Первое, при использовании Break, не надо будет перебирать все элементы.
Второе можно задать конкретный цикл от 48000 до 50000.

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 14:29:13
Alex2013
Seenkao писал(а):по сути там не должно сохраняться i = 5, по простой причине, что данная переменная задействована. Какова правильная реализация в Си, не знаю. В Паскале не сохранится.

Разумеется ... Другое дело что после "честного завершения" цикла (без break ) ИНОГДА может быть i = 9 ... ( что вроде и странно но по своему логично )

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 14:33:38
Seenkao
Alex2013 писал(а):ИНОГДА может быть i = 9

может, надо знать какой компилятор используется. Старые компиляторы зачастую следующее значение выдавали.

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 14:34:50
Sharfik
ZWolol писал(а):Я всегда на С++ определял досрочный выход из цикла по 'break' проверкой значения i

for i := 0 to 8 do ...;
if i <= 8 then ... // был выход по break

Но здесь оказалось, что в конце цикла i=8 и не возможно определить был ли break на последнем элементе.
Это особенность Паскаля или Лазаруса?

дичь какая то.... простейшее условие с флагом. Зачем еще что то искать.
Код: Выделить всё
var
  bCorrect:Boolean;
  i:integer;
begin
bCorrect:=False;
for i:=0 to 100 do
begin
  if i=44 then
  begin
     bCorrect:=True;
    break;
  end;
end;

if  bCorrect then ....
end;

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 14:57:08
Seenkao
Sharfik, зачастую нужен поиск не по элементу, а нужен элемент, на котором поиск был остановлен.

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 15:43:29
ZWolol
>по сути там не должно сохраняться i = 5, по простой причине, что данная переменная задействована. Какова правильная реализация в Си, не знаю. В Паскале не сохранится.

Видимость для переменных: ты можешь многократно объявлять переменную i.
Локальная i не изменит приватную и глобальную.
Локальная i цикла не должна менять переменную вне ее.
А в паскале используется объявленная переменная. Она меняется, но результат использовать нельзя. :(

>Sharfik, зачастую нужен поиск не по элементу, а нужен элемент, на котором поиск был остановлен.
Собственно я так и делал.

Но в данном случае мне каждую строку в массиве нужно разобрать на составляющие и по комбинации этих значений определить соответствие.
А если я уже разобрал строку и сохранил их в переменных, то зачем мне по ее номеру опять делать разбор, достаточно указать что найдена.
Я сразу сказал, что переменная True/False решает эту проблему.
Нужно только ко всем break добавить ей True (аналогично можно ей присваивать номер в массиве).

Вопрос стоял в том: почему результат i нельзя использовать, а на С не было проблем.

Re: Вопрос про цикл for

СообщениеДобавлено: 22.01.2024 15:59:13
Seenkao
ZWolol писал(а):Она меняется, но результат использовать нельзя.

что? :shock:
Я постоянно использую результат именно счётчика цикла. Потому что при использовании Break мы получим последнее значение когда был прерван цикл. А если цикл завершился, то использую значение для задание новых данных.

Что за сказки тут рассказывают? :)

Добавлено спустя 2 минуты 57 секунд:
ZWolol писал(а):Вопрос стоял в том: почему результат i нельзя использовать, а на С не было проблем.

ещё раз пишу, что надо использовать те переменные, которые будут входить в условие, тогда ты получишь необходимое значение.

Если ты используешь значения больше/меньше в счётчике цикла, то должен это обставить в нужном варианте. В Си будет так же.
Нужен обход кода, делай вызов функции или используй оператор GoTo.