В то время как (верный) с повреждением плохая практика программирования?

Примечание: Неинициализированное смещение строки: *

Как видно из названия, возникает такой тип ошибки, когда вы, скорее всего, пытаетесь перебрать или найти значение из массива с не- существующий ключ.

Считаем, что вы пытаетесь показать каждую букву из $string

$string = 'ABCD'; 
for ($i=0, $len = strlen($string); $i <= $len; $i++){
    echo "$string[$i] \n"; 
}

. Вышеприведенный пример сгенерирует ( онлайн-демонстрацию ):

A
B
C
D
Notice: Uninitialized string offset: 4 in XXX on line X

И, как только скрипт заканчивается эхом D, вы получите ошибку, потому что внутри цикла for() вы сказали PHP, чтобы показать вам от первого до пятого символа строки из 'ABCD' Что, существует, но поскольку цикл начинает отсчитываться от 0 и эха D к моменту достижения значения 4, он выдает ошибку смещения.

Аналогичные ошибки:

54
задан emlai 9 April 2016 в 15:35
поделиться

21 ответ

Между этими двумя примерами существует несоответствие. Первое выполнится, "делают что-то", по крайней мере, один раз во время, даже если оператор никогда не верен. Второе только "сделает что-то", когда оператор оценит к истинному.

я думаю, что Вы ищете, цикл с условием продолжения. Я 100% соглашаются, что while (true) не хорошая идея, потому что из-за нее сложно поддерживать этот код и способ, которым Вы выходите из цикла, очень goto esque, который считают плохой практикой.

Попытка:

do {
  //do something
} while (!something);

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

44
ответ дан Michał Perłakowski 7 November 2019 в 07:46
поделиться

использование циклов как

, в то время как (1) {действительно наполняют}

, необходимо в некоторых ситуациях. Если Вы сделаете какое-либо программирование встроенных систем (думайте микроконтроллеры как PIC, MSP430 и программирование DSP), то тогда почти весь Ваш код будет в некоторое время (1) цикл. При кодировании для DSPS иногда Вам просто нужно некоторое время (1) {}, и остальная часть кода является процедурой обработки прерывания (ISR).

0
ответ дан devin 7 November 2019 в 07:46
поделиться

То, что Вашего друга рекомендуют, отличается от того, что Вы сделали. Ваш собственный код более сродни

do{
    // do something
}while(!<some condition>);

, которые всегда выполняют цикл, по крайней мере, однажды, независимо от условия.

, Но существуют повреждения времен, отлично хорошо, как упоминаются другими. В ответ на беспокойство Вашего друга "забывают повреждение", пишу я часто в следующей форме:

while(true){
    // do something
if(<some condition>) break;
    // continue do something
}

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

0
ответ дан billyswong 7 November 2019 в 07:46
поделиться

Было много разговора об удобочитаемости здесь и ее очень хорошо создано, но как со всеми циклами, которые не фиксируются в размере (т.е. сделайте, в то время как и в то время как) Вы работаете в риске.

His reasoning was that you could "forget the break" too easily and have an endless loop.

В некоторое время цикле Вы на самом деле просите процесс, который работает неограниченно долго, если чего-то не происходит, и если это, чего-то не происходит в определенном параметре, Вы получите точно, что Вы хотели... бесконечный цикл.

0
ответ дан Ólafur Waage 7 November 2019 в 07:46
поделиться

Я предпочитаю, в то время как(!) подход, потому что он более ясно и сразу передает намерение цикла.

0
ответ дан toad 7 November 2019 в 07:46
поделиться

Несколько преимуществ использования последней конструкции, которые прибывают по моему мнению:

  • легче понять то, что цикл обходится без поиска перерывов в коде цикла.

  • , если Вы не используете другие перерывы в коде цикла, существует только одна точка выхода в Вашем цикле, и это в то время как () условие.

  • обычно заканчивает тем, что был меньшим количеством кода, который добавляет к удобочитаемости.

0
ответ дан codelogic 7 November 2019 в 07:46
поделиться

Он, вероятно, корректен.

Функционально эти два могут быть идентичными.

Однако для удобочитаемость и понимание процесса выполнения программы, в то время как (условие) лучше. Повреждение порет больше goto своего рода. В то время как (условие) очень ясно на условиях, которые продолжают цикл и т.д. Это не означает, что повреждение является неправильным, просто может быть менее читаемым.

0
ответ дан Doug T. 7 November 2019 в 07:46
поделиться

Это не так , в то время как (верный) часть это плохо, но то, что необходимо повредиться или goto из него, который является проблемой. повреждение и goto не являются действительно приемлемыми методами управления потоком.

