Difference between revisions of "Cpp Info fondamentali"
From Aino Wiki
(→Istruzioni particolari) |
(→:: o scope resolution) |
||
| Line 466: | Line 466: | ||
==Operatori== | ==Operatori== | ||
===:: o scope resolution=== | ===:: o scope resolution=== | ||
| − | Viene utilizzato per accedere a membri di uno namespace, una classe o una struttura, anche se sono nascosti da un nome locale. | + | Viene utilizzato per accedere a membri di uno namespace, una classe o una struttura, anche se sono nascosti da un nome locale. |
| − | * Accesso a membri di namespace: std::cout accede alla variabile cout nel namespace std. | + | |
| − | * Accesso a membri statici di classe: MyClass::myStaticMember accede al membro statico myStaticMember della classe MyClass. | + | * ''Accesso a membri di namespace'': <code>std::cout</code> accede alla variabile cout nel namespace std. |
| − | * Specificare il namespace di origine: Permette di disambiguare nomi identici definiti in scope diversi. Ad esempio, se si definisce una funzione locale con lo stesso nome di una funzione globale, si può usare :: per chiamare la versione globale. | + | * Accesso a membri statici di classe: <code>MyClass::myStaticMember</code> accede al membro statico myStaticMember della classe MyClass. |
| − | * Definire membri di classe fuori dalla classe: Permette di definire la funzione di una classe o struttura al di fuori della sua dichiarazione, specificando il nome della classe che la contiene: MyClass::myMethod() { ... }. | + | * ''Specificare il namespace di origine'': Permette di disambiguare nomi identici definiti in scope diversi. Ad esempio, se si definisce una funzione locale con lo stesso nome di una funzione globale, si può usare <code>::</code> per chiamare la versione globale. |
| − | * Definire l'ambito della definizione: Permette anche di definire i membri di una classe in un namespace. Ad esempio, MyNamespace::MyClass::myMethod() { ... } definisce myMethod come membro di MyClass, che a sua volta è in MyNamespace. | + | * ''Definire membri di classe fuori dalla classe'': Permette di definire la funzione di una classe o struttura al di fuori della sua dichiarazione, specificando il nome della classe che la contiene: <code>MyClass::myMethod() { ... }</code>. |
| + | * ''Definire l'ambito della definizione'': Permette anche di definire i membri di una classe in un namespace. Ad esempio, <code>MyNamespace::MyClass::myMethod() { ... }</code> definisce myMethod come membro di MyClass, che a sua volta è in MyNamespace. | ||
| + | |||
===& operatore indirizzo=== | ===& operatore indirizzo=== | ||
Il simbolo commerciale & è usato come dichiaratore di riferimento oltre che come operatore di indirizzamento | Il simbolo commerciale & è usato come dichiaratore di riferimento oltre che come operatore di indirizzamento | ||
Latest revision as of 11:29, 3 December 2025
Contents
Fondamenta
IPOTESI conoscenza di altro liguaggio simile a C.
Per quanto riguarda il C usato nell'IDE di Arduino, la documentazione è qui: C language reference
Main
Ogni programma ha un metodo principale chiamato main, il minimo per fare output o avere un input è includere la libreria fondamentale che è stdio (Standard Input Output), l'istruzione che lo fa è #include ed è chiamata "direttiva", la libreria è un file e l'etensione delle librerie è .h
#include <stdio.h> int main(void){ printf("Ciao !"); return 0; }
Costanti
La costante con nome si definisce col qualificatore "const":const int nMax = 10; const double pg = 3.1415; const char separatore = -''; const char frase[] = "Giuseppe Aino";
La compatibilità con C consente la definizione di costanti simboliche sostituite dal "precompilatore". Una costante simbolica è definita mediante una "direttiva" che si definisce col simbolo #:
#define 3.1415 PI_GRECOCostanti particolari sono i caratteri speciali:
| Simbolo | Significato | Esempio |
|---|---|---|
| \n | new line, accapo | char parola[] = "Frase finisce qui\ne qui inizia..." |
| \r | return, va ad inizio rigo | |
| \t | tabulatore orizontalle | |
| \ooo | Numero ottale | |
| \xhh | Numero esadecimale |
Variabili
Tipi
Tipi semplici
| Tipo | Descrizione | Esempio |
|---|---|---|
| byte | Numero intero che va da 0 a 255 | byte i = 0; |
| int | Numerico intero | int contatore = 0; |
| long | Numeri interi da -2.147.483.648 a -2.147.483.647 | long n = 100; |
| float | Numero a virgola mobile da -3.4028235*10^38 a 3.4028235*10^38 | float temperatura = 1.12; |
| char | Carattere. Si indicano con l'apice singolo ' . Array di caratteri posson esser trattate come stringhe ma la dimensione deve esser maggiorata di uno in quanto l'ultimo carattere deve il carattere speciale \0 |
char lettera = 'a'; char testo[5] = '1234'; |
| String | Stringa |
String testo = "Bravo come sempre"; String testo2 = "Amico " + "mio."; |
| bool | Tipo booleano che rappresenta "vero" o "falso" |
bool test = true; |
Enumeratori
Si usa il qualificatore enum
enum Giorno{lunedì,martedì,..,sabato,domenica};
Gli elementi tra parentesi graffe sono identificatori delle costanti del tipo.
Tipi puntatore
Riferiti a variabili e funzioni.
Variabili puntatore
Innanzitutto definiamo due caratteri usati nei riferimenti a puntatori e variabili puntate:
- '*', usato per accedere ad un oggetto a cui un puntatore si riferisce. Se anteposto ad un nome di una variabile indica che questa sarà un puntatore ovvero un indirizzo di memoria che conterrà una variabile. Anche chiamato operatore di deferenziazione o indirezione.
- '&', se anteposto ad una variabile ne restituisce l'indirizzo di memoria (il puntatore) a questa variabile. Chiamato operatore di referenziazione o "address of".
int number = 1234; int *pointer; //pointer è una variabile che conterrà un puntatore e sarà di tipo intero pointer = &number; //pointer conterrà l'indirizzo di memoria della variabile number *pointer = 10; //modifica inserendo 10 nella memoria puntata da pointer ==> number sarà così diventato 10
Altro esempio:
int i=0, j=0; int *p, *q; p=&i; //p conterrà l'indirizzo di i *p=3; //poiché p punta ad i, l'istruzione equivale a scrivere: i=3; j=*p; //è come scrivere assegna a j il contenuto puntato da p, equivale a j=i; q=p; //equivale a scrivere q=&i;
Con un puntatore è possibile, in teoria, raggiungere via software ognuna delle celle di memoria esistenti sul computer ospitante (è un tipo di codice non protetto), ma in pratica non è saggio farlo (e con i Sistemi Operativi moderni non è nemmeno possibile), poiché in taluni casi si rischia un crash di sistema.
Tentare di accedere al di fuori dello spazio di indirizzi riservato al programma genera una violazione, che il sistema operativo ci segnala con un messaggio di errore e con l'interruzione forzata del codice che stiamo eseguendo.
Tipi strutturati
Come array, struct, unione.
Array
ATTENZIONE C'è differenza tra C++ e C#, si usano le parentesi quadarate ma in C++ si mettono dopo il nome della variabile mentre in C# si mettono dopo il nome del tipo.
//Array di interi di dimensione non definita: int arrInt[] = {10, 20, 30, 40}; // di dimensione fissa int arrCinquinaTombola[5] = {1, 2, 3, 4, 5}; //Array di numeri reali: float v[3] = {0.1, 0.2, 0.3}; //Array di stringhe String arrCars[] = {"Volvo", "BMW", "Ford", "Mazda"}; //Accesso ad elemento: Console.WriteLine(arrCars[0]); // Outputs Volvo
Array bidimensionali:
int matrice[2,3] = { {11, 12, 13}, {21, 22, 23} };
Struct o Record
Trovano analogia in un record di un database:
struct numComplesso { float parteReale; float coefficienteImmaginario; };
Pertanto per riferisvisi:
struct numComplesso { float parteReale; float coefficienteImmaginario; }; // Ecco come vi si accede agli elementi della struttura e come si valorizza: numComlesso x; // x è variabile di tipo numComplesso //Valorizzazione: x = {3.5, 4.6}; //Oppure x.parteReale = 3.5; x.coefficienteImmaginario = 4.6; //Acccesso printf(x.parteReale); //Oouput: 3.5 printf(x.coefficienteImmaginario); //Oouput: 4.6
Output
L'output a schermo è così prodotto in base al tipo di variabile di cui stampare il contenuto.//Per stampare l'output di un numero: int i = 12; printf("Contatore = %d", i); //Per stampare l'output di un carattere: char carattere = 'x'; printf("Carattere = %c", carattere); //Per stampare l'output di un vettore di caratteri: char testo[] = "Il suno del silenzio"; printf("Testo = %s", testo); //Per stampare l'output di un numero float: float risultato = 10.1 / 2.2; printf("Risultato = %f", risultato); // ancora float risultato = (float)10 / (float)2; printf("Risultato = %f", risultato); //Per stampare l'output di una variabile booleana: bool vero = false; printf("Risultato = %d", vero); //Stamperà 0 printf("Risultato = %d", !vero); //Stamperà 1
Per andare accapo si usa il carattere speciale \n
Operazioni
Stringhe di caratteri
// Ricordarsi che una stringa di caratteri DEVE finire con \n char Str3[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o', '\0'};
Stringhe x Arduino
[1] Sintassi:
String(val) String(val, base) // base: DEC, HEX, BIN String(val, decimalPlaces)
String stringOne = "Hello String"; // using a constant String String stringOne = String('a'); // converting a constant char into a String String stringTwo = String("This is a string"); // converting a constant string into a String object String stringOne = String(stringTwo + " with more"); // concatenating two strings String stringOne = String(13); // using a constant integer String stringOne = String(analogRead(0), DEC); // using an int and a base String stringOne = String(45, HEX); // using an int and a base (hexadecimal) String stringOne = String(255, BIN); // using an int and a base (binary) String stringOne = String(millis(), DEC); // using a long and a base String stringOne = String(5.698, 3); // using a float and the decimal places
Operazioni
Nel seguente esempio c'è la concatenazione anche con un numero e l'append.
//Concatenazione String myString1 = "Pizza "; String myString2 = "Margherita"; String myString3 = myString1 + myString2; //Concatenazione stringa numero int numero = 0; String myString3 = myString1 + " di " + (String)numero + myString2; //Append String myString1 = "Pizza "; String myString2 = "ai 4 formaggi"; myString1 += myString2;
Controllo del flusso
if
if (x > 120) digitalWrite(LEDpin, HIGH); if (x > 120) {digitalWrite(LEDpin, HIGH);} if (x > 120) { digitalWrite(LEDpin1, HIGH); digitalWrite(LEDpin2, HIGH); }
switch case
Una specie di multi if corrispondente all'istruzione switch case:char[20] strValue = "xxx"; switch (strValue) { case "Caso 1": case "Caso 2": case "Caso 3": printf("Caso 1,2,3"); break; case "Caso 4": printf("Caso 4, 6?"); break; case "Caso 5": Console.Write("Caso 4"); break; case "Caso ok": break; default: break; }
Cicli
for
for (int i = 1; i <= 5; i++) { printf("%i", i); }
While loop
int n = 1; while (n < 6) { printf("Current value of n is %d", n); n++; // break; // <--- esce dal ciclo while ! }
Do While Loop
int i = 0; do { //Operazioni con l'indice i // ... etc ... i++; } while (i < 7);
Varie
Operatore ternario
Anzichè usare if then else. Sintassi:
(condizione ? valore_se_vero : valore_se_falso)
int value1 = 0; int value2 = 5; int value3 = 10; // Si potrebbe usare 0 come valore "nullo" per gli interi, anche se non è un vero "NULL" int result_value = (value1 != 0) ? value1 : ((value2 != 0) ? value2 : value3);
Uso di Funzioni
Nel segeunte esempio main() è la funzone di partenza che userà la nostra funzione custom somma(), somma() ha due parametri interi passati (per valore ovvero che non cambieranno in Main()):
#include <iostream> // Dichiarazione della funzione (prototipo) !!! // Specifica che la funzione si chiama 'somma', restituisce un 'int' // e accetta due parametri 'int' chiamati a e b. int somma(int a, int b); int main() { int risultato; // Chiamata della funzione 'somma' con gli argomenti 5 e 3. risultato = somma(5, 3); //Stampa in output: std::cout << "Il risultato della somma e': " << risultato << std::endl; return 0; } // Definizione della funzione int somma(int a, int b) { // 'a' e 'b' sono variabili locali alla funzione, inizializzate con i valori passati. int r; r = a + b; // La parola chiave 'return' restituisce il valore di 'r' al chiamante (main). return r; }
Passaggio per referenza
#include <iostream.h> using namespace std; // Definizione del prototipo int moltiplica(int* x, int* y); void main() { int a = 5; int b = 6; int risultato; //Passagio per referenza con & risultato = moltiplica(&a, &b); cout << Il risultato della moltiplicazione è: << risultato <<endl; return (0); } // Dichiarazione della funzione int moltiplica(int* x, int* y) { int ris; ris = *x * *y; return ris; }
Parametri di default
Si può definire una funzione preassegnando di default un volore ai parametri in input
void MiaFunzione(int numero1=1, char lettera='a') { //... }
Overload
Si può definire più funzioni ocn lo stesso nome a patto che i parametri siano diversi per numero o tipo.
void MiaFunzione(int numero1) { //... } void MiaFunzione2(int numero1, int numero2) { //... }
Istruzioni o operatori particolari
Customizzazioni
typedef
Da geeksforgeeks.org
E' una parola chiave usata per "aggiungere" (creare un alias) un nome diverso ad un tipo esistente, allo scopo di rendere più friendly il codice.
Sintassi
typedef current_name new_nam
Es. nel codice seguente il tipo "int" si vuol chiamare anche "Integer".
#include <stdio.h> typedef int Integer; int main() { // n is of type int, but we are using // alias Integer Integer n = 10; printf("%d", n); return 0; }
Esempio in cui si definisce un nuovo data type!
#include <bits/stdc++.h> using namespace std; int main() { // Giving new name // of vector<int> typedef vector<int> vInt; // vec1 is a vector of // type int vInt v; v.push_back(190); v.push_back(180); v.push_back(10); v.push_back(10); v.push_back(27); for (auto X : v) { cout << X << " "; } return 0; }
Operatori
:: o scope resolution
Viene utilizzato per accedere a membri di uno namespace, una classe o una struttura, anche se sono nascosti da un nome locale.
- Accesso a membri di namespace:
std::coutaccede alla variabile cout nel namespace std. - Accesso a membri statici di classe:
MyClass::myStaticMemberaccede al membro statico myStaticMember della classe MyClass. - Specificare il namespace di origine: Permette di disambiguare nomi identici definiti in scope diversi. Ad esempio, se si definisce una funzione locale con lo stesso nome di una funzione globale, si può usare
::per chiamare la versione globale. - Definire membri di classe fuori dalla classe: Permette di definire la funzione di una classe o struttura al di fuori della sua dichiarazione, specificando il nome della classe che la contiene:
MyClass::myMethod() { ... }. - Definire l'ambito della definizione: Permette anche di definire i membri di una classe in un namespace. Ad esempio,
MyNamespace::MyClass::myMethod() { ... }definisce myMethod come membro di MyClass, che a sua volta è in MyNamespace.
& operatore indirizzo
Il simbolo commerciale & è usato come dichiaratore di riferimento oltre che come operatore di indirizzamento
Programmazione Avanzata
Callback functions
In C#, evoluzione del C++, si chiamano Delegati (guida interna Delegati C#), usati anche negli haldlers.
Una funzione callback è una funzione passata ad un'altra utilizzando un puntatore a funzione questo perché il nome della funzione reale non può esser passato direttamente con questa complicanza si ottiene però una comodissima dinamicità.
Nel seguente esempio prima si definirà una funzione reale "ConvertiCarattere" che prenderà il posto di quella simbolica usata nella funzione "PrintASCIIcode()". Quindi, in PrintASCIIcode() si fa riferimento simbolicamente a "func_ptr" il cui compito definito è restituire un intero accettando in input un parametro di tipo char. NOTA il motivo per cui il meccanismo della callback è proprio nella definizione del parametro formale in input è proprio perché è lì il suo confine con l'esterno e lo fa con una sintassi in cui figura il carattere '*':
int(*func_ptr)(char)
Notare che il riferimento alla funzione concreta lo si fa tramite l'operatore puntatore "&"
, vedere nella funzione main() dell'esempio che segue.
Esempio completo:
#include <iostream> using namespace std; // Funzione di callback che concretamente farà una operzione int ConvertiCarattere(char c) { return (int)c; } // Segue una funzione che ne usa un'altra come se fosse un simbolo "func_ptr", // la concretezza di quanto richiesto da "func_ptr" la svolgerà fisicamente una // funzione che nel nostro caso specifico sarà ConvertiCarattere(). // Il momento in cui ConvertiCarattere() sarà usata è nella funzione main() in // cui figurerà come parametro di PrintASCIIcode() void PrintASCIIcode(char c, int(*func_ptr)(char)) { int ascii = func_ptr(c); // Stampa in output il codice ASCII del carattere passato cout << "ASCII code of '" << c << "' is: " << ascii; } // Esempio di utilizzo dinamico di una funzione int main() { PrintASCIIcode('a', &ConvertiCarattere); return 0; }
Output attraverso l'istruzione cout
ASCII code of 'a' is: 97
Mappa e Link
C# | Visual Studio | MS SQL | Dizionario IT | Dizionario
Parole chiave:
