Elaborazione File di testo.

di il
10 risposte

Elaborazione File di testo.

Ciao a tutti! sono bloccato da un pò di tempo con la realizzazione di un esercizio, che chiede di elaborare un file di testo.

(Sto studiando da autodidatta , perciò non so a chi chiedere, non posto il nome del libro ma se mi dite che posso lo farò, scusate ma sono nuovo su questo Forum).

L'esercizio dice:

Scrivere un programma che elabora file di testo. Il programma deve leggere un file di testo e visualizzare i dati in esso contenuti, cosi come sono, oltre al numero di parole, di righe e di paragrafi ( nel file di ingresso sono separati da una riga vuota ), Scrivere ed utilizzare le seguenti funzioni:

Initialize: Inizializza tutte le variabile della funzione main.

processBlank: Questa funzione legge e scrive caratteri di spaziatura. Ogni volta che incontra un carattere che non sia di spaziatura, incrementa il numero di parole presenti nella riga, la funzione termina dopo aver elaborato tutti i caratteri di spaziatura.

copyText: Questa funzione legge e scrive i caratteri che non sono di spaziatura, appena trova un carattere di spaziatura termina.

updateCount: questa funzione viene eseguita al termine di ogni riga: aggiorna il conteggio totale delle parole, incrementa il numero di righe e riporta a zero il numero di parole presenti nella riga che si sta leggendo. Se la riga letta non aveva parole, incrementa il numero di paragrafi: per separare un paragrafo dall'altro si usa una righa vuota, che non deve modificare il conteggio delle righe.

printTotal: questa funzione visualizza il numero di parole, il numero di righe e il numero di paragrafi.

Il programma deve leggere dati da un file e scrivere i risultati in un file, non usare variabili globali.

Collaudare il programma usando la seguente funzione main:

int main()

{

dichiarazione di variabili

apertura dei file

lettura di un carattere

while(il file non è finito)

{

while(la righa non è finita)

{

processBlank(parametri);

copyText(parametri);

}

updateCount(parametri);

lettura di un carattere

…

}

printTotal(parametri);

chiusura dei file;

return 0;

}

Ecco,  da questo capisco che non devo usare stringhe e devo passare tutti i valori per riferimento, il mio dubbio iniziale era nei “…” inseriti dopo la lettura del carattere all'interno del ciclo while. 

Il mio codice è questo, rimango bloccato alla lettura dell'ultimo carattere, ( fermando il programma ed analizzando vedo che rimane in un ciclo infinito di lettura, nel ciclo while (carattere != ‘\n’) c'è il ( in.get(carattere); ), rimane li, continua a leggere il carattere ed a stamparlo, se termino il programma ed apro il file “Risultato”, mi copia perfettamente tutto il testo, ma scrive all'infinito l'ultimo carattere.

#include <iostream>
#include <fstream>
#include <cmath>
#include <string>
#include <cstring>
#include <Windows.h>
#include <iomanip>
#include <cstdlib>
// Ho tutte queste inclusioni perchè nello stesso progetto ho più esercizi.

void initialize(int& numparole, int& TOTparole, int& righe, int& paragrafi, char& carattere);
void processBalnk(ifstream& in, ofstream& out, int& numparole, char& carattere);
void copyText(ifstream& in, ofstream& out, char& carattere);
void updateCount(int& numparole, int& TOTparole, int& righe, int& paragrafi, char& carattere);
void printTotal(int& TOTparole, int& righe, int& paragrafi);

int main()
{
int numparole, TOTparole, righe, paragrafi;
char carattere;
initialize(numparole, TOTparole, righe, paragrafi, carattere);

ifstream in;
ofstream out;

in.open("Testo.txt");
out.open("Risultato.txt");

while (!in.eof())
{
 while (carattere != '\n')
 {
  in.get(carattere);
  processBalnk(in, out, numparole, carattere);
  copyText(in, out, carattere);
 }
 updateCount(numparole, TOTparole, righe, paragrafi, carattere);

 // qua ripeto la lettura del carattere per determinare il paragrafo
 in.get(carattere);
 updateCount(numparole, TOTparole, righe, paragrafi, carattere);
 out << "\n";

 // qua inserisco di nuovo le funzioni per non perdere il carattere letto al di fuori del ciclo
 in.get(carattere);
 processBalnk(in, out, numparole, carattere);
 copyText(in, out, carattere);
}
printTotal(TOTparole, righe, paragrafi);

in.close();
out.close();

return 0;
}

void initialize(int& numparole, int& TOTparole, int& righe, int& paragrafi, char& carattere)
{
numparole = 0;
TOTparole = 0;
righe = 0;
paragrafi = 0;
carattere = 0;
}

void processBalnk(ifstream& in, ofstream& out, int& numparole, char& carattere)
{
if (carattere == ' ' || carattere == '\t')
{
 out << carattere;
 numparole++;
}
}

void copyText(ifstream& in, ofstream& out, char& carattere)
{
if (carattere != ' ' && carattere != '\t')
{
 out << carattere;
}
}

void updateCount(int& numparole, int& TOTparole, int& righe, int& paragrafi, char& carattere)
{
if (carattere == '\n' && numparole > 0)
{
 righe++;
 numparole++;
 TOTparole += numparole;
}
else if (carattere == '\n' && numparole == 0)
{
 paragrafi++;
}
}

void printTotal(int& TOTparole, int& righe, int& paragrafi)
{
cout << "Parole totali: " << TOTparole << endl;
cout << "Righe totali: " << righe << endl;
cout << "Paragrafi: " << paragrafi << endl;
}

10 Risposte

  • Re: Elaborazione File di testo.

    Prima di tutto inserisci tutti i codici che scrivi nel forum tra tag CODE (tasto <>) in modo che siano ben leggibili, come da regolamento.

    Per il problema ti chiedo se l'ultima riga del tuo file di testo ha un ritorno a capo o no.

  • Re: Elaborazione File di testo.

    È un semplice file di testo ( testo.txt) dove ho copiato del testo di un libro, e dopo l'ultima riga, non c'è più niente, solo spazi vuoti. 

    Ergo, il problema sta nella lettura dell'ultimo carattere ( che nel mio caso è un punto ), nonostante il primo ciclo while monitora se il file è finito.

  • Re: Elaborazione File di testo.

    Rileggi quello che ti ho scritto e, se vuoi, rispondi… hai un ritorno a capo dopo l'ultimo carattere dell'ultima riga o no?

    Se non hai chiara la domanda, facci scaricare il file di testo che hai usato.  

  • Re: Elaborazione File di testo.

    No, non un ritorno a capo, allego comunque il file.

    https://it.wikipedia.org/wiki/C%2B%2B Ho usato i primi due paragrafi di questo testo, e lo copiato dentro un file di testo semplicissimo, per poter usarlo come prova.

  • Re: Elaborazione File di testo.

    Il problema te l'ha indicato oregon. Tieni conto che in.get(carattere) ha return value NULL quando arrivi alla fine del file (e carattere non viene alterato) e prova a risolvere in base a questa informazione.

  • Re: Elaborazione File di testo.

    Ho provato a fare: 

    while(carattere != ' ' && carattere != '\t' && carattere != '\n')
    {
    bool vero (in.get(carattere));
    
    if(&vero)
    {
    out << carattere;
    else
    {
    carattere = '\n\;
    }
    }

    il problema che perdo un carattere letto in precedenza da processBalnk, perchè il bool rilegge un carattere a sua volta, e se legge uno spazio lo da come vero allora scrive lo spazio, ma non dovrebbe perchè è compito di processbalnk

  • Re: Elaborazione File di testo.

    https://cplusplus.com/reference/istream/istream/get/

    Così si legge un file un carattere alla volta

    #include <iostream>     // std::cin, std::cout
    #include <fstream>      // std::ifstream
    
    int main () {
      char str[256];
    
      std::cout << "Enter the name of an existing text file: ";
      std::cin.get (str,256);    // get c-string
    
      std::ifstream is(str);     // open file
    
      char c;
      while (is.get(c)){       // loop getting single characters
        std::cout << c;
        // qui fai le tue cose col carattere che stai leggendo 
      }
      is.close();                // close file
    
      return 0;
    }

    Poi cambia libro, perché leggere un file impostando il doppio while in quel modo ha delle trappole come quella in cui sei incappato

  • Re: Elaborazione File di testo.

    17/06/2023 - Weierstrass ha scritto:


    https://cplusplus.com/reference/istream/istream/get/

    Così si legge un file un carattere alla volta

    #include <iostream>     // std::cin, std::cout
    #include <fstream>      // std::ifstream
    
    int main () {
      char str[256];
    
      std::cout << "Enter the name of an existing text file: ";
      std::cin.get (str,256);    // get c-string
    
      std::ifstream is(str);     // open file
    
      char c;
      while (is.get(c)){       // loop getting single characters
        std::cout << c;
        // qui fai le tue cose col carattere che stai leggendo 
      }
      is.close();                // close file
    
      return 0;
    }

    Poi cambia libro, perché leggere un file impostando il doppio while in quel modo ha delle trappole come quella in cui sei incappato

    Ti ringrazio molto per l'aiuto, però non è quello il mio obbiettivo, mi spiego: ho già risolto questo esercizio utilizzando delle string, che con le giuste funzioni riesci perfettamente ad elaborare le singole righe, ma l'esercizio richiede proprio di usare quella funzione main e di usare la luttura del singolo carattere.

    Ringrazio tutti per l'aiuto dato, ho ancora però una domanda, è possibile far funzionare due funzioni contemporaneamente nello stesso ciclo? 

  • Re: Elaborazione File di testo.

    Che vuol dire contemporaneamente? Prima esegui la prima e poi la seconda nel ciclo.

    Per leggere un file di testo ti stai complicando la vita. Posta un link per scaricare progetto e file di testo che utilizzi per le prove e li guardo

  • Re: Elaborazione File di testo.

    Ho risolto! usando quella funzione main! Ho dovuto creare un semplicissimo bool…  

    Se trovate errori o miglioramenti sono ben accetti, non sarà un gran che! ma funziona. 

    Ovviamente come ha consigliato “Weierstrass” , utilizzare un Arry di carattere è la cosa migliore, però non potevo usarle, il libro le spiega nel prossimo capitolo.

    Grazie a tutti per l'aiuto, posto la soluzione in caso servisse a qualcuno! 

    void scriviRisultato(int& parole, int& righe, int& paragrafi);
    void aggiorna(ofstream& out, char& c, int& numparole, int& righe, int& paragrafi, int& parole, bool& vero);
    void inizializza(int& numparole, int& righe, int& paragrafi, int& parole, bool& vero);
    void scrivitesto(ifstream& in, ofstream& out, char& c);
    void contaparole(ifstream& in, ofstream& out, char& c, int& numparole, bool& vero);
    
    int main()
    {
    	char c = 0;
    	bool vero;
    	int numparole, parole, righe, paragrafi;
    	inizializza(numparole, righe, paragrafi, parole, vero);
    
    	ifstream in;
    	ofstream out;
    
    	in.open("Testo.txt");
    	out.open("ScriviTesto.txt");
    
    	in.get(c);
    
    	while (!in.eof())
    	{
    		while (c != '\n')
    		{
    			contaparole(in, out, c, numparole, vero);
    			scrivitesto(in, out, c);
    		}
    		aggiorna(out, c, numparole, righe, paragrafi, parole, vero);
    		in.get(c);
    	}
    	scriviRisultato(parole, righe, paragrafi);
    
    	in.close();
    	out.close();
    
    	return 0;
    }
    
    void contaparole(ifstream& in, ofstream& out, char& c, int& numparole, bool& vero)
    {
    
    	if (vero)
    	{
    		if (c != 32)
    		{
    			numparole++;
    			vero = false;
    		}
    	}
    		if (c == 32)
    		{
    			out << ' ';
    			vero = true;
    		}
    }
    
    void scrivitesto(ifstream& in, ofstream& out, char& c)
    {
    	if (c != ' ')
    	{
    		out << c;
    	}
    	in.get(c);
    
    	if (c == '\n')
    	{
    		out << '\n';
    		out << '\n';
    	}
    }
    
    void inizializza(int& numparole, int& righe, int& paragrafi, int& parole, bool& vero)
    {
    	numparole = 0;
    	righe = 0;
    	paragrafi = 0;
    	parole = 0;
    	vero = true;
    }
    
    void aggiorna(ofstream& out, char& c, int& numparole, int& righe, int& paragrafi, int& parole, bool& vero)
    {
    		if (numparole > 0 && c == '\n')
    		{
    			righe++;
    			parole += numparole;
    			numparole = 0;
    			vero = true;
    		}
    		else if (numparole == 0 && c == '\n')
    		{
    			paragrafi++;
    			vero = true;
    		}
    }
    
    void scriviRisultato(int& parole, int& righe, int& paragrafi)
    {
    	cout << "Righe totali: " << righe << endl;
    	cout << "Parole totali: " << parole << endl;
    	cout << "Paragrafi: " << paragrafi << endl;
    }
Devi accedere o registrarti per scrivere nel forum
10 risposte