7.7 Зачем нужен цикл: "Пока 1 = 1 Цикл"

Тема в разделе "Конфигурирование на платформе "1С:Предприятие 7.7"", создана пользователем Tanush, 24 май 2010.

  1. TopicStarter Overlay
    Tanush
    Offline

    Tanush Опытный в 1С

    Регистрация:
    24 апр 2008
    Сообщения:
    96
    Симпатии:
    0
    Баллы:
    26
    Разбираю чужой код потому что программа не завершает обработку, а так и зависает. Нашла что вис происходит внутри такого цикла:

    Код:
    Пока 1 = 1 Цикл
    Если Условие1 Тогда
    // операторы
    Возврат;
    КонецЕсли;
    // операторы
    КонецЦикла;
    
    Вот и вопрос: зачем нужны подобные циклы?
  2. BabySG
    Offline

    BabySG Администраторы Команда форума Администратор

    Регистрация:
    10 июн 2007
    Сообщения:
    11.853
    Симпатии:
    12
    Баллы:
    29
    Это т.н. бесконечный цикл. Применяется редко, когда лень писать другой алгоритм.
    Обычно из него выход происходит через Возврат (как в примере), или через Прервать.
  3. TopicStarter Overlay
    Tanush
    Offline

    Tanush Опытный в 1С

    Регистрация:
    24 апр 2008
    Сообщения:
    96
    Симпатии:
    0
    Баллы:
    26
    Т.е. если условие не выполнится, то я никогда из него не выйду!!! О ужас!!!

    Самое интересное, что иногда (зависит от определенной заполненности документа), это цикл хорошо исполняется, а вот иногда - на нем все застревает.
  4. BabySG
    Offline

    BabySG Администраторы Команда форума Администратор

    Регистрация:
    10 июн 2007
    Сообщения:
    11.853
    Симпатии:
    12
    Баллы:
    29
    Это признак непродуманности алгоритма... Учтите этот момент и перепишите алгоритм.
  5. TopicStarter Overlay
    Tanush
    Offline

    Tanush Опытный в 1С

    Регистрация:
    24 апр 2008
    Сообщения:
    96
    Симпатии:
    0
    Баллы:
    26
    Посмотрела алгоритм - вообще нет смысла в цикле: постоянно идет проверка на нахождение определенного значения в ТЗ.

    Код:
    Пока 1 = 1 Цикл
    Ном = 0;
    ТЗКопия.НайтиЗначение(Знач1,Ном,Кол1);
    Если Ном = 0 Тогда
    Возврат(0);
    КонецЕсли;
    Если (ТЗКопия.ПолучитьЗначение(Ном,Кол2) = Знач2) И
    (ТЗКопия.ПолучитьЗначение(Ном,Кол3) = Знач3) И
    (ТЗКопия.ПолучитьЗначение(Ном,Кол4) = Знач4) Тогда
    Возврат(Ном);
    КонецЕсли;
    ТЗКопия.УстановитьЗначение(Ном,Кол1,ПолучитьПустоеЗначение());
    КонецЦикла;
    
    
  6. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    "кривой" алгоритм поиска полного сообвествия строки ТЗ указанным значениям... Есть более красивые решения (подобный алгоритм накрайняк когда допустим есть периодические значений и нельзя воспользоваться запросом и группировкой)
  7. TopicStarter Overlay
    Tanush
    Offline

    Tanush Опытный в 1С

    Регистрация:
    24 апр 2008
    Сообщения:
    96
    Симпатии:
    0
    Баллы:
    26
    О кривизне - полностью согласна!
  8. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    бесконечный цикл, который означает, что прерывание происходит внутри цикла..
    в данном случае есть некорректное условие
    Код:
    Если (ТЗКопия.ПолучитьЗначение(Ном,Кол2) = Знач2) И
    (ТЗКопия.ПолучитьЗначение(Ном,Кол3) = Знач3) И
    (ТЗКопия.ПолучитьЗначение(Ном,Кол4) = Знач4) Тогда
    Возврат(Ном);
    КонецЕсли;
    
    при невыполнении которого цикл становится бесконечным..
    Заменить его можно просто циклом по строкам ТЗ или (если нужна скорость) отфильтровать ТЗ по Знач1, и сделать цикл по строкам
  9. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    Фобец, вы не внимательны. Если условие не выполнится - найденное значение затирается строчкой ниже и при условии что ни одно значение не отыщется - цикл все равно прервется (условие Ном=0)
  10. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    Верно :unsure: тогда так:
    Код:
    Пока 1 = 1 Цикл
    Если ПустоеЗначение(Знач1) = 1 Тогда
    Возврат 0;
    КонецЕсли
    Ном = 0;
    ТЗКопия.НайтиЗначение(Знач1,Ном,Кол1);
    Если Ном = 0 Тогда
    Возврат(0);
    КонецЕсли;
    Если (ТЗКопия.ПолучитьЗначение(Ном,Кол2) = Знач2) И
    (ТЗКопия.ПолучитьЗначение(Ном,Кол3) = Знач3) И
    (ТЗКопия.ПолучитьЗначение(Ном,Кол4) = Знач4) Тогда
    Возврат(Ном);
    КонецЕсли;
    ТЗКопия.УстановитьЗначение(Ном,Кол1,ПолучитьПустоеЗначение());
    КонецЦикла;
    
  11. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    я все-таки решил исправиться и предлагаю свое скромное решение, может быть поможет.. (соррь за транслит)
    Код:
    //Function FilterVT(Val oVT,keyCol,keyVal) Фильтр В ТЗ 
    //oVT - ТЗ, в которой будет осуществляться отбор
    //keyCol - Номер или идентификатор колонки, по которой осуществляется отбор
    //keyVal - Значение отбора
    Function FilterVT(oVT,keyCol,keyVal)
    oVTEx = CreateObject("ValueTable");
    oVT.Unload(oVTEx,1,1);
    oVTEx.DeleteLines();
    nStrEnd = 0;
    nStrBeg = 0;
    oVT.Sort("+"+keyCol);
    If oVT.FindValue(keyVal,nStrEnd,keyCol)>0 Then
    oVT.Sort("-"+keyCol);
    oVT.FindValue(keyVal,nStrBeg,keyCol);
    oVT.Unload(oVTEx,nStrBeg,oVT.LinesCnt()-nStrEnd+1);
    Else
    Return oVTEx;
    EndIf;
    Return oVTEx;
    EndFunction
    
    
    Процедура ВашегоПоиска()
    ...
    //Вместо вашего цикла..
    //Если номер строки копии должен точно соответствовать номеру строки ТЗ,
    //добавляем колонку со номером, т.к. таблицу будем резать
    ТЗКопия.InsertCollumn("nCntr");
    For i = 1 To ТЗКопия.LinesCnt();
    ТЗКопия.SetValue(i,"nCntr",i);
    EndDo;
    ТЗКопия = FilterVT(ТЗКопия,Кол1,Знач1);
    ТЗКопия.SelectLines();
    While ТЗКопия.GetLine() = 1 Do
    If ТЗКопия.Кол2<>Знач2 Or ТЗКопия.Кол3<>Знач3 Or ТЗКопия.Кол3<>Знач3 Then
    Continue;
    Else
    Return ТЗКопия.nCntr;     //Если номер строки неважен (например если эта ТЗКопия общая переменная),
    //эту колонку nCntr не добавляем, и здесь передаем номер строки ТЗКопии
    EndIf;
    EndDo;
    Return 0;
    КонецЦикла;
    
    
  12. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    Спасибо, грамотное решение. Поскольку на АнлиЦком пишут единицы взял на себя труд перевести
    Фобец, если вы выкладываете код -убедительная просьба.. БУДЬТЕ ВНИМАТЕЛЬНЫ. Старайтесь приводить код без ошибок.
    Люди же зачастую просто копируют. Здесь так много новичков...


    Код:
    Функция ФильтрТЗ(ТЗ,Ключ,КлючЗн)    
    вТЗ = СоздатьОбъект("ТаблицаЗначений");    
    //скопировали структуту ТЗ
    ТЗ.Выгрузить(вТЗ,1,1);    
    вТЗ.УдалитьСтроки();    
    
    КонСтр = 0;    
    НачСтр = 0;    
    ТЗ.Сотрирова("+"+Ключ);    
    Если  ТЗ.НайтиЗначение(КлючЗн,КонСтр,Ключ)>0 Тогда        
    ТЗ.Сортировать("-"+Ключ);        
    ТЗ.НайтиЗначение(КлючЗн,НачСтр,Ключ);        
    ТЗ.Выгрузить(вТЗ,НачСтр,ТЗ.КоличествоСтрок()-КонСтр+1);    
    КонецЕсли;    
    Возврат вТЗ;
    КонецФункции
    
    //
    Функция ВашегоПоиска()  // поскольку мы что-то возвращаем не процедура, а функция
    //Вместо вашего цикла..    
    //Если номер строки копии должен точно соответствовать номеру строки ТЗ,    
    //добавляем колонку со номером, т.к. таблицу будем резать    
    ТЗКопия.НоваяКолонка("КолонкаТЗ");    
    Пока я = 1 To ТЗКопия.КоличествоСтрок(); Цикл
    ТЗКопия.УстановитьЗначение(я,"КолонкаТЗ",я);    
    КонецЦикла;    
    
    ТЗКопия = ФильтрТЗ(ТЗКопия,Кол1,Знач1);    
    ТЗКопия.ВыбратьСтроки();    
    Пока ТЗКопия.ПолучитьСтроку() = 1 Do        
    Если (ТЗКопия.Кол2<>Знач2) ИЛИ (ТЗКопия.Кол3<>Знач3) ИЛИ (ТЗКопия.Кол3<>Знач3) Тогда
    Продолжить;        
    Иначе
    Возврат ТЗКопия.КолТЗ;     //Если номер строки неважен (например если эта ТЗКопия общая переменная),                         
    //эту колонку КолонкаТЗ не добавляем, и здесь передаем номер строки ТЗКопии        
    КонецЕсли;    
    КонецЦикла;    
    Возврат 0;
    КонецФункции
    
    
    
    
    
    
    
    
  13. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    Спасибо) Вообще можно было сделать функцию фильтра по нескольким значениям, было бы еще грамотнее, но это нужно еще сидеть думать :)
  14. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    А чего тут думать - в качестве фильтра нужно передать СписокЗначений и добавить цикл по размеру списка. Все
  15. TopicStarter Overlay
    Tanush
    Offline

    Tanush Опытный в 1С

    Регистрация:
    24 апр 2008
    Сообщения:
    96
    Симпатии:
    0
    Баллы:
    26
    Спасибо, ребята! Здорово помогли! Очень толково. Я немного переписала исправив ошибки:

    Код:
    Функция ФильтрТЗ(ТЗ,Ключ,КлючЗн)    
    вТЗ = СоздатьОбъект("ТаблицаЗначений");    
    
    //скопировали структуту ТЗ
    ТЗ.Выгрузить(вТЗ,1,1);    
    
    вТЗ.УдалитьСтроки();    
    
    КонСтр = 0;    
    НачСтр = 0;    
    ТЗ.Сортировать("+" + Ключ);    // отсортировать таблицу по колонке "Ключ"
    
    Если ТЗ.НайтиЗначение(КлючЗн,КонСтр,Ключ)>0 Тогда	// если значение найдено (в переменную КонСтр записывается номер найденной строки)
    // сортируем в обратном порядке
    ТЗ.Сортировать("-"+Ключ);	
    ТЗ.НайтиЗначение(КлючЗн,НачСтр,Ключ);        // НачСтр записывается номер найденной строки
    ТЗ.Выгрузить(вТЗ, НачСтр, ТЗ.КоличествоСтрок() - КонСтр + 1);    
    КонецЕсли;    
    
    Возврат вТЗ;
    КонецФункции
    
    //*********************************************************
    Функция ПоискПоТремТЗ(ТЗ,Знач1,Знач2,Знач3,Кол1,Кол2,Кол3) Экспорт
    Перем ТЗКопия, Индекс;
    
    ТЗ.Выгрузить(ТЗКопия);
    
    
    ТЗКопия.НоваяКолонка("КолонкаТЗ");
    
    Для Индекс=1 по ТЗКопия.КоличествоСтрок() Цикл
    ТЗКопия.УстановитьЗначение(Индекс, "КолонкаТЗ", Индекс);
    КонецЦикла;
    
    ТЗКопия = ФильтрТЗ(ТЗКопия, Кол1, Знач1);
    
    ТЗКопия.ВыбратьСтроки();
    
    Для Индекс = 1 По ТЗКопия.КоличествоСтрок() Цикл
    Если (ТЗКопия.ПолучитьЗначение(Индекс, Кол2) = Знач2) И (ТЗКопия.ПолучитьЗначение(Индекс, Кол3) = Знач3) Тогда
    Возврат ТЗКопия.КолонкаТЗ;        
    Иначе
    Продолжить;
    КонецЕсли;
    КонецЦикла;
    
    
    Возврат 0;
    КонецФункции
    

    Посмотрите, если не трудно. Все ОК?
  16. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    Все нормально, но я бы использовал цикл через ПолучитьСтроку()
    так красивее и правильнее
  17. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    норм..
    только еще есть "Знач4" и "Кол4", у нас опечатки
  18. TopicStarter Overlay
    Tanush
    Offline

    Tanush Опытный в 1С

    Регистрация:
    24 апр 2008
    Сообщения:
    96
    Симпатии:
    0
    Баллы:
    26
    Почему правильнее? Просто когда использую
    Код:
    ПолучитьСтроку()
    
    , то не могу получить номер строки. А как у меня если - то могу.

    Где они?
  19. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    Не можете? Значит не всеми методами пользуетесь...
    Код:
    НомСтр=ТЗКопия.НомерСтроки; //как раз вернет номер строки)))
    
    

Поделиться этой страницей