Skocz do zawartości

Pomocna odpowiedź

2 minuty temu, Mikolajkie napisał:

Czy mógłbyś dać mi jakieś sytuacje, w których używać osobnych if'ów, a else/if'a? 🙂

Jestem marnym autorytetem raczej🤭 no ale używasz w danej chwili tego co Ci najbardziej pasuje 😉 w przypadku else/if warunki są sprawdzane po kolei aż do napotkania prawdy, wtedy już reszty tej "drabiny" nie sprawdzamy...przez co kod może być szybszy (narazie Cię to nie interesuje) ciężko mi teraz jakiś konkretny przykład przytoczyć 🙄 osobiście ja używam else/if bardzo rzadko...zazwyczaj same if'y z else wystarczają lub switch case

Okej, dzięki. Ja zwykle będę korzystał z else/if. Ale zanim napiszę jakiś warunek z else/if to muszę pomyśleć, czy wszystko będzie działać.

Tutaj w kodzie poniżej są dwa osobne warunki, bo z else/if nie działałoby (chyba). Jeśli dałoby się to jakoś upchać w else/if to ten drugi warunek nigdy nie zadziałałby. Jeśli źle myślę to proszę mnie poprawić 😄

if(digitalRead(przycisk1) == LOW || digitalRead(przycisk2)) {
  digitalWrite(diodaZielona, HIGH);
} else {
  digitalWrite(diodaZielone, LOW);
}

if(digitalRead(przycisk1) == LOW && digitalRead(przycisk2)) {
  digitalWrite(diodaCzerwona, HIGH);
} else {
  digitalWrite(diodaCzerwona, LOW);
}

 

13 minut temu, Mikolajkie napisał:

Czy mógłbyś dać mi jakieś sytuacje, w których używać osobnych if'ów, a else/if'a? 🙂

void process_command(parsed_cmd_t* cmd)
{
	if(strcmp((char*) cmd->name, LED_CMD) == 0 && cmd->type == CMD_SET)
		switch_led_cmd(cmd);
	else if(strcmp((char*) cmd->name, SAVE_CMD) == 0 && cmd->type == CMD_SET)
		save_cmd(cmd);

	else if(strcmp((char*) cmd->name, FAN_SPEED_CMD) == 0)
		default_fan_speed_cmd(cmd);
	else if(strcmp((char*) cmd->name, LIGHT_VALUE_CMD) == 0)
		default_light_value_cmd(cmd);
	else if(strcmp((char*) cmd->name, ON_TIME_CMD) == 0)
		on_time_cmd(cmd);
	else if(strcmp((char*) cmd->name, FAN_DELAY_CMD) == 0)
		fan_delay_cmd(cmd);
	else if(strcmp((char*) cmd->name, FAN_TIME_CMD) == 0)
		fan_time_cmd(cmd);
	else if(strcmp((char*) cmd->name, FAN_DELTA_CMD) == 0)
		fan_delta_cmd(cmd);
	else if(strcmp((char*) cmd->name, LIGHT_DELTA_CMD) == 0)
		light_delta_cmd(cmd);

	else if(strcmp((char*) cmd->name, LIGHT_ACTIVE_R_CMD) == 0)
		active_r(cmd);
	else if(strcmp((char*) cmd->name, LIGHT_ACTIVE_G_CMD) == 0)
		active_g(cmd);
	else if(strcmp((char*) cmd->name, LIGHT_ACTIVE_B_CMD) == 0)
		active_b(cmd);

	else if(strcmp((char*) cmd->name, LIGHT_INACTIVE_R_CMD) == 0)
		inactive_r(cmd);
	else if(strcmp((char*) cmd->name, LIGHT_INACTIVE_G_CMD) == 0)
		inactive_g(cmd);
	else if(strcmp((char*) cmd->name, LIGHT_INACTIVE_B_CMD) == 0)
		inactive_b(cmd);

}

Jest to sekcja wykrywająca komendę i wykonująca odpowiednią funkcję za nią odpowiedzialną. Niestety komendy są w formie tekstowej, więc trzeba było się pomęczyć z strcmp, co jest dość wolne, ale w tym przypadku to nie ma znaczenia 😉 

// If room is not occupied, time passed and fan is not active
	if(roomIsOccupied == FALSE)
	{
		emptyTimer += deltaTime;
		if(emptyTimer / TICKS_PER_SECOND > settings->fanAutoCleanupDelay && cleanupFanActive == FALSE)
		{
			emptyTimer = 0; // Reset timer
			cleanupFanActive = TRUE; // Activate fan
		}
		else if(emptyTimer / TICKS_PER_SECOND > settings->fanAutoCleanupTime && cleanupFanActive == TRUE)
		{
			emptyTimer = 0; // Reset timer
			cleanupFanActive = FALSE; // Deactivate fan
		}
	}

