[RISOLTO] Zero padding

Buonasera,
ho la necessità di convertire un intero in una stringa.
Il numero ha un max di quattro cifre (9999) e devo aggiungere lo zero iniziale se le cifre sono una o tre, cioè:

  1=>01
  12=>12
 123=>0123
1234=>1234

in definitiva, la stringa che devo ottenere è sempre di due o quattro caratteri.

Inizialmente, avevo risolto utilizzando sprintf

  uint16_t number = 123;
  char digits[5];
  if (number<10) {
    sprintf(digits, "%02d", number);
  } else if (number > 99 && number < 1000) {
    sprintf(digits, "%04d", number);  
  } else {
    sprintf(digits, "%d", number);
  }
  Serial.print("=>");Serial.println(digits);

poi mi sono ricordato d'aver letto, che se possibile è meglio non usare sprintf per ridurre la memoria utilizzata, allora l'ho scritta cosi:

  uint16_t number = 123;
  char digits[5];
  itoa(number, digits, 10);
  uint8_t digits_count = strlen(digits);
  Serial.print(digits);
  if (digits_count == 1 || digits_count == 3) {
    for (byte i = digits_count+2; i > 0; i--) {
      digits[i] = digits[i-1];
    }
    digits[0] = '0';
    digits_count = strlen(digits);
  }
  Serial.print("=>");Serial.println(digits);

ed in effetti, guadagno circa il 5% di spazio disponibile!!!

Domanda (solo per curiosità), c'è un modo più "conciso" per ottenere lo stesso risultato?

TIA
Federico

itoa(n, digits, 10);
int stl = strlen(digits);
if (stl & 1) { memmove(digits+1, digits, stl+1);  digits[0] = '0'; }

Alla faccia del conciso :slight_smile:

Claudio_FF:

itoa(n, digits, 10);

int stl = strlen(digits);
if (stl & 1) { memmove(digits+1, digits, stl+1);  digits[0] = '0'; }

Fantastico,
memmove non la conoscevo, ma a questo stl & 1 non sarei mai arrivato!
Purtroppo la mia lunga esperienza di programmazione ad alto livello mi limita nel pensare ad operazioni come questa :frowning:

Grazie
Federico

Quindi questa

Claudio_FF:
if (stl & 1) { }

può essere usata in alternativa a questa:

if ((num % 2) != 0) {}

Oggi è proprio un buon giorno :smiley:

Federico

Federico66:
Purtroppo la mia lunga esperienza di programmazione ad alto livello mi limita nel pensare ad operazioni come Questa

Infatti è solo la mia "lunga...mah?" esperienza in assembly Z80 che mi ha fatto vedere come naturale uno spostamento di blocco di memoria (e l'uso dei bitwise in generale). Tuttavia su 'memmove' avevo un grosso dubbio. Lo Z80 ha due istruzioni di spostamento specifiche LDDR (carica decrementa e ripeti) e LDIR (carica incrementa e ripeti), che simulate in C Arduino sono le seguenti (DE è l'indirizzo di destinazione, HL quello di partenza e BC la quantità da spostare):

void LDDR(char* DE, char* HL, uint16_t BC)
{
        do {
                *DE = *HL;
                DE--;
                HL--;
                BC--;
        } while (BC != 0);
}
void LDIR(char* DE, char* HL, uint16_t BC)
{
        do {
                *DE = *HL;
                DE++;
                HL++;
                BC--;
        } while (BC != 0);
}

Se i blocchi da spostare non si sovrappongono usare una o l'altra è indifferente. Invece se si sovrappongono va usata la LDIR per spostarli indietro, e la LDDR per spostarli in avanti, altrimenti si vanno a sovrascrivere con i dati nuovi zone ancora da leggere.

Il dubbio era: e la memmove che accetta i parametri della LDIR copierà in avanti o all'indietro?

Risposta: è intelligente, riconosce da sola la direzione in cui deve procedere per non causare la corruzione dei dati.

Invece in assembly la "corruzione" poteva essere usata volontariamente come "feature" per ottenere l'equivalente di una 'memset' del C :slight_smile:

;; Azzera 1000 byte a partire da INDIRIZZO

LD   HL,INDIRIZZO
LD   (HL),0
LD   DE,INDIRIZZO+1
LD   BC,999
LDIR

...operazione che uno Z80 a 4MHz impiega ben 5,25ms ad eseguire, mente la stessa 'LDIR' simulata su Arduino per spostare 1k dura 0,56ms (e una 'memset' 0,376ms)

può essere usata in alternativa a questa:

if ((num % 2) != 0) {}

Potrebbe comunque essere ridotta a:

if (num % 2) {}

Sicuramente però tutte queste "concisioni" rendono il codice più difficile da leggere.

Claudio_FF:
Infatti è solo la mia "lunga...mah?" esperienza in assembly Z80 ...

Guarda... alcune volte devo rileggerti con calma e in più volte, ma è sempre un piacere :wink:

Grazie

Claudio_FF:
Sicuramente però tutte queste "concisioni" rendono il codice più difficile da leggere.

Vero, ma per uso personale (aggiungo commenti) è legale :smiley: :smiley: :smiley:

Federico