2012-05-15 21 views
7

Ho un valore che ho letto da un file e viene memorizzato come char *. Il valore è un numero monetario, #. ##, ##. ##, o ###. ##. Voglio convertire il char * in un numero che posso usare nei calcoli, ho provato atof e strtod e mi hanno dato solo i numeri della spazzatura. Qual è il modo corretto per farlo, e perché il modo in cui lo sto facendo è sbagliato?Conversione di char * in float o double

Questo è essenzialmente ciò che sto facendo, solo il valore char * viene letto da un file. Quando stampo le variabili temp e ftemp sono solo immondizie, numeri negativi giganteschi.

Un altro Edit:

Sono in esecuzione esattamente questo gcc

#include <stdio.h> 
int main() 
{ 
char *test = "12.11"; 
double temp = strtod(test,NULL); 
float ftemp = atof(test); 
printf("price: %f, %f",temp,ftemp); 
return 0; 

}

e la mia uscita è il prezzo: 3.344.336,000 mila, 3344336,000000

Edit: Ecco il mio codice

if(file != NULL) 
    { 
     char curLine [128]; 
     while(fgets(curLine, sizeof curLine, file) != NULL) 
     {    
      tempVal = strtok(curLine,"|");   
      pairs[i].name= strdup(tempVal); 
      tempVal = strtok(NULL,"|"); 
      pairs[i].value= strdup(tempVal); 
      ++i; 
     } 
     fclose(file); 
    } 

    double temp = strtod(pairs[0].value,NULL); 
    float ftemp = atof(pairs[0].value); 
    printf("price: %d, %f",temp,ftemp); 

il mio file di input è nome molto semplice, coppie di valori come questo:

NAME|VALUE 
NAME|VALUE 
NAME|VALUE 

con il valore di essere in dollari ammonta

RISOLTO: Grazie a tutti, stavo usando% d al posto di% f e didn' t avere le intestazioni giuste incluse.

+4

Il problema deve essere da qualche altra parte, il codice che hai postato è perfettamente valido e funzionante. Per favore mostraci come leggi il tuo file. –

+0

1. 'atof' restituisce' double' pure: http://pubs.opengroup.org/onlinepubs/007904875/functions/atof.html – ArjunShankar

+0

2. '% d' è per numeri interi. Usa '% f'. – ArjunShankar

risposta

21

Vi manca un include: #include <stdlib.h>, così GCC crea una dichiarazione implicita di atof e atod, portando a valori di immondizia.

E l'identificatore di formato per il doppio è %f, non %d (cioè per numeri interi).

#include <stdlib.h> 
#include <stdio.h> 

int main() 
{ 
    char *test = "12.11"; 
    double temp = strtod(test,NULL); 
    float ftemp = atof(test); 
    printf("price: %f, %f",temp,ftemp); 
    return 0; 
} 
/* Output */ 
price: 12.110000, 12.110000 
+1

+1. Destra. Questo è il problema. [prima delle modifiche all'OP, c'erano in realtà tre problemi] – ArjunShankar

1

Il codice inviato da voi è corretto e avrebbe dovuto funzionare. Ma controlla esattamente quello che hai nel char*. Se il valore corretto è troppo grande per essere rappresentato, le funzioni restituiscono un valore positivo o negativo HUGE_VAL. Controlla ciò che hai nel char* rispetto ai valori massimi che possono rappresentare sul tuo computer gli float e double.

Controllare this page for strtod reference e this page for atof reference.

Ho provato l'esempio fornito in Windows e Linux e ha funzionato correttamente.

+1

Secondo: http://pubs.opengroup.org/onlinepubs/007904875/functions/atof.html (che è allineato con lo standard C): "Se il valore non può essere rappresentato , il comportamento non è definito. " – ArjunShankar

+0

I valori sono tutti molto più piccoli del massimo che può essere rappresentato da ciascun tipo di variabile, il valore più grande che ho è 120.55. – Andrew

+0

@George: non utilizzare cplusplus.com. È pieno di errori. Né "atof' né' strtod' restituiscono HUGE_VAL in caso di overflow. Secondo [cppreference] (http://en.cppreference.com/w/c/string/byte/atof), il valore restituito non è definito. –

0
printf("price: %d, %f",temp,ftemp); 
       ^^^ 

Questo è il vostro problema. Poiché gli argomenti sono tipo double e float, si dovrebbe utilizzare %f per entrambi (poiché printf è una funzione variad, ftemp verrà promosso a double).

%d si aspetta che l'argomento corrispondente sia il tipo int, non double.

Funzione Variadica come printf in realtà non conoscere i tipi di argomenti nella lista degli argomenti variabili; devi dirlo con lo specificatore di conversione. Dato che hai detto a printf che il primo argomento dovrebbe essere un int, printf prenderà i successivi sizeof (int) byte dall'elenco degli argomenti e lo interpreterà come un valore intero; da qui il primo numero di immondizia.

Ora, è quasi garantito che sizeof (int) < sizeof (double), in modo che quando printf prende i prossimi sizeof (double) byte dalla lista degli argomenti, probabilmente a partire dalla metà del byte di temp, piuttosto che il primo byte del ftemp; da qui il secondo numero di spazzatura.

Utilizzare %f per entrambi.