Go Down

Topic: Array to unsigned long function (Read 1 time) 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
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy