Login Login
MORE

WIDGETS

Widgets

Wanted articles
Who is online?
Article tools

Cpp Info fondamentali

From Aino Wiki

Jump to: navigation, search

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_GRECO

Costanti 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::cout accede alla variabile cout nel namespace std.
  • Accesso a membri statici di classe: MyClass::myStaticMember accede 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++ | Cpp Teoria


 C# | Visual Studio | MS SQL |  Dizionario IT | Dizionario

Parole chiave:

Author Giuseppe AINO