Tutaj warunek główny (brak osoby w pomieszczeniu) musi być spełniony, lepiej było go zrobić jako osobny, gdyż redukuje to duplikację kodu oraz jego podwójne sprawdzanie w najgorszym wypadku - w skrócie program jest szybszy i czytelniejszy.

	// Process button inputs
	button_t* fanUp = process_button(BTN_FAN_UP);
	if(fanUp->stable == TRUE && fanUp->state == GPIO_PIN_SET && fanUp->handled == FALSE)
	{
		config->fanSpeed += config->fanSpeedDelta;

		fanUp->handled = TRUE; // Handled now ;)
	}

	button_t* fanDn = process_button(BTN_FAN_DN);
	if(fanDn->stable == TRUE && fanDn->state == GPIO_PIN_SET && fanDn->handled == FALSE)
	{
		config->fanSpeed -= config->fanSpeedDelta;

		fanDn->handled = TRUE; // Handled now ;)
	}

	button_t* lightUp = process_button(BTN_LIGHT_UP);
	if(lightUp->stable == TRUE && lightUp->state == GPIO_PIN_SET && lightUp->handled == FALSE)
	{
		config->lightValue += config->lightDelta;

		lightUp->handled = TRUE; // Handled now ;)
	}


	button_t* lightDn = process_button(BTN_LIGHT_DN);
	if(lightDn->stable == TRUE && lightDn->state == GPIO_PIN_SET && lightDn->handled == FALSE)
	{
		config->lightValue -= config->lightDelta;

		lightDn->handled = TRUE; // Handled now ;)
	}

Przyciski mogą być naciśnięte w tym samym momencie. Stąd użycie osobnych if'ów dla każdego z przycisków.

Ogólnie to zazwyczaj zależy od logiki aplikacji (i optymalizacji wydajności).

  • Lubię! 1
(edytowany)

Gdyby upchać w else/if to jak będzie to działało? Pierwszy warunek zawsze będzie spełniony i po tym od razu program wychodzi z tego wszystkiego. Więc na jakiej zasadzie mogłoby to działać i jak wyglądałby kod? Teraz jest to czytelne, ale czytelniejsze są dla mnie else/if 🙂

Edytowano przez Mikolajkie
10 minut temu, Mikolajkie napisał:

Teraz jest to czytelne, ale czytelniejsze są dla mnie else/if 🙂

Poprostu musiałbyś zrobić else/if dla każdej z 4 możliwości ustawień guzików...było by to gorzej czytelne i dłuższe 😉

(edytowany)

@farmaceuta Dobrze, już chyba wszystko rozumiem. Osobne if'y są czytelniejsze w takich przypadkach. Dzięki za wytłumaczenie i pomoc 😉

Edytowano przez Mikolajkie
45 minut temu, ethanak napisał:

Tu jest jeszcze jeden kruczek...

Ważne jest, aby stan czegoś zewnętrznego (np. przycisku) czytać tylko raz - w przeciwnym przypadku może się zmienić między kolejnymi instrukcjami i się okaże, że żaden warunek nie jest spełniony. Przykład błędnego kodu:

if (digitalRead(X) == LOW) zapal_diodę();
if (digitalRead(X) == HIGH) zgaś_diodę();

Kod z podanego przykładu można bardzo ładnie uprościć.

Zacznę może jednak od tego dobrego zwyczaju czytania tylko raz:

bool p1 = digitalRead(przycisk1);
bool p2 = digitalRead(przycisk2);

Teraz mamy coś takiego:

if(!p1 || p2)) { // to po podstawieniu zmiennych do warunku
  digitalWrite(diodaZielona, HIGH);
} else {
  digitalWrite(diodaZielone, LOW);
}

Można stąd w ogóle wywalić if razem z else:

digitalWrite(diodaZielona, !p1 || p2);

Zadziała dokładnie tak samo...

To samo można zrobić z drugim ifem - i w ten sposób pozbywamy się zarówno problematycznego wielokrotnego odczytu stanu pinu jak i ifów w ogóle (czyli dyskusja o "else" przestaje mieć sens) 🙂

Ja tylko przypomnę pewne autentyczne zdarzenie sprzed lat...

Kod był w Pythonie, bibliotekę pisałem ja, reszta w liczbie programistów sztuk trzech zajmowała się pisaniem aplikacji. Fragment biblioyeki wyglądał mniej więcej tak:

if warunek1:
  czynność_pierwsza()
elif warunek2:
  czynność_druga()
  
if warunek3:
  czynność_trzecia()
elif warukek4:
  czynność_czwarta()
  

No i w pewnym momencie aplikacja przestała działać... po paru godzinach szukania błędu w aplikacji jeden z młodych dumny jak paw stwierdził "czego wy szukacie, tam w bibliotece był błąd, był if i zamieniłem na elif".

Oczywiście jego kawałek kodu bazujący na "poprawionym" kodzie biblioteki działał... 

Stąd biorą się zwyczaje umieszczania w kodzie komentarzy zawierających słowa ogólnie uznane za nieprzyzwoite 🙂

 

 

@ethanak w formie którą lubię. 

Muszę to jeszcze parę razy przeczytać;)

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...