[C] Aprire contenuto di un file

floppyes
Ciao a tutti!

Sono alle prese con questo esercizio di programmazione in C:
Definire una funzione che, dato un puntatore ad un file testuale, visualizzi i floating point contenuti nel file puntato.

Non avendo nessuna soluzione ho preparato un file .txt contente diversi numeri sia interi che con la parte decimale. Quello che non riesco a fare sono due cose:

1) Passare il puntatore del file
2) Scrivere il codice che mi restituisca se il numero presente su ogni riga è intero o frazionario.

Ho provato a scrivere questo pezzetto di codice:
#include <stdio.h>

int apri ();

int main ()
{
      return 0;
}

int apri ()
{
	FILE *cfPtr;
	if ((cfPtr = fopen ("numeri.txt", "r")) == NULL)
	{
		printf("Il file non può essere aperto!\n");
	}
	
   return 0;
}


Però in questo caso il puntatore è incluso nella funzione, non vado a passare il puntatore dal main alla funzione.

Avete qualche suggerimento in merito?

Grazie
Buona serata
Ciaoo :-)

Risposte
el_brando
Non ho ben capito il senso del codice che hai scritto. Dalla consegna, devi dichiarare una funzione che riceve come parametro un puntatore a file:
void print_float (FILE *);

ed in questa funzione esegui l'elaborazione sul file, che sarà stato aperto nell'ambiente chiamante:
void print_float (FILE *fp)
{
    if (fp != NULL) {
        // cerca e stampa i float contenuti nel file 'puntato' da fp
    }
}

floppyes
Ciao!

Grazie per la risposta, ho scritto la prima parte del programma, però non riesco a capire come individuare se un numero è floating point oppure no!

/*
Definire una funzione che, dato un puntatore ad un file testuale, visualizzi i floating point contenuti nel file puntato.
*/

#include <stdio.h>

void leggi (FILE *fptr);

int main ()
{
   FILE *cfPtr;
   if ((cfPtr = fopen ("numeri.txt", "r")) == NULL)
   {
      printf("Il file non può essere aperto!\n");
   }

   leggi (cfPtr);
   return 0;
}

void leggi (FILE *fptr)
{
}


Hai qualche suggerimento da darmi?

Grazie
Ciao :)

el_brando
Beh, per prima cosa, è sempre buona norma fare un'analisi del problema che si sta affrontando e decidere quale livello di raffinatezza l'algoritmo che si vuole scrivere dovrà avere.

Per esempio.
Il file che devi analizzare avrà una struttura fissa, nota, oppure è un qualsiasi file di testo (contenente anche parole, caratteri particolari, etc) ?
Consideri float i numeri che contengono la virgola, il punto o entrambi ?
Necessiti di un algoritmo preciso ed efficiente (ma più complicato) oppure ti basta qualcosa di semplice e che comunque funziona bene nella maggior parte dei casi ?

vict85
Direi che il modo più semplice per determinare se un numero floating point è intero è quello di usare modf oppure, dal C99, trunc (eventualmente floor e ceil se testi il segno). Il mancato utilizzo del C99 mi sembra immotivato quindi do per scontato che tu possa usarlo.

floppyes
Ciao!

"el_brando":
Beh, per prima cosa, è sempre buona norma fare un'analisi del problema che si sta affrontando e decidere quale livello di raffinatezza l'algoritmo che si vuole scrivere dovrà avere.

Per esempio.
Il file che devi analizzare avrà una struttura fissa, nota, oppure è un qualsiasi file di testo (contenente anche parole, caratteri particolari, etc) ?
Consideri float i numeri che contengono la virgola, il punto o entrambi ?
Necessiti di un algoritmo preciso ed efficiente (ma più complicato) oppure ti basta qualcosa di semplice e che comunque funziona bene nella maggior parte dei casi ?


Dal testo non viene (purtroppo) specificato nulla, per adesso sono partito con un esempio semplice per poi raffinare il codice, magari aggiungendo anche la virgola al posto del punto ecc :)

"vict85":
Direi che il modo più semplice per determinare se un numero floating point è intero è quello di usare modf oppure, dal C99, trunc (eventualmente floor e ceil se testi il segno). Il mancato utilizzo del C99 mi sembra immotivato quindi do per scontato che tu possa usarlo.


Per adesso sono riuscito a risolvere in questo modo:
/*
Definire una funzione che, dato un puntatore ad un file testuale, visualizzi i floating point contenuti nel file puntato.
*/

#include <stdio.h>


void leggi (FILE *fptr);

int main ()
{
   FILE *cfPtr;
   if ((cfPtr = fopen ("es8numeri.txt", "r")) == NULL)
   {
      printf("Il file non può essere aperto!\n");
      return -1;
   }

   leggi (cfPtr);
   fclose(cfPtr);
   return 0;
}


void leggi (FILE *fptr)
{
   char temp[100];
   int i;
   int j=0;//contatore posizione
   int df=0; //numero decimale rilevato

   fscanf(fptr, "%s", temp);
   for (i=0;temp[i]!='\0';i++)
   {
      if (temp[i]=='.')
      {
         printf("Il numero di posizione %d è decimale\n",j);
         df=1;
      }
      else if (temp[i]=='-')
      {
         if (df!=1) {
            printf("Il numero di posizione %d è intero\n",j);
         }
         df=0;
         j++;
      }
   }
}


Utilizzando il file .txt strutturato in questo modo:
1235.56-4584-6558-125.245


Invece non riesco ancora a capire come fare se il file .txt è strutturato in colonna, cioè:
1235.56
4584
6558
125.245


Grazie
Ciaoo :)

el_brando
Sì il tuo codice funziona per quella specifica istanza del problema, però si può fare qualcosa di più generale. Poi non capisco perchè stampi la posizione del numero quando il testo ti chiede di stampare il numero, se non ho capito male.

Allora io posso proporti una soluzione generale, visto che non abbiamo indicazioni sulla struttura del file. Innanzi tutto un file di testo può essere visto come un elenco di righe, quindi possiamo esaminarlo leggendo una riga alla volta. Una volta acquisita una riga cerchiamo al suo interno se vi sono '.' e poi "espandiamo" a destra e a sinistra di questo carattere la sottostringa, composta solo da cifre decimali, più lunga. La giustapposizione di sottostringa sinistra, '.' e sottostringa destra è il numero floating point che dobbiamo stampare. Questo procedimento va ripetuto per tutti i '.' incontrati nella riga. Effettivamente a parole è un pò difficile da spiegare, forse capisci meglio con l'algoritmo:

mentre il file non è vuoto
  riga := leggi una riga dal file;
  n := |riga|;
  i := 0;
  mentre i < n
    se riga[i] = '.'
      allora
        sx := i - 1;
        mentre sx >= 0 e riga[sx] è una cifra decimale
          sx := sx - 1;
        fineciclo
        dx := i + 1;
        mentre dx < n e riga[dx] è una cifra decimale
          dx := dx + 1;
        fineciclo
        se sx != i - 1 e dx != i + 1
          allora
            num_fl := copio tutti i caratteri da riga[sx+1] a riga[dx-1];
            stampo num_fl;
            i := dx + 1;
        finese
    finese
    i := i + 1;
  fineciclo
fineciclo

vict85
Io mi riferivo a qualcosa di più semplice. Prendi il valore come un double, quindi usi modf per dividere tra parte intera e frazionaria ed infine testi che la parte frazionaria sia zero. Il problema è che esistono molti modi per inserire un float.

el_brando
Da quanto ho capito, questo è un esercizio di programmazione. Quindi direi che il focus è più sulla parte algoritmica. Poi, senza assunzioni sull'input, il file da analizzare potrebbe essere il seguente:

123
123.34
sd34.6 5
123.45.55f
3456.56.dd
2.4f5f5.7
1235.56-4584-6558-125.245

1235.56
4584
6558
125.245

ed in questo caso la mia soluzione rileva effettivamente i float.

vict85
Ma non lo fa se il file include cose del tipo 1E+23 o 123E-1

el_brando
Certamente, hai perfettamente ragione. Per questo motivo nel mio secondo post ho suggerito che è necessario fare un'analisi del problema e vedere quali obbiettivi dovrà avere l'algoritmo che dobbiamo scrivere. Io ho fatto implicitamente delle assunzioni, trovando una soluzione che ricoprisse la maggior parte dei casi e fosse al contempo semplice. In questo caso è il testo stesso che è ambiguo, in quanto si può intendere come la ricerca di una stringa con il formato floating point oppure una stringa che corrisponde ad un numero floating point. Io ho scelto quindi di ricercare una stringa che indica un numero diciamo "con la virgola" (che secondo me è la più plausibile).

floppyes
Ciao!

Grazie per le risposte. In effetti non avevo considerato il caso della notazione scientifica o esponenziale!

Ora provo a riscrivere un po' il codice e vediamo cosa esce :D

Grazie
Ciaoo :)

vict85
Dal punto di vista implementativo penso possa essere una buona idea creare un automa.

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