FORUM

Polecenia cz.5

Odpowiedz

Emotikony
:D :) ;) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :arrow: :| :mrgreen: :geek: :ugeek:

BBCode włączony
[Img] włączony
[Flash] wyłączony
[URL] włączony
Emotikony włączone

Przegląd tematu
   

Rozwiń widok Przegląd tematu: Polecenia cz.5

Polecenia cz.5

autor: Erni86 » 12 sie 2021, 10:11

Polecenia

W języku C zaimplementowano wiele poleceń. W tym podrozdziale omówimy niektóre z nich i zobaczymy, jak można je zastosować w szkicach.

IF
Do tej pory zakładaliśmy, że linie kodu umieszczone w szkicu będą wykonywane jedna po drugiej, bez żadnych wyjątków. Ale co, jeżeli tego nie chcesz? Co, jeżeli chcesz wykonać tylko część kodu, zależnie od jakichś uwarunkowań? Wróćmy do przykładu, w którym dioda LED błyskała z coraz niższą częstotliwością. W tej chwili dioda będzie migać coraz to wolniej i wolniej, aż błysk będzie trwał godzinami. Przyjrzyjmy się temu, jak można sprawić, by częstotliwość błyskania diody po osiągnięciu pewnej dolnej wartości znów wracała do wartości początkowej. Aby tego dokonać, musisz zastosować polecenie
if. Poniżej zamieszczono zmodyfiko­wany szkic. Wypróbuj go.

int ledPin = 13;
int delayPeriod 100;

void setup() {
pinMode(ledPin, OUTPUT) ;
}

void loop() {
digitalWrite(l edPin, HIGH) ;
delay (delayPeriod) ;
digitalWrite(ledPin, LOW);
delay (delayPeriod) ;
delayPeriod = delayPeriod + 100 ;
if (delayPeriod > 1000)
{
delayPeriod 100;
}
}

Polecenie if wygląda podobnie do definicji funkcji, jednakże jest to tylko powierzch­niowe podobieństwo. Wyrażenie zawarte w nawiasach nie jest argumentem. Wyrażenie to nazywamy warunkiem. W zaprezentowanym przykładzie warunkiem jest to, że zmienna del ayPeri od ma wartość większą od 3000. Jeżeli ten warunek będzie spełniony, wykonane zostaną polecenia objęte nawiasami klamrowymi. W tym przypadku kod zawarty w nawia­sach klamrowych nadaje zmiennej del ayPeri od ponownie wartość 100. Jeżeli warunek nie będzie spełniony, Arduino zignoruje kod zawarty w nawiasach klam­rowych i będzie wykonywało kolejne operacje. W naszym przykładzie po poleceniu i f nie ma żadnej kolejnej instrukcji, a więc Arduino będzie ponownie wykonywało funkcję loop. Przeanalizowanie sekwencji kodu pozwoli Ci zrozumieć jego działanie. Oto lista prze­prowadzanych operacji:

1. Arduino uruchamia funkcję setup i inicjalizuje złącze diody LED tak, aby działało ono jako wyjście.
2. Arduino uruchamia funkcję loop.
3. Dioda zostaje włączona.
4. Arduino odczekuje określoną ilość czasu.
5. Dioda zostaje wyłączona.
6. Arduino odczekuje określoną ilość czasu.
7. Do wartości zmiennej del ayPeri od zostaje dodana liczba 100.
8. Jeżeli wartość zmiennej delayPeriod jest większa od 3000, zmiennej tej przypisywana jest ponownie wartość 100.
9. Operacje zostają wykonane ponownie, zaczynając od punktu drugiego.

Zastosowaliśmy znak większości (> ). Jest to jeden z przykładów operatorów porówny­wania

OPERATORY ARYTMETYCZNE

OPERATOR SKŁADNIA OPIS
= a=b Powoduje przypisanie wartości zmiennej b do a
+ a+b Zwraca wartość sumy wyrażeń
- a-b Zwraca wartość różnicy wyrażeń a - b
* a*b Zwraca wartość iloczynu wyrażeń
/ a/b Zwraca wartość dzielenia a przez b
% a%b Zwraca resztę z dzielenia

Przykłady:
int x,y,z;
x=9; //zmiennej x przypisaliśmy wartość 9
y=x+3;
z=y-2;
x=x*2;
y=x/3;
z=5%2; //reszta z dzielenia z=1

OPERATORY BITOWE

OPERATOR SKŁADNIA OPIS
& a&b Wykonuje bitową operację AND
^ a^b Wykonuje bitową operację XOR
| a|b Wykonuje bitową operację OR
~ a=~a Wykonuje bitową negację liczby
<< a<<b Przesuwa bity w lewo o b miejsc
>> a>>b Przesuwa bity w prawo o b miejsc

Przykłady:
int a = 92; // binarnie: 0000000001011100
int b = 101; // binarnie: 0000000001100101
int c = a & b; // wynik: 0000000001000100
int d = a | b; // wynik: 0000000001111101
int x = 12; // binarnie: 1100
int y = 10; // binarnie: 1010
int z = x ^ y; // wynik: 0110
int a = 103; // binarnie: 0000000001100111
int b = ~a; // wynik: 1111111110011000
int a = 5; // binarnie: 0000000000000101
int b = a << 3; // binarnie: 0000000000101000
int c = b >> 3; // binarnie: 0000000000000101

OPERATORY PRZYPISANI
OPERATOR SKŁADNIA OPIS
++ a++ lub ++a Inkrementacja - zwraca wartość i zwiększa a o 1 (lub zwiększa i zwraca wartość)
-- a-- lub --a Dekrementacja - zwraca wartość i zmniejsza a o 1 (lub zmniejsza i zwraca wartość)
+= a+=b Powoduje przypisanie wartości a+b do zmiennej a
-= a-=b Powoduje przypisanie wartości a-b do zmiennej a
*= a*=b Przypisuje wartość wyrażenia a*b do zmiennej a
/= a/=b Przypisuje wartość wyrażenia a/b do zmiennej a
&= a&=2 Wykonuje iloczyn bitowy a i 2
|= a|=10 Wykonuje sumę bitową a i 10

Przykłady:
int x;
x=9; //zmiennej x przypisaliśmy wartość 9
x++; //x=10
x--; //x=9
x+=2; //x=11
x-=3; //x=8

OPERATORY PORÓWNANIA

OPERATOR SKŁADNIA OPIS
== a==b Zwraca TRUE jeśli oba wyrażenia są sobie równe
!= a!=b Zwraca TRUE kiedy oba wyrażenia są różne
< a<b Zwraca TRUE kiedy wyrażenie a jest mniejsze od b
> a>b Zwraca TRUE kiedy pierwsze wyrażenie jest większe od drugiego
>= a>=b Zwraca TRUE kiedy a jest większe lub równe b
<= a<=b Zwraca TRUE kiedy a jest mniejsze lub równe b
&& a && b Zwraca TRUE, jeśli obra wyrażenia są prawdziwe
|| a || b Zwraca TRUE, jeśli któreś z wyrażeń jest prawdziwe
! !a Zmienia wartość logiczną wyrażenia na przeciwną

Przykłady:
int x;
if(x==9) // prawda gdy x równe 9
if(x!=9) // prawda gdy x różne od 9
if(x<9) // prawda gdy x mniejsze od 9
if(x>9) // prawda gdy x większe od 9
if(x<=9) // prawda gdy x mniejsze lub równe 9
if((x<5)&&(x>2)) // prawda gdy x2
if((x<5)||(x>8)) // prawda gdy x8

W celu porównania dwóch liczb stosowany jest operator ==. Ten podwójny znak rów­ności jest często mylony z pojedynczym znakiem równości ( = ), który jest stosowany do przypisywania wartości do zmiennych. Istnieje również nieco inna forma polecenia i f, która pozwala wykonać jeden zestaw operacji, gdy warunek jest spełniony (jest prawdziwy), i inny zestaw operacji, gdy warunek nie jest spełniony (jest fałszywy). Taka operacja zostanie omówiona na podstawie przykła­dów zamieszczonych w dalszej czesci.

FOR
Poza wykonywaniem różnych poleceń ze względu na różne warunki możesz często potrze­bować wykonania w programie serii instrukcji określoną liczbę razy. Wiesz, że możesz to wykonać przy użyciu funkcji loop. Po wykonaniu wszystkich instrukcji znajdujących się w pętli loop instrukcje te zostaną automatycznie wykonane ponownie. Czasem potrzebna jest jednakże bardziej ścisła kontrola nad takim zapętleniem operacji. Na przykład chcąc napisać szkic powodujący dwadzieścia błysków, a następnie po trzech sekundach przerwy ponownie uruchamiający błyski, możesz powtarzać wielokrotnie tę samą sekwencję kodu w funkcji loop, co pokazano poniżej:

int ledPin = 13 ;
int delayPeriod = 250 ;

void setup ( )
{
pinMode ( ledPin , OUTPUT ) ;
}

voidloop ( )
{
digital Write ( ledPin , HIGH) ;
delay (delayPeriod ) ;
digitalWrite (ledPin , LOW) ;
delay (delayPeriod ) ;

digitalWrite ( ledPin , H I GH) ;
delay (delayPeriod ) ;
digitalWrite ( ledPin , LOW) ;
delay (delayPeriod ) ;

digitalWrite ( ledPin , H I GH) ;
delay (delayPeriod ) ;
digitalWrite ( ledPin , LOW) ;
delay (delayPeriod ) ;
//powyższe cztery linie kodu należy powtórzyć jeszcze 1 7 razy
delay ( 3000);
}

Taka operacja wymaga napisania dużej ilości kodu. Istnieją lepsze sposoby na przepro­wadzenie takiej operacji. Zacznijmy od przeanalizowania zastosowania w tym celu pętli for, a następnie przeanalizujmy sposób przeprowadzenia tej operacji przy użyciu licznika i polecenia if.

Jak widzisz, poniższy szkic, wykonujący to samo zadanie przy użyciu pętli for, jest o
wiele krótszy.

int ledPin = 13 ;
intdelayPeriod = 250 ;

void setup ( )
{
pinMode ( ledPi n , OUTPUT) ;
}
void loop ( ) {
for ( int i = O ; i < 20 ; i ++) {
digitalWrite ( ledPin , HIGH ) ;
delay (delayPeriod ) ;
digitalWrite ( ledPin , LOW ) ;
delay (delayPeriod ) ;
}
delay ( 3000) ;
}

Pętla for przypomina funkcję, do której przekazywane są trzy argumenty. W przypadku tej pętli „argumenty" są jednakże oddzielane średnikami, a nie przecinkami. Jest to jedna z zasad języka C. Kompilator poinformuje Cię, gdy zastosujesz nieprawidłowy znak sepa­rujący. Nawiasy po for zawierają deklarację zmiennej. Zmienna ta jest stosowana jako licznik. W nawiasach nadajemy również jej wartość początkową - w naszym przypadku jest to O. Drugim elementem zawartym w nawiasie jest warunek, który musi być prawdziwy, aby polecenia zawarte w funkcji loop były dalej wykonywane. W analizowanym przypadku polecenia będą wykonywane, dopóki zmienna i ma wartość mniejszą od 20. Gdy zmienna i osiągnie wartość równą 20 lub większą od 20, program przestanie wykonywać instrukcje zawarte wewnątrz funkcji l oop. Trzeci element zawarty w nawiasie określa to, co powinno się stać po wykonaniu wszystkich poleceń zawartych w funkcji loop. W naszym przykładzie wartość zmiennej i jest zwiększana o 1. A więc po dwudziestokrotnym wykonaniu operacji zawartych w funkcji loop wartość zmiennej i będzie wynosić 20, co spowoduje zakończenie działania funkcji loop. Spróbuj wprowadzić ten kod, a następnie go uruchomić. Jedynym sposobem na opanowa­nie reguł składni oraz irytującej interpunkcji jest samodzielne wpisywanie kodu. Kompila­tor poinformuje Cię, gdy popełnisz jakiś błąd. Z czasem wszystkie te skomplikowane zapisy zaczną nabierać sensu. Potencjalną wadą takiego rozwiązania jest to, że wykonanie funkcji loop zabierze dużo czasu. Nie jest to problemem w pr zypadku poprzedniego szkicu, ponieważ szkic nie wyko­nuje żadnych innych czynności poza sterowaniem diodą LED. W innych szkicach funkcja l oop będzie jednakże sprawdzała, czy nie wciśnięto jakiegoś przycisku lub czy komunikacja z urządzeniem zewnętrznym została zakończona. Jeżeli procesor będzie zajęty długotrwałym
przetwarzaniem pętli for, wymienione operacje mogą zostać niewykonane. Ogólnie rzecz biorąc, dobrą praktyką jest tworzenie funkcji loop tak, aby działała jak najszybciej i mo­gła być jak najczęściej uruchamiana. Poniższy szkic prezentuje sposób, w jaki można osią­gnąć taki efekt:

intledPin = 13 ;
intdelayPeriod = 250 ;
intcount = O ;

void setup ( )
{
pinMode ( ledPin , OUTPUT ) ;

void loop ( ) {

digitalWrite ( ledPin , HIGH ) ;
delay (delayPeriod ) ;
digitalWrite ( ledPin , LOW) ;
delay (delayPeriod ) ;
count ++ ;
if (count == 20)
{
count = O ;
delay ( 3000 ) ;
}
}

Poniższa linia kodu mogła przyciągnąć Twoją uwagę.
count ++ ;
Linia ta zawiera skrót często stosowany w języku C. Poniżej przedstawiono kod wyko­nujący dokładnie tę samą operację.
count = count + 1

Wykonanie operacji zawartych w funkcji loop za każdym razem będzie zabierać trochę więcej niż 200 milisekund. Wykonanie operacji zawartych w tej funkcji po raz dwudziesty zajmie ponadto o 3 sekundy dłużej z powodu zaprogramowanego oczekiwania pomiędzy błyskami. W niektórych aplikacjach taki czas może się okazać za długi. Puryści generalnie odradzają stosowanie funkcji delay. Nie ma jednego uniwersalnego, najlepszego rozwiąza­nia tego problemu. Rozwiązanie należy dobierać indywidualnie zależnie od potrzeb danej aplikacji.

WHILE
Pętle w języku C można tworzyć również przy użyciu polecenia whi le. Poniżej znajduje się przykład jego zastosowania. W przy kładzie tym wykonywana jest ta sama operacja co w przy­toczonym wcześniej przykładzie użycia polecenia for.

inti = O ;
while ( i < 20)
{
digitalWri te ( ledPi n , H I GH ) ;
delay (delayPeriod ) ;
digitalWrite ( ledPin , LOW ) ;
delay (delayPeriod ) ;
i ++ ;
}
Aby pętla while była wykonywana, wyrażenie zawarte w nawiasach musi być prawdziwe. Gdy wyrażenie to przestanie być prawdziwe, program wykona kolejne polecenia, które znajdą się w programie za ostatnim nawiasem klamrowym.

Dyrektywa #define
Istnieje alternatywne rozwiązanie dla stosowania zmiennych do opisu wartości, które nie zmieniają się podczas działania programu (np. do określania numeru złącza). Zamiast zmien­nej można w ta kiej sytuacji zastosować dyrektywę #de fine. Dyrektywa ta pozwala na sko­relowanie nazwy z wartością. Każde miejsce, gdzie zostanie użyta dana nazwa, zostanie przed kompilacją szkicu wypełnione określoną wartością. Przypisanie numeru złącza diody LED można zdefiniować w następujący sposób: #define ledPin 13 Zauważ, że w dyrektywie #defi ne pomiędzy nazwą a wartością nie stosuje się znaku „=". Na końcu dyrektywy nie umieszcza się nawet średnika. Dzieje się tak, ponieważ dy­rektywa nie jest elementem języka C. Jest to dyrektywa przedkompilacyjna, która jest ob­sługiwana przed kompilacją programu. Według autora niniejszej książki taki zapis jest trudniejszy do odczytania niż zapis zmiennej. Jego zaletą jest to, że do przechowywania tej dyrektywy nie używa się pamięci. Warto jest rozważyć zastosowanie tej techniki, gdy zależy nam na tym, aby nasz program zajmował jak najmniej pamięci.

Na górę