[C]float

dem1509
Ciao a tutti!
Programmazione in C:
Qualcuno saprebbe dirmi perché nel confronto di due float di cui uno assume il valore -1.7 e l'altro assume il valore -1.3, il secondo risulta essere un numero minore del primo?? :shock:

Risposte
vict85
Non dovrebbe avvenire. Sei sicuro che le variabili abbiano quei valori?

apatriarca
Mostra il codice che hai scritto..

dem1509
Il programma legge un file così strutturato:
01:30 0.8 C coperto con qualche pioggia
04:00 0.7 C pioggia debole
07:30 28.8 F pioggia debole
10:00 2.7 C pioggia debole
13:00 31.9 F pioggia debole
16:20 4.1 C pioggia debole
19:00 2.5 C pioggia e schiarite
21:15 -1.3 C sereno
22:10 0.2 C sereno

Il primo dato rappresenta l'orario, il secondo la temperatura, la lettera seguente rappresenta se i gradi sono scritti in Celsius o Fahrenheit. Se c'è la F, bisogna convertire il dato in C.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXDIM 200

struct ora
{
   int ore;
   int minuti;
};

struct meteo
{
   struct ora o;
   float temperatura;
   char previsione[MAXDIM];
};

struct meteo cerca_minima (char nome_file[]);
int leggi_file (FILE *fprevisioni, struct meteo previsioni_orarie[]);
void leggi_riga (char riga[], struct meteo previsioni_orarie[], int numero_consecutivo);
struct meteo ricerca_minimo (struct meteo previsioni_orarie[], int numero_previsioni);


int main(int argc, char *argv[])
{
   struct meteo temp_minima;
   
   if (argc != 2)
   {
      printf ("Uso: previsioni <file_previsioni>\n");
	  exit (EXIT_FAILURE);
   }
   
   temp_minima = cerca_minima (argv[1]);
   printf ("%d:%d %f gradi previsione: %s\n", temp_minima.o.ore, temp_minima.o.minuti, temp_minima.temperatura,
                                              temp_minima.previsione);
   
   return EXIT_SUCCESS;
}

struct meteo cerca_minima (char nome_file[])
{
   FILE *fprevisioni;
   struct meteo previsioni_orarie[MAXDIM];
   int numero_previsioni;
   struct meteo minima;
   
   if ((fprevisioni = fopen (nome_file, "r")) == NULL)
   {
      printf ("Errore apertura file previsioni\n");
	  exit (EXIT_FAILURE);
   }
   
   numero_previsioni = leggi_file (fprevisioni, previsioni_orarie);
   minima = ricerca_minimo (previsioni_orarie, numero_previsioni);
   
   
   return minima;
}

int leggi_file (FILE *fprevisioni, struct meteo previsioni_orarie[])
{
   char riga[400];
   int i;
   i = 0;
   
   while (fgets (riga, 400, fprevisioni) != NULL)
   {
      leggi_riga (riga, previsioni_orarie, i);
	  i++;
   }
   
   return i;
}

void leggi_riga (char riga[], struct meteo previsioni_orarie[], int numero_consecutivo)
{
   char unita;
   char temp[5];
   int i, j;
   i = 0;
   j = 0;
   
   while (riga[i] != ':')
   {
      temp[j] = riga[i];
	  j++;
	  i++;
   }
   temp[j] = '\0';
   
   previsioni_orarie[numero_consecutivo].o.ore = atoi(temp);
   i++;
   
   j = 0;
   while (riga[i] != ' ')
   {
      temp[j] = riga[i];
	  j++;
	  i++;
   }
   
   temp[j] = '\0';
   previsioni_orarie[numero_consecutivo].o.minuti = atoi(temp);
   
   i++;
   
   j = 0;
   while (riga[i] != ' ')
   {
      temp[j] = riga[i];
	  j++;
	  i++;
   }
   
   temp[j] = '\0';
   previsioni_orarie[numero_consecutivo].temperatura = atof(temp);
   
   i++;
   
   unita = riga[i];
   
   if (unita == 'F')
   {
      previsioni_orarie[numero_consecutivo].temperatura = 
	                                          (previsioni_orarie[numero_consecutivo].temperatura - 32) / 1.8;
   }
   printf ("%c\n", unita);
   i++;
   
   j = 0;
   while (riga[i] != '\0')
   {
      previsioni_orarie[numero_consecutivo].previsione[j] = riga[i];
	  i++;
	  j++;
   }
   
   previsioni_orarie[numero_consecutivo].previsione[j] = '\0';
   printf ("%d:%d %f gradi; previsione: %s\n", previsioni_orarie[numero_consecutivo].o.ore, 
                                               previsioni_orarie[numero_consecutivo].o.minuti,
											   previsioni_orarie[numero_consecutivo].temperatura,
                                               previsioni_orarie[numero_consecutivo].previsione);

   
   return;
}

