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

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

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

Сообщение ZWolol » 22.01.2024 10:52:58

Я всегда на С++ определял досрочный выход из цикла по 'break' проверкой значения i

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

Но здесь оказалось, что в конце цикла i=8 и не возможно определить был ли break на последнем элементе.
Это особенность Паскаля или Лазаруса?
ZWolol
новенький
 
Сообщения: 21
Зарегистрирован: 06.01.2023 06:49:21

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

Сообщение Seenkao » 22.01.2024 11:10:43

Паскаля.
Используй While. Только не понимаю смысла проверки.
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

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

Сообщение ZWolol » 22.01.2024 11:48:37

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

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

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

Описание работы for для паскаля мягко говоря не соответствует действительности.
ZWolol
новенький
 
Сообщения: 21
Зарегистрирован: 06.01.2023 06:49:21

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

Сообщение xchgeaxeax » 22.01.2024 12:33:52

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 для паскаля мягко говоря не соответствует действительности.

Смотря где вы читаете.
xchgeaxeax
новенький
 
Сообщения: 90
Зарегистрирован: 11.05.2023 03:51:40

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

Сообщение Seenkao » 22.01.2024 13:12:58

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

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

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

Если хочешь то можешь привести пример, когда значение не определено для значения счётчика по выходу из цикла.
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

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

Сообщение ZWolol » 22.01.2024 13:25:14

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 тыс элементов, если найден десятым, я не вижу смысла.
И мне нужно определить в конце цикла, найден элемент или нет.
ZWolol
новенький
 
Сообщения: 21
Зарегистрирован: 06.01.2023 06:49:21

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

Сообщение Sergei I. Gorelkin » 22.01.2024 13:48:53

Компилятор может оптимизировать цикл 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;

И здесь значение управляющей переменной тоже перестает использоваться.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1397
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

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

Сообщение xchgeaxeax » 22.01.2024 13:52:56

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.
xchgeaxeax
новенький
 
Сообщения: 90
Зарегистрирован: 11.05.2023 03:51:40

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

Сообщение Seenkao » 22.01.2024 14:17:04

Sergei I. Gorelkin, да, тут моя вина, но если пользователь/программист будет использовать счётчик цикла вне цикла, то значение цикла будет учтено.



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

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

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

Первое, при использовании Break, не надо будет перебирать все элементы.
Второе можно задать конкретный цикл от 48000 до 50000.
Последний раз редактировалось Seenkao 22.01.2024 14:34:06, всего редактировалось 1 раз.
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

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

Сообщение Alex2013 » 22.01.2024 14:29:13

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

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

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

Сообщение Seenkao » 22.01.2024 14:33:38

Alex2013 писал(а):ИНОГДА может быть i = 9

может, надо знать какой компилятор используется. Старые компиляторы зачастую следующее значение выдавали.
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

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

Сообщение Sharfik » 22.01.2024 14:34:50

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;
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 766
Зарегистрирован: 20.07.2013 01:04:30

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

Сообщение Seenkao » 22.01.2024 14:57:08

Sharfik, зачастую нужен поиск не по элементу, а нужен элемент, на котором поиск был остановлен.
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

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

Сообщение ZWolol » 22.01.2024 15:43:29

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

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

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

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

Вопрос стоял в том: почему результат i нельзя использовать, а на С не было проблем.
ZWolol
новенький
 
Сообщения: 21
Зарегистрирован: 06.01.2023 06:49:21

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

Сообщение Seenkao » 22.01.2024 15:59:13

ZWolol писал(а):Она меняется, но результат использовать нельзя.

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

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

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

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

Если ты используешь значения больше/меньше в счётчике цикла, то должен это обставить в нужном варианте. В Си будет так же.
Нужен обход кода, делай вызов функции или используй оператор GoTo.
Последний раз редактировалось Seenkao 22.01.2024 16:03:00, всего редактировалось 1 раз.
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

След.

Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 56

Рейтинг@Mail.ru