Вопрос про цикл for
Модератор: Модераторы
Вопрос про цикл for
Я всегда на С++ определял досрочный выход из цикла по 'break' проверкой значения i
for i := 0 to 8 do ...;
if i <= 8 then ... // был выход по break
Но здесь оказалось, что в конце цикла i=8 и не возможно определить был ли break на последнем элементе.
Это особенность Паскаля или Лазаруса?
for i := 0 to 8 do ...;
if i <= 8 then ... // был выход по break
Но здесь оказалось, что в конце цикла i=8 и не возможно определить был ли break на последнем элементе.
Это особенность Паскаля или Лазаруса?
Паскаля.
Используй While. Только не понимаю смысла проверки.
Используй While. Только не понимаю смысла проверки.
Заменить 'for' на следующее не представляет проблемы:
i:=0;
while i < slGRUP.Count do
begin
i:=i+1;
Только i:=0 и i+1 делает 'for', иначе зачем он тогда нужен...
А смысл в том, что я ищу в массиве элементы удовлетворяющий условиям.
Проверки различны в зависимости от типа элемента. Я делаю 'break' когда элемент соответствует.
Но 'break' на последнем элементе равнозначен не найденному.
Нужно либо перед брейком присваивать переменной поиска труе, либо использовать вайл...
Описание работы for для паскаля мягко говоря не соответствует действительности.
i:=0;
while i < slGRUP.Count do
begin
i:=i+1;
Только i:=0 и i+1 делает 'for', иначе зачем он тогда нужен...
А смысл в том, что я ищу в массиве элементы удовлетворяющий условиям.
Проверки различны в зависимости от типа элемента. Я делаю 'break' когда элемент соответствует.
Но 'break' на последнем элементе равнозначен не найденному.
Нужно либо перед брейком присваивать переменной поиска труе, либо использовать вайл...
Описание работы for для паскаля мягко говоря не соответствует действительности.
-
xchgeaxeax
- постоялец
- Сообщения: 198
- Зарегистрирован: 11.05.2023 02:51:40
ZWolol, действие цикла for i := 0 to 8 do соответствует работе цикла for (int i = 0; i <= 8; ++i). В данном случае счетчик цикла существует только в пределах цикла. Значение счетчика не имеет значения после цикла и не сохраняется.
В данном случае эти две программы будут работать идентично, но на Pascal это будет длиннее
В данном случае эти две программы будут работать идентично, но на 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 для паскаля мягко говоря не соответствует действительности.
ZWolol, используй цикл по последний элемент включительно и тебе без разницы будет был break или нет.
Если хочешь то можешь привести пример, когда значение не определено для значения счётчика по выходу из цикла.
значение счётчика после выхода из цикла определено. И, если пользователь/программист не менял сам это значение, то всегда можно сказать какое это будет значение по выходу из цикла.xchgeaxeax писал(а):Значение счетчика не имеет значения после цикла и не сохраняется.
Если хочешь то можешь привести пример, когда значение не определено для значения счётчика по выходу из цикла.
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 тыс элементов, если найден десятым, я не вижу смысла.
И мне нужно определить в конце цикла, найден элемент или нет.
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 тыс элементов, если найден десятым, я не вижу смысла.
И мне нужно определить в конце цикла, найден элемент или нет.
- Sergei I. Gorelkin
- энтузиаст
- Сообщения: 1409
- Зарегистрирован: 24.07.2005 14:40:41
- Откуда: Зеленоград
Компилятор может оптимизировать цикл for. Например, если значение управляющей переменной не используется внутри тела цикла, то задача компилятора - сгенерировать код, повторяющий тело цикла заданное количество раз, а как именно - это его проблемы. Т.е. компилятор имеет право превратить "for i:=0 to 7 do" в "for i:=1000 to 1007 do" или "for i:=7 downto 0 do", и переменная после цикла действительно не определена.
Другой пример - если в цикле ведется перебор элементов массива, то для получения более быстрого кода компилятор может добавить т.н. induction variable:
превратится в что-то такое (если считать, что arr - массив элементов типа integer)
И здесь значение управляющей переменной тоже перестает использоваться.
Другой пример - если в цикле ведется перебор элементов массива, то для получения более быстрого кода компилятор может добавить т.н. induction variable:
Код: Выделить всё
for i:=0 to 7 do arr[i] := arr[i]+25;
Код: Выделить всё
var tmp: PInteger;
tmp := @arr[0];
for i:=0 to 7 do
begin
tmp^ := tmp^+25;
inc(tmp);
end;
-
xchgeaxeax
- постоялец
- Сообщения: 198
- Зарегистрирован: 11.05.2023 02:51:40
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;Sergei I. Gorelkin, да, тут моя вина, но если пользователь/программист будет использовать счётчик цикла вне цикла, то значение цикла будет учтено.
Второе можно задать конкретный цикл от 48000 до 50000.
по сути там не должно сохраняться i = 5, по простой причине, что данная переменная задействована. Какова правильная реализация в Си, не знаю. В Паскале не сохранится.ZWolol писал(а):int i = 5;
for (int i = 0; i <= 8; ++i) ...;
Первое, при использовании Break, не надо будет перебирать все элементы.ZWolol писал(а):Перебирать 50 тыс элементов, если найден десятым, я не вижу смысла.
Второе можно задать конкретный цикл от 48000 до 50000.
Последний раз редактировалось Seenkao 22.01.2024 13:34:06, всего редактировалось 1 раз.
Разумеется ... Другое дело что после "честного завершения" цикла (без break ) ИНОГДА может быть i = 9 ... ( что вроде и странно но по своему логично )Seenkao писал(а):по сути там не должно сохраняться i = 5, по простой причине, что данная переменная задействована. Какова правильная реализация в Си, не знаю. В Паскале не сохранится.
может, надо знать какой компилятор используется. Старые компиляторы зачастую следующее значение выдавали.Alex2013 писал(а):ИНОГДА может быть i = 9
дичь какая то.... простейшее условие с флагом. Зачем еще что то искать.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, зачастую нужен поиск не по элементу, а нужен элемент, на котором поиск был остановлен.
>по сути там не должно сохраняться i = 5, по простой причине, что данная переменная задействована. Какова правильная реализация в Си, не знаю. В Паскале не сохранится.
Видимость для переменных: ты можешь многократно объявлять переменную i.
Локальная i не изменит приватную и глобальную.
Локальная i цикла не должна менять переменную вне ее.
А в паскале используется объявленная переменная. Она меняется, но результат использовать нельзя.
>Sharfik, зачастую нужен поиск не по элементу, а нужен элемент, на котором поиск был остановлен.
Собственно я так и делал.
Но в данном случае мне каждую строку в массиве нужно разобрать на составляющие и по комбинации этих значений определить соответствие.
А если я уже разобрал строку и сохранил их в переменных, то зачем мне по ее номеру опять делать разбор, достаточно указать что найдена.
Я сразу сказал, что переменная True/False решает эту проблему.
Нужно только ко всем break добавить ей True (аналогично можно ей присваивать номер в массиве).
Вопрос стоял в том: почему результат i нельзя использовать, а на С не было проблем.
Видимость для переменных: ты можешь многократно объявлять переменную i.
Локальная i не изменит приватную и глобальную.
Локальная i цикла не должна менять переменную вне ее.
А в паскале используется объявленная переменная. Она меняется, но результат использовать нельзя.
>Sharfik, зачастую нужен поиск не по элементу, а нужен элемент, на котором поиск был остановлен.
Собственно я так и делал.
Но в данном случае мне каждую строку в массиве нужно разобрать на составляющие и по комбинации этих значений определить соответствие.
А если я уже разобрал строку и сохранил их в переменных, то зачем мне по ее номеру опять делать разбор, достаточно указать что найдена.
Я сразу сказал, что переменная True/False решает эту проблему.
Нужно только ко всем break добавить ей True (аналогично можно ей присваивать номер в массиве).
Вопрос стоял в том: почему результат i нельзя использовать, а на С не было проблем.
что?ZWolol писал(а):Она меняется, но результат использовать нельзя.
Я постоянно использую результат именно счётчика цикла. Потому что при использовании Break мы получим последнее значение когда был прерван цикл. А если цикл завершился, то использую значение для задание новых данных.
Что за сказки тут рассказывают?
Добавлено спустя 2 минуты 57 секунд:
ещё раз пишу, что надо использовать те переменные, которые будут входить в условие, тогда ты получишь необходимое значение.ZWolol писал(а):Вопрос стоял в том: почему результат i нельзя использовать, а на С не было проблем.
Если ты используешь значения больше/меньше в счётчике цикла, то должен это обставить в нужном варианте. В Си будет так же.
Нужен обход кода, делай вызов функции или используй оператор GoTo.
Последний раз редактировалось Seenkao 22.01.2024 15:03:00, всего редактировалось 1 раз.
