Operatore - con String

Ho trovato un po di esempi e costruito una semplice funzione string to int.

int StringaToIntero (String inStr) {
  int i;
  int lung;
  int num = 0;
  lung = inStr.length();
  Serial.println(lung);
  for (int i = 0; i < lung; i++) {
     num = num * 10 + (inStr[i] - '0'); 
     Serial.println(num);
  }   
  return num;   
  
 }

Direi che funziona, ma non mi spiego il

num = num * 10 + (inStr - '0'); [/quote]
Soprattutto
> (inStr - '0')[/quote]
> Cosa fa esattamente?
> Grazie
> N

contecavour:

(inStr - '0')[/quote]
Cosa fa esattamente?
[/quote]
Semplicemente sottrae al valore di inStr il valore del codice ASCII del carattere '0'. Se noti è messo fra apici singoli, quindi viene detto al compilatore di considerare il carattere '0' col suo valore ASCII, 48.

inStr - '0' non ha senso. (inStr[i] - '0') invece produce un intero che ha il valore corrispondente alla cifra '0'..'9' memorizzata nella posizione i della stringa.

(edit: [i] viene interpretato come l'inizio del tag 'italics' e viene perciò stampato solo all'interno di una sezione 'code'...)

Grazie Leo.
Chiarissimo.

Si tuxduino, copiando e incollando si è mangiato alcuni caratteri.
Mi è chiaro.
Aspettandomi solo cifre e sottraendo il valore ascii della cifra a quello dello 0 si ottiene appunto il valore della cifra.
Quindi mi sta benissimo.
Dato che sto usando un keypad in cui ho disabilitato le 4 lettere ABCD e se premo asterisco o diesi faccio altre cose (reset e invio).

La cosa che non sapevo era che '0' era il codice ASCII del carattere.
Ma quindi inStr da solo è il carattere e dato che li tutto è intero automaticamente fa il cast del codice ASCII in intero?
Perchè se faccio print(inStr*) stampa il carattere.*
Grazie a tutti

L'apparente incongruenza di questa situazione è dovuta alle conversioni implicite char => int e viceversa che il compilatore applica quando necessario (in realtà la conversione consiste proprio nel prendere il char ed usarlo pari pari come fosse un int, senza "convertire" alcunché).

piuttosto usa

istringstream (inStr)>>a;(richiede #include )
o
atoi(inStr.c_str);

il metodo print accetta stringhe(nel tuo caso è una stringa contenente un solo caratteri),interi...
in realtà ci sono più metodi print,uno che accetta come parametro una stringa,un altro accetta come parametro un interi,etc..

Ma quindi inStr da solo è il carattere e dato che li tutto è intero automaticamente fa il cast del codice ASCII in intero?
Perchè se faccio print(inStr) stampa il carattere.

un char è un numero. se prendi un int e ci schiaffi 48, e poi fai una write (attento, una write, non una print che fa "del lavoro sporco" di nascosto) vedrai sol monito seriale comparire un 0!

la println invece si accorge del TIPO di dato, e se trova un int, un float o un double, "di nascosto" estrae le varie cifre una per una e le converte in una stringa (sommando '0'!) mentre per i char/stringhe non fa nessuna conversione, dando questa senzazione che un char e un uint8_t (leggi unsigned byte) siano due cose differenti.

Altro trucco: se guardi la tabella ASCII le lettere sono tutte di seguito. Quindi puoi usare un trucco simile per convertire una lettere da maiuscolo a miniscolo:
minuscolo = maiuscolo + 'A'-'a';
e viceversa:
maiuscolo = minuscolo + 'a'-'A';

oppure per scorrere tutto l'afabeto puoi fare
for (int i='a'; i<='z';i++){
char lettera = i;
}

non dare un gioco del genere così per scontato; osserva l'EBCDIC, un charset dell'IBM che esiste ancora dai tempi delle schede perforate, e capirai come "trucchi" così banali sono in realtà frutto di un'evoluzione e della genialità XD

m_ri:
piuttosto usa

istringstream (inStr)>>a;(richiede #include )
o
atoi(inStr.c_str);

sconsiglio.
sia atoi (string.h) che >> (sstream.h) sono librerie molto pesanti, anche se vengono estratte solo le parti realmente utilizzate possono incidere molto, forse troppo sul peso dello sketch, perchè sono funzioni generiche a discapito della dimensione del codice. Meglio una funzioncina ad-hoc

un char è un numero. se prendi un int e ci schiaffi 48, e poi fai una write (attento, una write, non una print che fa "del lavoro sporco" di nascosto) vedrai sol monito seriale comparire un 48!

No, vedrai comparire il carattere 0 (zero), il cui codice ASCII è appunto 48 (in base 10).

Arrivo dai mainframe IBM, Unix e poi dos, quindi sia EBCDIC che ASCII e la loro aritmetica mi + molto chiara (e semplice peraltro).
Come prima prova avevo proprio usato atoi che richiedeva un include anche se non ricordo quale, ma non mi era piaciuta.

atoi che richiedeva un include anche se non ricordo quale

mi pare stdlib.h

tuxduino:

un char è un numero. se prendi un int e ci schiaffi 48, e poi fai una write (attento, una write, non una print che fa "del lavoro sporco" di nascosto) vedrai sol monito seriale comparire un 48!

No, vedrai comparire il carattere 0 (zero), il cui codice ASCII è appunto 48 (in base 10).

sì, errore mio, correggo :slight_smile:

contecavour:
Arrivo dai mainframe IBM, Unix e poi dos, quindi sia EBCDIC che ASCII e la loro aritmetica mi + molto chiara (e semplice peraltro).
Come prima prova avevo proprio usato atoi che richiedeva un include anche se non ricordo quale, ma non mi era piaciuta.

ma arduino usa ascii..
comunque confermo che la atoi usa stdlib.h: http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

(atoi) non mi era piaciuta.

Sarei curioso di sapere perché :slight_smile:

Oggi sono altrove, appena ho il codice sotto mano cerco di capire cosa non mi era piaciuto.
In prima battuta potrebbe essere stato proprio per l'include, sviluppo da 30 anni (mamma mia) e ormai come filosofia ho: <<meno includo e meno componenti uso meglio è>>.
Ho passato notti a riscrivere codice perchè librerie o componenti non venivano più supportati nelle release successiva di un ambiente...

In seconda battuta potrebbe essere che chiedevo un lavoro aggiuntivo quindi già che c'ero ho preferito farmi una versione io prendendo il codice e modificandolo. Forse qui ho omesso che come input uso una tastiera 4x4 (non I2C) è ho disabilitato la riga con 4 lettere, quindi ho la certezza che possano entrare solo 12 caratteri.

N

atoi() fa parte della libreria standard del C, quindi sulla sua presenza in un dato ambiente direi che si può stare abbastanza tranqulli a prescindere dagli aggiornamenti :slight_smile:

Non entravo nel merito di stdlib.h, ma di usare un include.
Il mio linguaggio preferito è Delphi che non so se conosci, ma è come dire li..abbassare gli uses...per evitare definizioni ricorsive.
Insomma, diventa uno stile a priori.

Mi viene un dubbio, accetta String in ingresso o pchar?

N

Delphi lo conosco bene di nome (il ns. gestionale ad esempio è scritto in Delphi). Usato non proprio, ci ho giocato tanto tempo fa... (ma col turbo pascal ero bravino... :slight_smile: )

Mi viene un dubbio, accetta String in ingresso o pchar?

atoi() accetta pchar come argomento (const char* nel gergo C/C++)

http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

Quando si passa dagli array null-terminated del C ad una classe stringa si cambia approccio, perché la rappresentazione stringa è già nell'oggetto stesso. Quindi si dota la classe stringa di un metodo tipo int toInt(), e/o si definisce l'operatore di casto-to-int per la classe, in modo che String s="10"; int i = (int)s; abbia un senso. VB.net usa un approccio inverso: fornisce una classe per ogni tipo nativo, e ognuna di queste classi ha un metodo di classe che fa il parsing di una stringa e ritorna il tipo di dato numerico corrispondente. Ad esempio i = Integer.parse(str).

Allora era per quello.
Me ne ero fatto uno che accettasse in entrata il mio tipo di dato e uscisse con quello che mi serviva.

VB.net

Ecco VB.net penso che sia uno di quei linguaggi che non userò mai (Dio mi aiuti), se devo lavorare in .Net che sia c#.

N

ho usato il VB (tradizionale), ma ora che son stato costretto ad usare il .net mi son buttato sul c#.
è un casino quando programmi mezaz giornata in VB e mezza in c o altro, ti ritrovi a mischiar le sintassi.

fornisce una classe per ogni tipo nativo, e ognuna di queste classi ha un metodo di classe che fa il parsing di una stringa e ritorna il tipo di dato numerico corrispondente. Ad esempio i = Integer.parse(str).

java fa un mischione, perchè ha sia gli oggetti (Integer, Float, etc..) che i tipi primitivi (int, float, etc..). Se usi gli oggetti hai i metodoti toInt() etc, se usi i primitivi o le stringhe usi dei metodi statici delle classi sopracitate.