next up previous contents index
Next: Indice analitico Up: Cenni sulla IOStream Previous: ios   Indice   Indice analitico

fstream

Abbiamo detto presentando la libreria IOStream che i progettisti hanno deciso di fornire una interfaccia comune per ogni possibile tipo di stream; compresi nella libreria ci sono, oltre a istream e ostream, altre classi per la gestione specifica di stream su file e in memoria: sono, rispettivamente, le classi ofstream e ostrstream (e le corrispondenti per l'input). Entrambe derivano anche da ostream (istream), per cui tutte le funzioni membro per la scrittura/lettura fino ad ora presentate sono utilizzabili anche le nuove arrivate. Tralasceremo la presentazione di strstream per due motivi: le modalità di utilizzo dovrebbero essere ovvie non appena letta la guida del proprio compilatore al proposito; rischiano di diventare obsolete tra non molto, a causa delle più sofisticate stringstream, cui non accenneremo in quanto esse si basano sul tipo string, la cui trattazione non è stata inserita in questo testo. Le intestazioni delle classi fstream si trovano nell'omonimo file, così come quelle per le strstream.

I costruttori della classi ifstream e ofstream sono i seguenti12.6:

ifstream::ifstream ()
ifstream::ifstream (char* nome, int modalita)
ofstream::ofstream ()
ofstream::ofstream (char* nome, int modalita)

I costruttori default creano un oggetto di tipo ifstream o ofstream senza che esso venga collegato ad alcun file, per cui prima di effettuare qualunque operazione è necessario chiamare la funzione membro (sia per ifstream che per ofstream):

void open (char* nome, int modalita)

Il significato degli argomenti è il medesimo nei costruttori e in open, cioè: nome è una stringa rappresentante il nome del file da aprire; modalita specifica la modalità di apertura del file12.7:

A questo punto presentiamo tre semplici (utili) esempi riguardo l'utilizzo dei file tramite la IOStream12.8.

Il primo esempio è un programmino per effettuare la copia di un file su di un altro; esso presuppone che l'utente inserisca da riga di comando il nome del file sorgente come primo argomento e quello di destinazione come secondo e ultimo argomento; nel caso il secondo argomento non venga specificato, l'uscita viene indirizzata sullo standard output. La copia avviene carattere per carattere, tramite le funzioni get() e put().


// ex12_6_8.cpp
// copia un file in un altro
#include <iostream.h>
#include <fstream.h>
int main (int argc, char** argv) {
  // vogliamo che l'utente immetta almeno un argomento
  if (argc < 2) {
    cout << "ATTENZIONE\n"
      "\tdevi specificare almeno il file\n"
      "\tsorgente come argomento" << endl;
    return 1;
  }
  // ricordiamo che argv[0] e` il nome
  // dell'eseguibile avviato
  ifstream in  (argv[1], ios::in);
  if (!in) {
    cout << "ATTENZIONE\n"
      "\tci sono problemi in fase di apertura\n"
      "\tdel file sorgente che hai specificato\n"
      "\t(probabilmente sorgente non esiste)" << endl;
    return 1;
  }

  // effettuiamo la copia per carattere
  char c;
  // se non e` stato specificato il secondo argomento
  // l'output avviene a video
  if (argc >= 3) {
    ofstream out (argv[2], ios::out);
    while (in.get(c))
      out.put(c);
  }
  else
    while (in.get(c))
      cout.put(c);

  return 0;
}

L'esempio successivo apre un file in lettura, come primo argomento da riga di comando, e ne stampa il numero di parole (qualunque stringa separata da almeno uno spazio è considerata ``parola'') e di righe. Viene usato, rispettivamente, l'operatore `<<' e la funzione membro getline().


// ex12_6_9.cpp
#include <iostream.h>
#include <fstream.h>
const int MAX_LUNG_PAROLA = 200;
const int MAX_LUNG_RIGA   = 500;
int main (int argc, char** argv) {
  if (argc < 2) {
    cout << "manca un argomento" << endl;
    return 1;
  }

  // inizializza variabili
  ifstream in (argv[1], ios::in);
  char pbuf[MAX_LUNG_PAROLA];
  char rbuf[MAX_LUNG_RIGA];

  // conta parole
  unsigned counter = 0;
  while (in >> pbuf) counter++;
  cout << "no. parole:\t" << counter << endl;

  // resetta variabili
  counter = 0;
  in.close();
  in.open(argv[1], ios::in);

  // conta righe
  while (in.getline(rbuf, MAX_LUNG_RIGA)) counter++;
  cout << "no. righe:\t" << counter << endl;
  return 0;
}

L'ultimo esempio consiste in un programmino che sostituisce in un file tutte le occorrenze di una stringa (se separata da spazi dalle altre stringhe) con un altra e salva il tutto in un secondo file; esso accetta da riga di comando tre argomenti: il nome del file da aprire, la stringa sostituenda, la stringa sostituente. Abbiamo utilizzato l'operatore `<<' per effettuare un rozzo parsing sul file in entrata, il quale elimina gli spazi bianchi; siccome vogliamo che in uscita il nostro file modificato mantenga questi ultimi inalterati, abbiamo utilizzato un piccolo artificio, che tra l'altro ci permette di mostrare un semplice utilizzo della funzione peek().


// ex12_6_10.cpp
// cerca all'interno di un file XXX una stringa
// e la sostituisce con un altra
// salvando il risultato nel file XXX.sub
#include <iostream.h>
#include <fstream.h>
#include <string.h>
const int MAX_LUNG_PAROLA = 500;
int main (int argc, char** argv) {
  if (argc < 4) {
    cout << "mancano " << (4-argc) <<
      " argomenti" << endl;
    return 1;
  }
  
  // apre il file argv[1] in lettura
  ifstream in(argv[1], ios::in);
  if (!in) {
    cout << "il file " << argv[1] <<
      " non esiste" << endl;
    return 1;
  }
  const int n = strlen(argv[1]);
  char* nomeFileOut = new char[n + 5];
  for (int i = 0; i < n; i++)
    nomeFileOut[i] = argv[1][i];
  nomeFileOut[n]   = '.';
  nomeFileOut[n+1] = 's';
  nomeFileOut[n+2] = 'u';
  nomeFileOut[n+3] = 'b';
  nomeFileOut[n+4] = '\0';
  // apre il file nomeFileOut in scrittura
  ofstream out (nomeFileOut, ios::out);

  // effettua un rozzo parsing del file sorgente
  // cercando le occorrenze da sostituire
  int counter = 0;
  char buf[MAX_LUNG_PAROLA];
  while (1) {
    if (!in) break;
    switch (in.peek()) {
    case '\n': out << '\n'; break;
    case ' ':  out << ' '; break;
    }
    in >> buf;
    if (strcmp(buf, argv[2]) == 0) {
      out << argv[3];
      counter++;
    }
    else
      out << buf;
  }
  cout << "modificate " << counter <<
    " parole" << endl;
  return 0;
}


next up previous contents index
Next: Indice analitico Up: Cenni sulla IOStream Previous: ios   Indice   Indice analitico
Claudio Cicconetti
2000-09-06