struct meteo ricerca_minimo (struct meteo previsioni_orarie[], int numero_previsioni)
{
   int min;
   int i;
   int indice_min;
   struct meteo temp_minima;
   
   i = 0;
   min = previsioni_orarie[i].temperatura;
   indice_min = i;
   
   i++;
   
   while (i < numero_previsioni)
   {
      if (previsioni_orarie[i].temperatura < min)
	  {
	     min = previsioni_orarie[i].temperatura;
		 indice_min = i;
		 printf ("minimo: %f, indice: %d\n", previsioni_orarie[i].temperatura, indice_min);
      }
	  i++;
   }
   
   temp_minima.o.ore = previsioni_orarie[indice_min].o.ore;
   temp_minima.o.minuti = previsioni_orarie[indice_min].o.minuti;
   temp_minima.temperatura = previsioni_orarie[indice_min].temperatura;
   strcpy (temp_minima.previsione, previsioni_orarie[indice_min].previsione);
   printf ("%d:%d %f gradi previsione: %s\n", temp_minima.o.ore, temp_minima.o.minuti, temp_minima.temperatura,
                                              temp_minima.previsione);
   
   
   return temp_minima;
}

Il problema del minimo si presenta nell'ultima funzione :(

apatriarca
Ciao, scusa ma avevo letto male l'output e avevo frainteso cosa dovevano stampare alcune parti del codice (ho cancellato il mio messaggio precedente se avevi avuto modo di vederlo). Il problema del confronto è che non avviene tra due float, ma tra un float e un int. min ha infatti tipo int per cui quando avviene la conversione -1.777 diventa -1 che è quindi maggiore di -1.3. La soluzione è semplicemente quella di dichiarare min come float.

dem1509
"apatriarca":
Ciao, scusa ma avevo letto male l'output e avevo frainteso cosa dovevano stampare alcune parti del codice (ho cancellato il mio messaggio precedente se avevi avuto modo di vederlo). Il problema del confronto è che non avviene tra due float, ma tra un float e un int. min ha infatti tipo int per cui quando avviene la conversione -1.777 diventa -1 che è quindi maggiore di -1.3. La soluzione è semplicemente quella di dichiarare min come float.

Grazie mille!!! Ho riguardato più e più volte il codice senza accorgermene :roll:

apatriarca
Quando pensavo che il problema fosse la lettura ti avevo fatto alcuni commenti, che ho poi cancellato. Ma credo ti possano essere utili in ogni caso e quindi te li ripresento qui:
1. La dimensione dell'array temp in leggi_riga è troppo bassa. Soprattutto considerando che non hai fatto alcun controllo in seguito per vedere se superavi il limite di tale array. Dovresti aumentarne la dimensione (non ti preoccupare più di tanto di sprecare memoria) e aggiungere i controlli.
2. Al posto di atoi, atof e della variabile temporanea potevi fare uso di strtod e strtof che leggono un qualche valore e poi restituiscono anche un puntatore al primo carattere dopo tale valore.
3. La soluzione più semplice sarebbe ovviamente stata comunque quella di usare sscanf. Avresti infatti potuto scrivere leggi_riga come segue:
void leggi_riga (char riga[], struct meteo previsioni_orarie[], int numero_consecutivo) 
{
    char unita;
    int prev_start = 0;

    if (4 != sscanf(riga, "%d:%d %f %c %n", &(previsioni_orarie[numero_consecutivo].o.ore),
            &(previsioni_orarie[numero_consecutivo].o.minuti), &(previsioni_orarie[numero_consecutivo].temperatura),
            &unita, &prev_start)) {
        /* Ci sono stati errori di lettura.. */
    } 
    
    if (unita == 'F') {
        previsioni_orarie[numero_consecutivo].temperatura = 
                                             (previsioni_orarie[numero_consecutivo].temperatura - 32) / 1.8;
    }
    
    strncpy(previsioni_orarie[numero_consecutivo].previsione, riga + prev_start, MAXDIM);
    printf ("%d:%d %f gradi; previsione: %s\n", previsioni_orarie[numero_consecutivo].o.ore, 
                                               previsioni_orarie[numero_consecutivo].o.minuti,
                                    previsioni_orarie[numero_consecutivo].temperatura,
                                               previsioni_orarie[numero_consecutivo].previsione);
}

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.