Вопрос на логику (Функции и циклы)

Dr_grizzly
Dr_grizzly аватар
Offline
Зарегистрирован: 07.12.2015

Всем привет! Не могу ответить на свой вопрос сам, решил спросить вас))

Есть функция, в которой вложен бесконечный цикл.

bool read(char *buffer, int count, unsigned int timeout= DEFAULT_TIMEOUT, unsigned int chartimeout= DEFAULT_INTERCHAR_TIMEOUT) {
    int i = 0;
    unsigned long timerStart, prevChar;
    timerStart = millis();
    prevChar = 0;
    while(1) {
        while (sim_check_readable()) {
            char c = Serial1.read();
            prevChar = millis();
            buffer[i++] = c;
            if (i >= count) { 
            //break;
            return true; 
            }
        }
        
        if (i >= count) break;
        
        if ((unsigned long) (millis() - timerStart) > timeout * 1000UL) {
          //break;
           return false;
            
        }
        //If interchar Timeout => return FALSE. So we can return sooner from this function. Not DO it if we dont recieve at least one char (prevChar <> 0)
        if (((unsigned long) (millis() - prevChar) > chartimeout) && (prevChar != 0)) {
        //  break;
          return false;
            
        }
    }
}

Вопрос - как правильно разрывать бесконечный цикл? Break - прервывает цикл, Return должна возвратить значение Ture или False в зависимости от выполнения фукнции. Дак вот правильно ли я делаю в этом коде выходя из цикла командой Return? или надо сначала break а потом Return?

Николай Коростелев
Offline
Зарегистрирован: 05.04.2016

как написано  - правильно.

 

if (i >= count) break; 

что вернёт функция в этом случае?

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А что именно Вас смущает? Тогда и ответить можно.

Просто "правильно" понятие широкое. Например, если Вы спрсоите фаната "структурного программирования" (есть такая секта), то он Вам скажет, что функция (как и цикл) должна иметь только один вход и один выход, а у Вас они имеют по три. Если же Вы спросите человека? привыкшего к низкоуровневым делам, он скажет. что всё у Вас нормально. А если Вы спросите зануду - педанта эффективности, он скажет, что необходимо поменять местами условия в строке 25, т.к. второе явно быстрее первого :)

Dr_grizzly
Dr_grizzly аватар
Offline
Зарегистрирован: 07.12.2015

т.е 25 строка теперь выглядеть так должна if ((prevChar != 0) && ((unsigned long) (millis() - prevChar) > chartimeout)) ?

Дак все таки, return прервет цикл с возвратом результата? или нужно остановить цикл, а потом снова проверив условия вернуть результат? ))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да, нормально он его прервёт, не парьтесь.

А про ту строку, видите, если компилятор генерирует т.н. "ленивую логику", то когда условия соединены по И, он генерирует проверку первого и, если оно false, то второе не проверяется вовсе. Поэтому первым обычно ставят то, кторое чаще бывает false или более дешёвое по проверке (чтобы дорогое хоть иногда не проверять). А если поставить наоборот, то дорогое будет проверяться всегда.

Dr_grizzly
Dr_grizzly аватар
Offline
Зарегистрирован: 07.12.2015

Спасибо большое! ))

Dr_grizzly
Dr_grizzly аватар
Offline
Зарегистрирован: 07.12.2015

Николай Коростелев пишет:

как написано  - правильно.

if (i >= count) break; 

что вернёт функция в этом случае?

Ууупс )) пропустил эту поправку))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Dr_grizzly пишет:

Ууупс )) пропустил эту поправку))

Странно, что Вы её пропустили. Компилятор Вам про это говорил. Если у Вас выключены предупреждения (они выключены по умолчанию в IDE) - включите. Сэкономит кучу времени и нервов.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Не правильно вы сказали про фанатов "структурного программирования". Фанаты "структурного программирования" воевали с GO ТО. И похоже победили. Сейчас GO ТО нигде не найдешь.   break -это завоевание фанатов "структурного программирования" А  вот "фанаты модульного проектирования" скорее проиграли. У них размер модуля должен быть с размером в экран. И несколько операторов в строке это их стиль.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

qwone пишет:

Не правильно вы сказали про фанатов "структурного программирования". Фанаты "структурного программирования" воевали с GO ТО

Да, нет, "один вход и один выход" - это один из важнейших постулатов их символа веры, узко Вы их понимаете.

И вообще, наберите goto в строке поиска в правом верхнем углу - под 200 результатов.

А в новейших стандартах языков программирования появляются такие варианты goto, что "мама не горюй". Как Вам goto с адресом перехода, хранящимся в переменной? Можете запустить на Ардуинке - без проблем работает.

void setup() {
	Serial.begin(115200);
	void * lab[] = {&&kaka, &&mumu, &&kuku};
	const int totalLabels = sizeof(lab)/sizeof(lab[0]);
	int n = 0;
beg:
	if (n == totalLabels) {
		void *finlabel = &&fin;
		goto *finlabel;	
	}
	goto *lab[n++];	// адрес перехода в переменной
	
kaka:
	Serial.println("Kaka Label Area");
	goto beg; 

mumu:
	Serial.println("Mumu Label Area");
	goto beg; 

kuku:
	Serial.println("Kuku Label Area");
	goto beg; 

fin:
	Serial.println("fin Label Area");
}

void loop() {
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вот опять же . Или вы не знаете истоков, или специально дезинформируете. 

Цитирую :Структу́рное программи́рование — методология разработки программного обеспечения, в основе которой лежит представление программы в виде иерархической структуры блоков. Предложена в 1970-х годах Э. Дейкстрой и др.

В соответствии с данной методологией любая программа строится без использования оператора goto из трёх базовых управляющих структур: последовательность, ветвление, цикл; кроме того, используются подпрограммы. При этом разработка программы ведётся пошагово, методом «сверху вниз».

https://goo.gl/L2yLMb

 Я бы промолчал бы . Если бы сначала был в лагере тех, кто без GO ТО не мог программировать. А потом переучивался по Дейкстре. читал ее в переводе. И да блок-схемы расчитаны под GO TO программирование.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

О, да Вы, Википедик! Правда, в той статье в Википедии было слишком много букв и Вы её до конца не осилили.

Откройте ту самую статью, которую Вы цитировали. Найдите там раздел "Принципы структурного программирования" и прочитайте принцип №6: "Все перечисленные конструкции должны иметь один вход и один выход".

Вам показать этот же "постулат веры" в первоисточнике? Или Вы уже поверили, что я знаю, о чём говорю?

P.S. 
Кстати, существовали гнусные еретики, которые даже считали, что структурное программирование и использование goto не противоречит друг другу. Разумееется, это ересь, но надеюсь, что авторитет автора вот этой статьи и его право иметь и высказывать своё, уважаемое всеми программистами, мнение не вызывает сомнений?

Dr_grizzly
Dr_grizzly аватар
Offline
Зарегистрирован: 07.12.2015

ЕвгенийП пишет:

Dr_grizzly пишет:

Ууупс )) пропустил эту поправку))

Странно, что Вы её пропустили. Компилятор Вам про это говорил. Если у Вас выключены предупреждения (они выключены по умолчанию в IDE) - включите. Сэкономит кучу времени и нервов.

Абалдеть ))) включил эти галочки и теперь вижу еще мелкие косячки компиляции))) например

 for(int i=0; i<strlen(cmd); i++)  - ругается что сравниваются переменные не одинакового типа, signed и unsigned ))) созадал переменную int и в нее запихнул значение strlen, теперь не ругается))) хотя в целом то код работает, на что это могло повлиять не знаю... просто "правило хорошего тона"?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Dr_grizzly пишет:

 for(int i=0; i<strlen(cmd); i++)  - ругается что сравниваются переменные не одинакового типа, signed и unsigned ))) созадал переменную int и в нее запихнул значение strlen, теперь не ругается))) хотя в целом то код работает, на что это могло повлиять не знаю... просто "правило хорошего тона"?

В некоторых случаях может повлиять, хотя часто не влияет. Лучше иметь привычку так не делать.