я также действительно не вижу точку. Даже в чем-то, что циклы через всю продолжительность программы, Вы можете, по крайней мере, иметь как булевская переменная под названием Выход или что-то, что Вы устанавливаете на истинный для выхода из цикла правильно в цикле как в то время как (! Выход)... Не только назвав повреждение в некоторой произвольной точке и выскакивающий,

0
ответ дан Gene Roberts 7 November 2019 в 07:46
поделиться

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

1
ответ дан mcrute 7 November 2019 в 07:46
поделиться

Существует существенно идентичный вопрос уже в ТАК в , ТО, В ТО ВРЕМЯ КАК TRUE†¦ BREAK†¦ ЗАКАНЧИВАЮТСЯ В ТО ВРЕМЯ КАК хороший дизайн? . @Glomek отвечают (в недооцененном сообщении):

Иногда это - очень хороший дизайн. См. Структурированное Программирование С Операторами перехода Donald Knuth для некоторых примеров. Я часто использую эту основную идею для циклов, которые выполняют "n с половиной времена", особенно читайте/обрабатывайте циклы. Однако я обычно пытаюсь иметь только один оператор завершения. Это облегчает рассуждать о состоянии программы после того, как цикл завершится.

Несколько позже, я ответил связанным, и также горестно недооценил, комментарий (частично, потому что я не заметил Glomek в первый раз вокруг, я думаю):

Одна захватывающая статья является "Структурным программированием Knuth с движением к Операторам" с 1974 (доступный в его книге 'Грамотное программирование', и вероятно в другом месте также). Это обсуждает, среди других вещей, управляемые способы убежать из циклов, и (не использование термина) loop-and-a-half оператор.

Ada также обеспечивает конструкции цикличного выполнения, включая [1 110]

loopname:
    loop
        ...
        exit loopname when ...condition...;
        ...
    end loop loopname;

, код исходного вопроса подобен этому в намерении.

Одно различие между ссылаемым, ТАКИМ ОБРАЗОМ, объект и это являются 'заключительным повреждением'; это - однократный цикл, который использует повреждение для выхода из цикла рано. Были вопросы на том, является ли это хорошим стилем также - у меня нет перекрестной ссылки под рукой.

3
ответ дан Community 7 November 2019 в 07:46
поделиться

Ответ идеального консультанта: это зависит. Большинство случаев, правильный поступок является или использованием некоторое время цикл

while (condition is true ) {
    // do something
}

или "повторением до", которое сделано в подобном языку C с

do {
    // do something
} while ( condition is true);

, Если любая из этих работ случаев, используйте их.

Иногда, как во внутреннем цикле сервера, Вы действительно подразумеваете, что программа должна продолжать идти до чего-то внешние прерывания он. (Рассмотрите, например, httpd демон - это не собирается останавливаться, если это не отказывает, или это зашло в завершение работы.)

ТОГДА И ТОЛЬКО ТОГДА использование некоторое время (1):

while(1) {
   accept connection
   fork child process
}

Заключительный случай является редким случаем, где Вы хотите внести свой вклад функции перед завершением. В этом случае используйте:

while(1) { // or for(;;)
   // do some stuff
   if (condition met) break;
   // otherwise do more stuff.
}
1
ответ дан Charlie Martin 7 November 2019 в 07:46
поделиться

Если существует один (и только один), неисключительное условие повреждения, помещая то условие непосредственно в конструкцию потока управления (в то время как) предпочтительно. Наблюдение, в то время как (верный) {...} Делает меня, поскольку читатель кода думает, что нет никакого простого способа перечислить условия повреждения и не заставляет меня думать, "смотрят тщательно на это и думают о тщательно об условиях повреждения (что установлено перед ними в текущем цикле и что, возможно, было установлено в предыдущем цикле)",

Короче говоря, я с Вашим коллегой в самом простом случае, но, в то время как (верный) {...} Весьма распространено.

1
ответ дан Larry OBrien 7 November 2019 в 07:46
поделиться

Это зависит от того, какой you’re, пытающийся сделать, но в целом я предпочитаю вставлять условное выражение в то время как.

  • It’s более простой, так как Вам не нужен другой тест в коде.
  • It’s легче читать, начиная с Вас don’t должны отправиться на охоту для повреждения в цикле.
  • You’re, перестраивающий колесо. Смысл того, в то время как должен сделать что-то пока тест, верен. Почему ниспровергают это путем помещения условия повреждения где-то в другом месте?

I’d используют некоторое время (истинный) цикл, если я писал демону или другому процессу, который должен работать, пока это не уничтожается.

1
ответ дан ieure 7 November 2019 в 07:46
поделиться

Когда-то Вам нужен бесконечный цикл, например, слушающий на порте или ожидающий соединения.

Поэтому, в то время как (верный)... не должен категоризированный как хорошая или плохая, ситуация, которой позволяют, решают, что использовать

2
ответ дан JRomio 7 November 2019 в 07:46
поделиться

Первое в порядке, если существует много способов повредиться от цикла, или если условия повреждения нельзя выразить легко наверху цикла (например, содержание цикла должно работать на полпути, но другая половина не должна работать на последнем повторении).

, Но если можно избежать его, Вы должны, потому что программирование должно быть о записи очень сложных вещей самым очевидным возможным способом, также реализуя опции правильно и производительно. Вот почему Ваш друг, в общем случае, корректном. Способ Вашего друга записать конструкции цикла намного более очевиден (предположение, что условия, описанные в предыдущем абзаце, не получают).

4
ответ дан yfeldblum 7 November 2019 в 07:46
поделиться

Javier сделал интересный комментарий к моему более раннему ответу (одно заключение в кавычки Wordsworth):

я думаю, в то время как (верный) {} более 'чистая' конструкция, чем в то время как (условие) {}.

и я не мог ответить соответственно в 300 символах (извините!)

В моем обучении и менторстве, я неофициально определил "сложность" как, "Сколько из остальной части кода я должен иметь в голове, чтобы быть в состоянии понять эту одну строку или выражение?" Чем больше материала я имею для мысли, тем более сложен код. Чем больше код говорит мне явно, тем менее сложный.

Так, с целью сокращения сложности, позволяют мне ответить Javier с точки зрения полноты и силы, а не чистоты.

я думаю об этом фрагменте кода:

while (c1) {
    // p1
    a1;
    // p2
    ...
    // pz
    az;
}

как выражение двух вещей одновременно:

  1. (все) тело будет повторено целых c1, остается верным, и
  2. в точке 1, где a1 выполняется, c1 , гарантировал для содержания.

различием является одна из перспективы; первый из них имеет отношение к внешнему, динамическому поведению всего цикла в целом, в то время как второе полезно для понимания внутренней, статической гарантии, на которую я могу рассчитывать при размышлении [приблизительно 116] в частности. Конечно, результирующий эффект a1 может делать недействительным c1, требуя, чтобы я думал тяжелее о том, на что я могу рассчитывать в точке 2, и т.д.

, давайте поместим определенный (крошечный) пример на месте для размышления об условии и первом действии:

while (index < length(someString)) {
    // p1
    char c = someString.charAt(index++);
    // p2
    ...
}

"внешняя" проблема - то, что цикл ясно делает что-то в someString, который может только быть сделан целых index, расположен в someString. Это настраивает ожидание, что мы будем изменять или index или someString в теле (в местоположении и способе, не известном, пока я не исследую тело) так, чтобы завершение в конечном счете произошло. Это дает мне и контекст и ожидание размышления о теле.

"внутренняя" проблема - то, что нам гарантируют это, следующий момент действия 1 будет законен, поэтому при чтении кода в точке 2 я могу думать о том, что делается с символьным I значения, знают , был по закону получен. (Мы не можем даже оценить условие, если someString пустой указатель касательно, но я также предполагаю, что мы приняли меры против этого в контексте вокруг этого примера!)

Напротив, цикл формы:

while (true) {
    // p1
    a1;
    // p2
    ...
}

подводит меня по обеим проблемам. На внешнем уровне меня оставляют, задаваясь вопросом, означает ли это, что я действительно должен ожидать, что этот цикл циклически повторится навсегда (например, основной цикл отправки события операционной системы), или существует ли что-то еще продолжение. Это не дает мне ни явного контекста для чтения тела, ни ожидания того, что составляет продвижение к (неопределенному) завершению.

На внутреннем уровне, я имею абсолютно никакой явная гарантия о любых обстоятельствах, которые могут содержать в точке 1. Условие true, который, конечно, верен везде, является самым слабым оператором о том, что мы можем знать в любой точке в программе. Понимание предварительных условий действия является очень ценной информацией при попытке думать о том, что выполняет действие!

Так, я предполагаю, что while (true) ... идиома является намного более неполной и слабой, и поэтому более сложной, чем [1 117] согласно логике, которую я описал выше.

6
ответ дан joel.neely 7 November 2019 в 07:46
поделиться

в то время как (верный) мог бы иметь смысл, если у Вас есть много операторов, и Вы хотите остановиться, если сбой

 while (true) {
     if (!function1() ) return;   
     if (!function2() ) return;   
     if (!function3() ) return;   
     if (!function4() ) return;  
   }

лучше, чем

 while (!fail) {
     if (!fail) {
       fail = function1()
     }           
     if (!fail) {
       fail = function2()
     }  
     ........

   }
