Pages: [1]   Go Down
Author Topic: Array to unsigned long function  (Read 776 times)
0 Members and 1 Guest are viewing this topic.
Selvazzano Dentro - Padova
Offline Offline
Edison Member
*
Karma: 45
Posts: 1497
"Chi sa fa, chi non sa insegna"
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22930
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged


Selvazzano Dentro - Padova
Offline Offline
Edison Member
*
Karma: 45
Posts: 1497
"Chi sa fa, chi non sa insegna"
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

ivrea (to)
Offline Offline
Faraday Member
**
Karma: 87
Posts: 4991
miaaao ^-^
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

my name is IGOR, not AIGOR

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 114
Posts: 7182
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
/*
 * 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;
}
« Last Edit: June 26, 2013, 03:16:07 am by PaoloP » Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22930
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
(~variabile) +1
Logged


0
Online Online
Shannon Member
****
Karma: 132
Posts: 10495
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
(~variabile) +1

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

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

nulla toglie che la tua soluzione, leo, sia moooolto più elegante smiley
Logged

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

Selvazzano Dentro - Padova
Offline Offline
Edison Member
*
Karma: 45
Posts: 1497
"Chi sa fa, chi non sa insegna"
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

ivrea (to)
Offline Offline
Faraday Member
**
Karma: 87
Posts: 4991
miaaao ^-^
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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:
-72455
268363000
4294894841
« Last Edit: June 26, 2013, 01:20:58 pm by nid69ita » Logged

my name is IGOR, not AIGOR

0
Online Online
Shannon Member
****
Karma: 132
Posts: 10495
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley

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 smiley )
Code:
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() {}
« Last Edit: June 26, 2013, 01:50:12 pm by lesto » Logged

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

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22930
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Logged


0
Online Online
Shannon Member
****
Karma: 132
Posts: 10495
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

rispetto al cast? urca
Logged

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

ivrea (to)
Offline Offline
Faraday Member
**
Karma: 87
Posts: 4991
miaaao ^-^
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 ?
Logged

my name is IGOR, not AIGOR

0
Online Online
Shannon Member
****
Karma: 132
Posts: 10495
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

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

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22930
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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  smiley-wink 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ù  smiley-wink
Logged


Pages: [1]   Go Up
Jump to: