Newsgroup: it.comp.lang.c
Titolo: char array to double, che errore commetto?

Ricevo in output "Error in input array", ma il mio array e´ ok e quindi mi
aspetto un output cosi´:
My array = -123.456
Dove ho commesso l´errore????
#include <stdio.h>
/*
 This function calculate a double value from an array of char pointed by *pc
with n elements.
 If the values in the array are not correct, the parameter err will be set
*/
double array_to_double(const char *pc, int n, int *err)
{
 int i, denflag = 0, sign = 1;
  double res = 0.0, dendec = 10.0;
 if (*pc == '-')
 {
  sign = -1;
  pc++;
 }
  for (i = 0; i < n; i++, pc++)
  if (*pc >= '0' && *pc <= '9'  || (!denflag && *pc == '.'))
  {
   if ((*pc != '.') && (denflag == 0))
            /* here I calculate the numerator */
     res = *pc - '0' + res * (i == 0 ? 1.0 : 10.0);
        else
        if (denflag == 0)
        /* here start denominator */
            denflag = 1;
        else
        {
            res += (*pc - '0') / dendec;
            dendec *= 10.0;
        }
  }
  else
  {
   *err = 1;
   break;
  }
   return sign*res;
}
int main(void)
{
    const char array[] = {'-', '1', '2', '3', '.', '4', '5', '6'};
    double vd;
  int err = 0;
    // I pass the pnt to array and the number of elements
    vd = array_to_double(array, sizeof(array), &err);
  if (err)
   printf("\nError in input array \n");
  else
   printf("\nMy array = %f \n",  vd);
    return 0;
}

 }
...

Grazie Bepin avevi ragione, ho modificato il codice anche su altre parti (ho
incluso il controllo al segno + e ho messo lo 0 finale all徨rray per
stamparlo) ed ora funziona alla grande!
#include <stdio.h>
/*
This function calculate a double value from an array of char pointed by *pc
with n elements.
If the values in the array are not correct, the parameter err will be set
*/
double array_to_double(const char *pc, int n, int *err)
{
int i, denflag = 0, sign = 1;
  double res = 0.0, dendec = 10.0;
if (*pc == '-' || *pc == '+')
{
  sign = *pc == '-' ? -1 : 1;
  pc++;
}
  for (i = 0; i < n; i++, pc++)
  if (*pc >= '0' && *pc <= '9'  || (!denflag && *pc == '.'))
  {
   if ((*pc != '.') && (denflag == 0))
            /* here I calculate the numerator */
     res = *pc - '0' + res * 10.0;
        else
        if (denflag == 0)
        /* here start denominator */
            denflag = 1;
        else
        {
            res += (*pc - '0') / dendec;
            dendec *= 10.0;
        }
  }
  else
  {
   *err = 1;
   break;
  }
   return sign*res;
}
int main(void)
{
    const char array[] = {'-', '1', '2', '3', '.', '4', '5', '6', 0};
    double vd;
  int err = 0;
    // I pass the pnt to array and the number of elements
    vd = array_to_double(array, sizeof(array)-1, &err);
  if (err)
   printf("\nError in input array %s \n", array);
  else
   printf("\nMy array <%s> = %f \n", array, vd);
    return 0;
}

if (*pc == '-' || *pc == '+')
{
  sign = *pc == '-' ? -1 : 1;
  pc++;
  n--; /* <---- naturalmente mi ero dimenticato la cosa piu´ importante! */
}

 Dove ho commesso l´errore????
[...]
// Ricevo in output "Error in input array", ma il mio array e' ok e quindi mi
// aspetto un output cosi':
// My array = -123.456
// Dove ho commesso l'errore????
#include <stdio.h>
/*
 This function calculate a double value from an array of char pointed by *pc
with n elements.
 If the values in the array are not correct, the parameter err will be set
*/
double array_to_double(const char *pc, int n, int *err)
{
 int i = 0; // inizializzazione dell'indice
 int denflag = 0;
 int sign = 1;
  double res = 0.0, dendec = 10.0;
 if (*pc == '-')
 {
  sign = -1;
  pc++;
  i++; // Se c'e' il segno '-' i deve essere incrementato
 }
  for (; i < n; i++, pc++) // i non deve essere reinizializzato
  if (*pc >= '0' && *pc <= '9'  || (!denflag && *pc == '.'))
  {
   if ((*pc != '.') && (denflag == 0))
            /* here I calculate the numerator */
     res = *pc - '0' + res * (i == 0 ? 1.0 : 10.0);
        else
        if (denflag == 0)
        /* here start denominator */
            denflag = 1;
        else
        {
            res += (*pc - '0') / dendec;
            dendec *= 10.0;
        }
  }
  else
  {
   *err = 1;
   break;
  }
   return sign*res;
}
int main(void)
{
    const char array[] = {'-', '1', '2', '3', '.', '4', '5', '6'};
    double vd;
  int err = 0;
    // I pass the pnt to array and the number of elements
    vd = array_to_double(array, sizeof(array), &err);
  if (err)
   printf("\nError in input array \n");
  else
   printf("\nMy array = %f \n",  vd);
    return 0;
}
Se proprio non puoi farne a meno correggi l'errore come sopra, se vuoi dormire
tranquillo prova
     double strtod(const char *nptr, char **endptr);
fai prima e fai meglio: a rifare cose cose gia fatte (meglio da qualcun'altro)
ci si rimette sempre (o quasi).
Ciao Angelo.

 ...
Forse e' meglio incrementare i che decrementare n. Infatti non mi sembra che sia
cambiata la dimensione dell'array.
Ciao Angelo.

Ciao Angelo.
infatti dentro all'if viene incrementato il puntatore (pc++),
quindi la dimensione dell'array di caratteri puntato da pc E' cambiata,
mentre
NON e' cambiata quella di (char *)(pc-1).
Che poi la dimensione del vettore originale sia rimasta inalterata, non
cambia nulla, tanto la var n viene passata per valore, quindi, usciti dalla
funz. in n ci si ritrova lo stesso valore di quando la funzione e' stata
chiamata.
Comunque, secondo me, sono solo dettagli che dipendono dal gusto personale.
Ciao
bp

 Comunque, secondo me, sono solo dettagli che dipendono dal gusto personale.
   Non sono completamente d'accordo. Questi dettagli a volte ti fanno
risparmiare parcchio
   tempo di debug.
   Ciao Angelo.

hey aspetta un attimo,
sono d´accordo se vuoi conservare il puntatore ad inizio array e non ti va
di incrementare pc ma non puoi fare pc+i perche´ pc va incrementato
un´unita´alla volta per scandire l´array nel for.
Al limite puoi copiare pc in un altro puntatore prima del for se vuoi
utilizzare l´array anche dopo, oppure alla fine del for fare un bel pc-=n
per riportarlo all´inizio.
ciao

 un´unita´alla volta per scandire l´array nel for.
Forse mi sfugge qualcosa in quanto non ho seguito bene il thread ma ad
un puntatore puoi benissimo sommare un intero i che lo farà puntare i
oggetti più avanti (oggetti sarebbero il tipo a cui punta).
EMG

 ciao
Non mi e' molto chiaro cosa vuoi dire, pertanto vado un po' a ruota
libera e spero di aver interpretato il tuo pensiero: se ho sbagliato
ti chiedo scusa in anticipo.
Da quello che ho capito, secondo te pc+i e' sbagliato in quanto pc e' un
puntatore a char e i e' un intero, quindi poiche' sizeof(char) vale 1
e sizeof(int) vale 4, pc + i fa spostare l'inndirizzo di pc di 4
caratteri.
Mi spiace, ma non e' cosi'. Spero di essere chiaro facendo un esempio.
char pc[] = {'A', 'B', 'C', 'D'};
   +---+---+---+---+
   | A | B | C | E |
   +---+---+---+---+
   ^       ^
   |       |
   pc     pc+2
struct _pippo{
               char   a;
               int    b;
               double c;
             };
struct _pippo bigStruct[4];
   +--------------+--------------+--------------+--------------+
   |              |              |              |              |
   | bigStruct[0] | bigStruct[1] | bigStruct[2] | bigStruct[3] |
   |              |              |              |              |
   +--------------+--------------+--------------+--------------+
   ^                             ^
   |                             |
   bigStruct                     bigStruct+2
ovviamente sizeof(pc) < sizeof(bigStruct), ma entrambi hanno 4 elementi
e aggiungere 2 al puntatore dell'array significa "sposta il puntatore e
portalo sul secondo elemento dell'array".
Questo significa che la somma di un intero ad un puntatore ha un effetto
diverso a seconda del tipo del puntatore: supponendo che &pc == &bigStruct,
che sizeof(bigStruct) == sizeof(char)+sizeof(int)+sizeof(double) = 13 [1],
e che &pc = 0x0;
   - pc+2         vale 0x02;
   - bigStruct+2  vale 0x1A.
Di tener conto della dimensione degli elementi dell'array se ne occupa il
compilatore in fase di compilazione.
Per verificare quanto detto prova questo programma.
    <----------------> CUT HERE <---------------->
#include <stdio.h>
struct _pippo{
               char   a;
               int    b;
               double c;
             };
void printBigStructElem(struct _pippo* pP, int pItem)
{
   printf("bigStruct[%d] = {\n", pItem);
   printf("                 '%c'\n",(*(pP+pItem)).a);
   printf("                  %d\n",(*(pP+pItem)).b);
   printf("                  %f\n",(*(pP+pItem)).c);
   printf("                }\n");
}
void printCharArr(char* pP, int pItem)
{
   printf("pc[%d] = '%c'", pItem, *(pP + pItem));
}
int main(void)
{
          char   pc[4];
   struct _pippo bigStruct[4];
   int idx = 0;
   printf("\n\n\n");
   printf("sizeof(bigStruct) = %3d\n", sizeof(bigStruct));
   printf("sizeof(pc)        = %3d\n", sizeof(pc));
   printf("\n\n");
   printf("indirizzo iniziale di bigStruct = 0x%p indirizzo di bigStruct+2 =
0x%p\n", bigStruct, bigStruct+2);
   printf("indirizzo iniziale di pc        = 0x%p indirizzo di pc+2        =
0x%p\n", pc, pc+2);
   for(; idx < 4; idx++)
      pc[idx] = '0' + idx;
   for(idx = 0; idx < 4; idx++)
   {
      bigStruct[idx].a = '0' + idx;
      bigStruct[idx].b =  idx;
      bigStruct[idx].c =  2*idx;
   }
   printf("\n\n");
   printBigStructElem(bigStruct, 2);
   printCharArr(pc, 2);
   printf("\n\n\n");
   return 0;
}
    <----------------> CUT HERE <---------------->
Spero che questo abbia tolto qualche dubbio. Per una discussione piu'
formale prova a dare un'occhiata al Kernighan e Ritchie ("Linguaggio C"),
nella seconda ed. italiana la discussione dell'aritmetica degli indirizzi
e' a pag. 127.
[1]
Questo non e' vero per due motivi:
non e' detto che
   - 1 == sizeof(char);
   - 4 == sizeof(int);
   - 8 == sizeof(double);
dipende dalla macchina.
Normalmente non e' vero che:
    - sizeof(bigStruct) == sizeof(char)+sizeof(int)+sizeof(double);
infatti i compilatori "allineano" gli elementi delle strutture per
velocizzarne l'accesso.
Ciao Angelo.