9
ответ дан Martin Beckett 7 November 2019 в 07:46
поделиться

Я предпочитаю

while(!<some condition>) {
    //do something
}

, но я думаю, что это - больше вопрос удобочитаемости, а не потенциал для "упущения повреждения". Я думаю, что упущение эти break является довольно слабым аргументом, поскольку это было бы ошибкой, и Вы найдете и зафиксируете его сразу же.

аргумент я имею против использования break для выхода из бесконечного цикла, то, что Вы по существу используете break оператор как goto. Я не неукоснительно против использования goto (если язык поддерживает его, это - справедливая игра), но я действительно пытаюсь заменить его, если существует более читаемая альтернатива.

В случае многих break точки я заменил бы их [1 112]

while( !<some condition> ||
       !<some other condition> ||
       !<something completely different> ) {
    //do something
}

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

12
ответ дан Bill the Lizard 7 November 2019 в 07:46
поделиться

Когда можно записать код в форме

while (condition) { ... }

или

while (!condition) { ... }

с [1 116] никакие выходы (break, continue, или goto) в теле , та форма предпочтена, потому что кто-то может считать код, и понимают условие завершения только путем рассмотрения заголовка . Это хорошо.

, Но много циклов не соответствуют этой модели, и , бесконечный цикл с явным выходом (выходами) в середине является благородной моделью . (Циклы с continue обычно более трудно понять, чем циклы с break.), Если Вы хотите, чтобы некоторое доказательство или полномочия процитировали, посмотрите не далее, чем известная статья Don Knuth на Структурное программирование с Операторами перехода ; Вы найдете все примеры, аргументы и объяснения, которые Вы могли хотеть.

деталь А идиомы: запись while (true) { ... } бренды Вы как старый программист Паскаля или возможно в эти дни программист Java. Если Вы пишете в C или C++, предпочтительная идиома

for (;;) { ... }

нет никакого серьезного основания для этого, но необходимо записать ему этот путь, потому что это - путь C, программисты ожидают видеть его.

22
ответ дан Norman Ramsey 7 November 2019 в 07:46
поделиться

Для заключения в кавычки, который отметил разработчика прошедших дней, Wordsworth:

...
, По правде говоря, тюрьма, к которой мы обрекаем
Сами, никакая тюрьма; и следовательно для меня,
В различных капризах, это было времяпрепровождение, которое будет связано
В рамках скудного графика Сонета земли;
Рад, если некоторые души (для таких их потребностей должен быть)
, Кто чувствовал, вес слишком большой свободы,
Должны найти краткое утешение там, как я нашел.

Wordsworth принял строгие требования сонета как кадр освобождения, а не как смирительная рубашка. Я предположил бы, что основа "структурного программирования" об отказе от свободы создать произвольно сложные потоковые графы в пользу простоты освобождения понимания.

я свободно соглашаюсь, что иногда ранний выход является самым простым способом выразить действие. Однако мой опыт состоял в том, что, когда я вынуждаю меня использовать самые простые управляющие структуры (и действительно думать о разработке в рамках тех ограничений), я чаще всего нахожу, что результатом является более простой, более ясный код. Недостаток с [1 116]

while (true) {
    action0;
    if (test0) break;
    action1;
}

состоит в том, что легко позволить action0, и action1 становятся большими и большими блоками кода, или добавить "просто еще одну" тестовую последовательность действий повреждения, пока не становится трудным указать на определенную строку и ответить на вопрос, "Что условия, я знаю, содержат в этой точке?" Так, не делая правила для других программистов, я стараюсь избегать while (true) {...} идиома в моем собственном коде, когда это возможно.

29
ответ дан joel.neely 7 November 2019 в 07:46
поделиться

Я думаю преимущество использования, "в то время как (верный)" должен, вероятно, позволить нескольким выйти из условия, легче записать особенно, если они выходят, условие должно появиться в различном месте в блоке кода. Однако для меня, это могло быть хаотично, когда у меня есть к пробному прогону код, чтобы видеть, как код взаимодействует.

Лично я буду стараться избегать, в то время как (верный). Причина состоит в том, что каждый раз, когда я оглядываюсь назад на код, записанный ранее, я обычно нахожу, что должен выяснить, когда он выполняет/завершает больше, чем, что он на самом деле делает. Поэтому необходимость определить местоположение "повреждений" сначала немного неприятна для меня.

, Если существует потребность в нескольких, выходят из условия, я склонен осуществлять рефакторинг логику определения условия в отдельную функцию так, чтобы блок цикла выглядел чистым и легче понять.

1
ответ дан Conrad 7 November 2019 в 07:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: