Ad una variabile di tipo char può essere assegnato un numero, da -128 a +127 oppure il carattere direttamente, ad esempio le due assegnazioni seguenti sono equivalenti dal momento che il carattere ‘A’ ha il posto 65 nella tabella ASCII:
char lettera = ‘A’;
char lettera = 65;
Nel linguaggio C, un vettore di N caratteri costituisce una stringa, ma nel linguaggio “Wiring” di Arduino sono presenti funzioni specifiche che operano su tali variabili. Per dichiarare un vettore di caratteri usiamo la sintassi tipica del linguaggio C, che prevede un carattere terminatore del vettore oppure un modo più veloce come nell’esempio seguente:
char parola[]={‘c’,’i’,’a’,’o’,’\0′};
char parola[]=”ciao”;
I singoli apici si usano per definire i caratteri singoli, i doppi apici per le perole.
Se si definisce la stringa individuandone i singoli caratteri, bisogna inserire anche il carattere terminatore ‘\0’. Si può osservare che la seconda forma è più semplice e non costringe ad inseirre il carattere terminatore (lasciando il compito al compilatore di farlo).
In ogni caso, sia che usiamo il primo che il secondo metodo per definire la stringa, possiamo usare comunque il formalismo degli array per individuare per esempio un carattere singolo nella parola. Per visualizzare la stringa basta indicare il nome della variabile: esempio lcd.print(parola);
Esercizio: usate il display LCD, dichiarate la stringa sopra e visualizzate la stringa ed anche un carattere random ogni secondo.
#include <LiquidCrystal.h>
char parola[]={‘c’,’i’,’a’,’o’,’\0′}; char a=65; char e=’a’;
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
void setup() { randomSeed(analogRead(0)); lcd.begin(16, 2);
|
lcd.print(parola);
}
void loop() { lcd.setCursor(0, 1); lcd.print(parola[random(4)]); delay(1000); }
|
Possiamo anche cambiare un singolo carattere della stringa, ma non tutta la stringa: l’istruzione parola[0]=’p’ trasforma la stringa “ciao” in “piao”. Non è possibile scrivere parola[]=”piao”.
Le funzioni sulle stringhe.
strcpy(stringa1, stringa2) : copia stringa2 in stringa1
strcat(stringa1, stringa2) : attacca stringa2 alla fine di stringa1
strlen(stringa1): restituisce la lunghezza di stringa1
strcmp(stringa1, stringa2): restituisce 0 se le stringhe sono identiche, un numero negativo se stringa1 è minore, positivo se è maggiore
strchr(stringa1, carattere) : restituisce la posizione della prima occorrenza del carattere se è presente nella stringa, altrimenti restituisce 0.
strstr(stringa1, stringa2) : controlla se stringa2 è contenuta in stringa1.
Esercizi, usate LCD per eseguire i seguenti esercizi:
- visualizzate la frase “salve antonio” attaccando le 2 singole stringhe.
- visualizzate la lunghezza delle tre stringhe
- visualizzate la posizione del carattere “t”
- definite le stringhe “antonio”, “tin” e “ton” e verificate quale sia contenuta nella prima.
I metodi sulle stringhe.
Il C tratta le stringhe in maniera un po’ ostica. Il C++, evoluzione del C, mette a disposizione la classe “String” che offre dei “metodi” (delle funzioni) addizionali per la manipolazione delle stringhe.
Per istanziare un oggetto di tipo stringa se ne “preleva” una copia dalla classe String nel modo seguente:
String nome; ho creato una istanza dalla classe Stringa
String nome = “Ciao”; ho creato una istanza ed assegnato un valore
Il linguaggio Wiring di Arduino, non ha tutte le potenzialità del C++ ma molte di queste. L’area di RAM utilizzata per le stringhe non è però molto ampia.
miastringa.concat.
Il metodo “concat” serve a concatenare due stringhe, l’espressione serve a concatenare a stringa1 la stringa2.
stringa1.concat(stringa2)
esempio:
String miastringa=”prova”;
miastringa.concat(“123”);
ottiene come risultato che miastringa diventa “prova123”.
Possiamo anche usare l’operatore “+” che converte anche in stringa un dato che sia di altro tipo:
String miastringa=”prova”;
altrastringa=miastringa +123;
dove il numero 123 viene convertito anche in stringa.
miastringa.length(). Restituisce la lunghezza della stringa.
miastringa.remove(pos [nC]). Rimuove “nC” caratteri a partira dal carattere di posto “pos”.
mystr=”test di rimozione”;
mystr.remove(4);
mystr 🡪 “test”
oppure:
mystr=”test di rimozione”;
mystr.remove(4,3);
mystr 🡪 “test rimozione”
miastringa.replace(seq, sost). Sostituisce tutte le sequenze di caratteri “seq” con quella “sost”.
mystr=”pozzo”;
mystr.replace(“o”,”e”);
mystr 🡪 “pezze”
miastringa.toLowerCase(). Converte in minuscolo
miastringa.toUpperCase(). Converte in maiuscolo
Operazioni per le stringhe.
+ | Concatena più stringhe | miastringa= “prova” + ”di” + ”concatenazione”; |
+= | Appende una stringa alla fine | miastringa += altrastringa; |
[] | Accede ad un carattere nella stringa | Miastringa[2]=”A”; |
== | Controlla se due stringhe sono eguali | miastringa == altrastringa |
!= | Controlla se due stringhe sono diverse | miastringa != altrastringa |
> o >= | Controlla se la prima stringa è più grande | miastringa >= altrastringa |
< o <= | Controlla se la prima stringa è più piccola | miastringa <= altrastringa |
Tipo di dato strutturato.
Nell’esempio che segue, viene definito un tipo di dato che ha una struttura costituita da due numeri interi. I tipi di dati strutturati sono utili quando per definire una grandezza, non basta un unico dato ma ne servono 2 o più. Per esempio se indico un indirizzo devo precisare, città, via, cap e numero civico e pertanto il tipo “indirizzo” potrebbe essere una struttura con due interi (cap e numero civico) e due stringhe (città e nome della via).
struct myled {
int pin;
int stato;
} led1, led2;
nell’esempio sopra, alle variabili led1 e led2 viene assegnato il tipo di dato myled che viene individuato da 2 valori: il pin e lo stato del led.
Per assegnare i due valori si usa l’operatore “.” Nel modo sotto indicato:
led1.pin=10;
led2.stato=HIGH;
e potremmo usare l’espressione digitalWrite in questo modo:
digitalWrite(led1.pin, led1.stato);
Tipo di dato definito dall’utente.
Se vogliamo definire un nuovo tipo, non esistente, possiamo usare l’istruzione typedef. Possiamo, per esempio rendere un nuovo tipo la struttura degli esempi precedenti e identificarla, per esempio, con il nome “defled”, in questa maniera, quando ci serve stanziare una variabile, non dobbiamo più riscrivere tutta la struttura ma solo il novo identificatore.
typedef defled struct myled {
int pin;
int stato;
}
Da ora in poi si potrà scrivere:
defled led1,led2;
Tipo di dato enumerato.
Questo tipo di dato personalizzato ci permette di indicare quali sono gli elementi dell’insieme di appartenenze: se definisco il tipo “int” l’insieme di appartenenza è stabilito a priori dalla codifica a 16 bit e sono tutti gli interi da -32767 a +32767. Se invece vogliamo definire un nuovo tipo i cui elementi sono i giorni della settimana posso scrivere:
enum settimana {lunedi, martedi, mercoledi, giovedi, venerdi, sabato, domenica}
settimana giorno;
int temperatura;
posso così definire una variabele di tipo “settimana” i cui valori possibili sono solo quelli nell’elenco.
Le funzioni di I/O.
pinMode();
digitalWrite();
digitalRead();
analogWrite();
millis();
micros();
delay();
delayMicroseconds();
Numeri casuali.
random(); random(max); random(min,max);
randomSeed();
Funzioni matematiche:
min(val1,val2);
max(val1,val2);
abs(val);
round(val);
radians(gradi);
degree(rad);
sq(val);
pow(base,esp);
sqrt(val);
sin(gradi);
cos(gradi);
tan(gradi);