Go Down

Topic: Array to unsigned long function (Read 887 times) previous topic - next topic

cyberhs

Esiste una funzione similare ad atol(array) ma che restituisca un unsigned long?

leo72

Non credo  esista una funzione del C++.
In rete usano diversi "trick". Es.:
http://stackoverflow.com/questions/3186969/copying-between-byte-array-and-unsigned-long

cyberhs

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?

nid69ita

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);
my name is IGOR, not AIGOR

PaoloP

#4
Jun 26, 2013, 10:13 am Last Edit: Jun 26, 2013, 10:16 am by PaoloP Reason: 1
Esempio di codice da Arduinizzare.  :smiley-mr-green:
atoul --> ftp://ftp.uni-klu.ac.at/linux/debian.uniklu/resources/kernel-source/linux-2.4.32/linux/lib/libfreeswan/atoul.c

Code: [Select]
/*
* 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;
}

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
Code: [Select]
(~variabile) +1

lesto


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
Code: [Select]
(~variabile) +1


lui faceva già così (ed è equivalente):

Code: [Select]
X = atol(Array);
if (X < 0) Y = (X + 0xFFFFFFF);
else Y = X;


nulla toglie che la tua soluzione, leo, sia moooolto più elegante :)
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

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.

nid69ita

#8
Jun 26, 2013, 08:13 pm Last Edit: Jun 26, 2013, 08:20 pm by nid69ita Reason: 1
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".

Code: [Select]

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() {}

Code: [Select]

-72455
268363000
4294894841
my name is IGOR, not AIGOR

lesto

#9
Jun 26, 2013, 08:44 pm Last Edit: Jun 26, 2013, 08:50 pm by lesto Reason: 1
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 :) )
Code: [Select]
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() {}
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

leo72

Non accetto la sconfitta perché il mio sistema funziona perfettamente ed il codice è più piccolo di ben 8 byte  :P


lesto

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

nid69ita


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 ?
my name is IGOR, not AIGOR

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
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

leo72


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?  :smiley-yell:

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ù  ;)

Go Up