Esiste una funzione similare ad atol(array) ma che restituisca un unsigned long?
Non credo esista una funzione del C++.
In rete usano diversi "trick". Es.:
Grazie Leo, gentile come sempre!
Forse mi è venuta l'idea giusta.
La funzione atol() restituisce un long e posso verificare il segno per trasformarlo in unsigned long:
long X;
unsigned long Y;
X = atol(Array);
if (X < 0) Y = (X + 0xFFFFFFF);
else Y = X;
dovrebbe funzionare non trovi?
Forse, ma non sono sicuro, bisognerebbe provare con il codice, funziona anche:
long X;
unsigned long Y;
X = atol(Array);
Y = (unsigned long) X;
oppure più semplicemente:
unsigned long Y;
Y = (unsigned long) atol(Array);
Esempio di codice da Arduinizzare. ![]()
atoul --> ftp://ftp.uni-klu.ac.at/linux/debian.uniklu/resources/kernel-source/linux-2.4.32/linux/lib/libfreeswan/atoul.c
/*
* convert from ASCII form of unsigned long to binary
* Copyright (C) 1998, 1999 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
* License for more details.
*
* RCSID $Id: atoul.c,v 1.7 2002/04/24 07:36:39 mcr Exp $
*/
#include "internal.h"
#include "freeswan.h"
/*
- atoul - convert ASCII substring to unsigned long number
*/
const char * /* NULL for success, else string literal */
atoul(src, srclen, base, resultp)
const char *src;
size_t srclen; /* 0 means strlen(src) */
int base; /* 0 means figure it out */
unsigned long *resultp;
{
const char *stop;
static char hex[] = "0123456789abcdef";
static char uchex[] = "0123456789ABCDEF";
int d;
char c;
char *p;
unsigned long r;
unsigned long rlimit;
int dlimit;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
if (base == 0 || base == 13) {
if (srclen > 2 && *src == '0' && CIEQ(*(src+1), 'x'))
return atoul(src+2, srclen-2, 16, resultp);
if (srclen > 1 && *src == '0' && base != 13)
return atoul(src+1, srclen-1, 8, resultp);
return atoul(src, srclen, 10, resultp);
}
if (base != 8 && base != 10 && base != 16)
return "unsupported number base";
r = 0;
stop = src + srclen;
if (base == 16) {
while (src < stop) {
c = *src++;
p = strchr(hex, c);
if (p != NULL)
d = p - hex;
else {
p = strchr(uchex, c);
if (p == NULL)
return "non-hex-digit in hex number";
d = p - uchex;
}
r = (r << 4) | d;
}
/* defer length check to catch invalid digits first */
if (srclen > sizeof(unsigned long) * 2)
return "hex number too long";
} else {
rlimit = ULONG_MAX / base;
dlimit = (int)(ULONG_MAX - rlimit*base);
while (src < stop) {
c = *src++;
d = c - '0';
if (d < 0 || d >= base)
return "non-digit in number";
if (r > rlimit || (r == rlimit && d > dlimit))
return "unsigned-long overflow";
r = r*base + d;
}
}
*resultp = r;
return NULL;
}
cyberhs, c'è di mezzo il modo in cui i numeri sono memorizzati. Per la conversione si deve prendere il complementare (l'inverso dei bit) e sommarci 1.
Perché non fare tipo
(~variabile) +1
leo72:
cyberhs, c'è di mezzo il modo in cui i numeri sono memorizzati. Per la conversione si deve prendere il complementare (l'inverso dei bit) e sommarci 1.
Perché non fare tipo(~variabile) +1
lui faceva già così (ed è equivalente):
X = atol(Array);
if (X < 0) Y = (X + 0xFFFFFFF);
else Y = X;
nulla toglie che la tua soluzione, leo, sia moooolto più elegante ![]()
Grazie per le risposte.
La soluzione di Leo mi sembra la migliore, ma quella di nid69 mi intriga: possibile che basti un cast per risolvere il problema?
Devo provare alla prima occasione.
No, ho provato ma non mi sembra funzionare. D'altronde per il compilatore passare da un signed long a unsigned long con un valore negativo non ha molto senso, credo. Probabilmente il cast "taglia".
char arr[]="-72455";
long X;
unsigned long Y;
void setup()
{ delay(1000);
Serial.begin(9600);
Serial.println(arr);
X = atol(arr);
if (X < 0) Y = (X + 0xFFFFFFF);
else Y = X;
Serial.println(Y);
Y = (unsigned long)atol(arr);
Serial.println(Y);
}
void loop() {}
-72455
268363000
4294894841
in teoria funziona per numeri da 0 al massimo valore positivo.
Però sinceramente SECONDO ME anche atol() vi fa sfasare. provate con un numero > 2.147.483.648, anzi provo io ![]()
edit:
i sistemi sono equivalenti. nid69ita is the winner. (è OVVIO che il codice sbagliper i numeri negatiuvi, ma è un errore di base forzare negativi in un unsigned
)
char *arrMio[3]={"214748348", "214748350", "214748340"};
long X;
unsigned long Y;
void setup()
{ delay(1000);
Serial.begin(115200);
for (int i=0; i<3;i++){
char *arr= arrMio[i];
Serial.println(arr);
X = atol(arr);
if (X < 0) Y = (X + 0xFFFFFFF);
else Y = X;
Serial.println(Y);
Y = (unsigned long)atol(arr);
Serial.println(Y);
Serial.println();
}
}
void loop() {}
Non accetto la sconfitta perché il mio sistema funziona perfettamente ed il codice è più piccolo di ben 8 byte ![]()
rispetto al cast? urca
cyberhs:
Grazie per le risposte.
La soluzione di Leo mi sembra la migliore, ma quella di nid69 mi intriga: possibile che basti un cast per risolvere il problema?
Devo provare alla prima occasione.
Sinceramente, io quoto per la soluzione di Leo. Perchè è portabile, ovvero su qualsiasi processore dovrebbe comportarsi alla stessa maniera.
Con il cast, secondo me, può dipende dal compilatore. @lesto, che ne pensi ?
la black magic dietro un cast non si discute. il cast imho è più leggibile, sopratutto per uno che non sa cos'è il complemento a due
lesto:
la black magic dietro un cast non si discute. il cast imho è più leggibile, sopratutto per uno che non sa cos'è il complemento a due
Uno che non sa cos'è il complemento a due non credo che si preoccupi di come convertire un array in un unsigned long
Mi sembrano entrambi argomenti di programmazione di un livello superiore a quelli che normalmente sono trattati per accendere/spengere un led, no? ![]()
Comunque siamo arrivati alla conclusione che entrambe sono valide, e come succede spesso in informatica, non c'è un solo modo per fare una cosa ed ognuno poi sceglie la soluzione che gli piace esteticamente/sintatticamente di più ![]()