Input/Output carattere per carattere

es01. (stampavideo1) Scrivere un programma che stampi a video il contenuto del file in.txt.

es02. (stampavideo2) Scrivere una funzione che riceva in ingresso il nome di un file e ne stampi a video il contenuto. Utilizzare la funzione per mostrare il contenuto dei file in.txt e in2.txt.

es03. (contacaratteri) Scrivere una funzione che, ricevuto in ingresso il nome di un file, restituisca il conteggio dei caratteri presenti al suo interno oppure -1 nel caso in cui non sia possibile accedere al file. Utilizzare la funzione per mostrare il numero di caratteri dei file in.txt, in2.txt e nonesiste.txt (si supponga che quest'ultimo file non sia presente nel disco), emettendo un apposito messaggio in presenza di errori di apertura dei file.

es04. (contaparole) Un file di testo contiene un certo numero di parole. Ogni parola (a eccezione dell'ultima) e` separata da quella successiva da un solo carattere di whitespace. Scrivere un programma che, richiesta l'immissione da tastiera del nome del file da elaborare, visualizzi il conteggio delle parole contenute (suggerimento: contare i whitespace...).

es05. (copiafile1) Scrivere una funzione che, ricevuti in ingresso i nomi di due file, effettui la copia carattere per carattere del primo file nel secondo file. La funzione restituisce true se la copia si e` conclusa con successo, false in caso contrario. Utilizzare la funzione per copiare il file in.txt nel file out.txt.

es06. (copiafile2) Scrivere un programma che effettui la copia un file di testo in un altro file trasformando le lettere minuscole in maiuscole e le maiuscole in minuscole.

es07. (copialettere) Scrivere un programma che, richiesto da tastiera il nome di un file testo, memorizzi i caratteri dell'alfabeto nel file lettere.txt e tutti gli altri caratteri in altri_car.txt.

es08. (accodaparole) Dopo aver creato due file di testo parole1.txt e parole2.txt, ciascuno contenente un elenco di parole separate da uno spazio, scrivere un programma che accodi il contenuto del primo file al secondo file. Alla fine dell'esecuzione, osservare il contenuto del secondo file con un editor testuale.



Input/Output per linee di testo

es09. (inverti) Scrivere un programma che inverta ogni riga contenuta nel file righe.txt e riporti il risultato sullo schermo (per esempio, la riga Prova di stampa diventa apmats id avorP).

es10. (filtralinee) Scrivere una funzione che accetti come parametri d'ingresso due nomi di file e una parola P e memorizzi nel secondo file le sole righe del primo che contengono P (suggerimento: usare la funzione strstr).

es11. (accodalinee) Scrivere un programma che, chiesto in input il nome di un file di testo, accodi le linee del file al file di output risultato.txt, sostituendo le linee più lunghe di 20 caratteri con la stringa --LINEA TROPPO LUNGA--.

es12. (contalinee) Scrivere una funzione che accetti due parametri (un nome di file e una stringa S) e restituisca il conteggio delle righe contenenti S oppure -1 nel caso di errori nella gestione del 
file. Dopo aver creato un file di testo, utilizzare la funzione per contare le linee del file che contengono la parola BIANCO.

es13. (paginaweb) Scrivere un programma che generi automaticamente una pagina web di nome test.html avente il seguente contenuto testuale:
<!doctype html>
<html lang="it">
	<head>
		<meta charset='UTF-8'>
		<title>Pagina generata automaticamente</title>
	</head>
	<body>
		<p style='color: red;'>
			Questa pagina &egrave; stata generata automaticamente
			da un programma scritto in linguaggio C.
		</p>
	</body>
</html>



Input/Output formattato

es14. (numeri) Scrivere un programma che memorizzi in un file di testo e su una sola linea i primi 15 numeri pari separati da uno spazio.

es15. (multipli) Scrivere una funzione a due parametri interi A e N che memorizzi nel file di testo output.txt i primi N multipli di A (un solo multiplo per ogni riga).

es16. (casuali) Scrivere una funzione che, ricevuti in ingresso un nome di file e un numero intero N, memorizzi nel file N numeri casuali disposti a coppie su linee diverse (una coppia per ogni linea).

es17. (statistica) Scrivere un programma che, a partire da uno dei file prodotti nell'esercizio precedente, determini, per ogni coppia, una statistica formata dalla somma e dalla media dei due valori, riportando i risultati nel file statistica.txt (una statistica per ogni linea; all'interno della linea, separare la somma dalla media con un tabulatore).

es18. (occorrenze) Scrivere una funzione che, ricevuti in ingresso un nome di file e una parola S, restituisca il numero di occorrenze di S all'interno del file oppure -1 in caso di errore nella gestione del file. La funzione opera sotto le seguenti condizioni: una parola è una sequenza di caratteri priva di whitespace; un file è composto da una sequenza di parole separate da whitespace; la ricerca delle occorrenze è di tipo case insensitive.

es19. (maxmin) Scrivere un programma che calcoli il massimo e il minimo di una sequenza di valori interi contenuti in un file numeri.txt e memorizzi i risultati in maxmin.txt su due righe diverse nel seguente formato:
Valore minimo: ....
Valore massimo: ....
Si ipotizzi di non conoscere a priori ne` il numero esatto di valori contenuti nel file ne` il numero massimo di valori previsto per questo esercizio.

es20. (voti1) Un file di testo voti.txt contiene i voti di un certo numero di studenti secondo il seguente formato:
<cognome> <nome> <N> <voto1> <voto2> ... <votoN>
Poiche` ogni studente puo` avere un numero diverso di voti, ogni riga include (dopo il nome) il numero N di voti registrati per quello studente, seguito da un elenco di N voti (approssimati a una cifra decimale). Un possibile esempio di file e` il seguente:
Bianchi Paolo 3 7.0 7.5 6.0
Rossi Maria 4 8.5 8.0 8.0 9.0
Scrivere un programma che acquisisca i voti degli studenti e produca in output:
a) Il file medie.txt contenente le medie (approssimate a due cifre decimali) dei voti di ciascuno studente, nel formato:
<cognome> <nome> <media>
b) Il file esiti.txt contenente l'esito di fine anno scolastico di ogni studente: "debito" se la media e` inferiore a 6, "promosso" in caso contrario. Il formato del file e` <cognome> <nome> <esito>

es21. (misurecampo) Si vuole realizzare un programma che calcoli il perimetro e l'area di un terreno poligonale.
Utilizzando un ricevitore GPS si determinano innanzitutto le coordinate x,y degli N vertici del poligono. I dati sono successivamente memorizzati in un file di testo secondo il seguente formato:
u_m
N
x0 y0
x1 y1
.
xN-1 yN-1
La prima riga del file contiene una stringa rappresentante l'unita` di misura in cui sono espresse le coordinate; la seconda riga contiene un intero N che indica il numero dei vertici del poligono; le successive N righe contengono le coordinate reali dei vertici (una coppia di coordinate per ogni riga).
Il programma deve svolgere le seguenti operazioni:
a) chiedere all'utente il nome del file di input e acquisirne l'intero contenuto, memorizzando le coordinate in un'apposita struttura dati;
b) determinare il perimetro e l'area del terreno utilizzando le seguenti formule:
perimetro: P = somma{k =0->N-1} (x[(i+1)mod N]-x[i])^2 + (y[(i+1)mod N]-y[i])^2 (somma dei lati)
area: A = 1/2*|somma{k=0,N-1} (x[i]*y[(i+1) mod N] + x[(i+1) mod N]*y[i])| (formula di Gauss)
c) chiedere all'utente il nome di un file di ouput e memorizzare al suo interno i risultati ottenuti (valore e unita` di misura di perimetro e area).
Per esempio, a partire dal seguente file di input:
dam
6
-0.57  -1.05
 4.05   8.19
15.60  10.50
24.84   3.57
20.22  -1.05
 8.67  -3.36
il programma deve riportare in un nuovo file i messaggi:
Perimetro: 61.50 dam
Area: 229.45 dam^2

es22. (scrivitab) Scrivere un programma che legga da tastiera e memorizzi in un'apposita struttura dati la seguente tabella:
+-----------------+-----------------+-------------+-------------+
| Cognome         | Nome            | Altezza (m) | Peso (kg)   |
+-----------------+-----------------+-------------+-------------+
| Rossi           | Mario           |        1.75 |          76 |
| Ferraro         | Carlo           |        1.84 |          82 |
| Marelli         | Chiara          |        1.65 |          58 |
+-----------------+-----------------+-------------+-------------+
Terminato il caricamento, il programma deve memorizzare l'intera tabella nel file di testo tabella.txt (un record per linea, campi separati con un tabulatore; non deve essere memorizzata la riga d'intestazione). Si ipotizzi che tutti i campi testuali siano privi di spazi, che le altezze siano numeri float e i pesi numeri interi.

es23. (mostratab) Scrivere un programma che acquisisca da un file di testo la tabella dell'esercizio precedente e la visualizzi sullo schermo nel seguente formato:
+-----------------+-----------------+-------------+-------------+
| Cognome         | Nome            | Altezza (m) | Peso (kg)   |
+-----------------+-----------------+-------------+-------------+
| Rossi           | Mario           |        1.75 |          76 |
| Ferraro         | Carlo           |        1.84 |          82 |
| Marelli         | Chiara          |        1.65 |          58 |
+-----------------+-----------------+-------------+-------------+



Esercizi extra (file di testo)
// es91: Scrivere un programma che legge da file di testo una sequenza di parole e scrive un nuovo file sostituendo ad alcune parole (presenti in una lista) i loro contrari. Es: odio->amore, guerra->pace, ecc.
void uno(char c) {
	static char parola[50+1] = "";
	static char oldc = ' ';
	static unsigned i = 0;

	if (isspace(c))
		if (isspace(oldc)) {
			// due spazi consecutivi
			printf("%c", c);
		else {
			// e` appena terminata una parola; se appartiene ad una lista, sostituiscila
			parola[i++] = '\0';
			if (strcmp(parola, "odio"))
				strcpy(parola, "amore");
			else if (strcmp(parola, "guerra"))
				strcpy(parola, "pace");
			printf("%s", parola);
			i = 0;
		}
	}
	else
		// accodo la lettera in una parola
		parola[i++] = c;
	oldc = c;
}

// es92: Scrivere un programma che legge da file di testo una stringa e un carattere e verifica se il carattere e` presente nella stringa. Il risultato viene scritto su un nuovo file: se il carattere e` presente scrive "true", altrimenti scrive "false"
bool presente(char str[], char c) {
	// soluzione1
	bool result = false;
	for (unsigned int j = 0; j < strlen(str); j++) {
		if (str[j]==c) {
			result = true;
			break;
		}
	}
	return result;

	// soluzione2
	return (strchr(str, c) != NULL);
}


// es93: Scrivere un programma che legge da file di testo una stringa e la riscrive su un nuovo file dopo averla ruotata a SX per num volte.
void nshift(char stringa[], unsigned int num) {
	for (unsigned int j = 0; j < num; j++) {
		char temp = stringa[0];
		for (unsigned int i = 0; i < strlen(stringa)-1; i++)
			stringa[i] = stringa[i+1];
		stringa[strlen(stringa)-1] = temp;
	}
}

/*
Soluzione impropria (con fread/fwrite) dell'es05(copiafile1).
E' evidente che il file non viene copiato "carattere per carattere" ma "1000 caratteri per 1000 caratteri"
*/
bool es05(const char * filenamein, const char * filenameout) {
	FILE * fi = fopen(filenamein, "r");
	if (fi != NULL) {
		FILE * fo = fopen(filenameout, "w");
		if (fo != NULL) {
			char buffer[MAXBUFFER]; // non e` una stringa, ma una sequenza di bytes...
			int nr, nw;
			while ((nr = fread(buffer, sizeof(buffer[0]), MAXBUFFER, fi)) > 0) {
				nw = fwrite(buffer, sizeof(buffer[0]), nr, fo);
				if (nw < nr)
					return false;
			}
			if (fclose(fo)<0)
				return false;
		}
		if (fclose(fi)<0)
			return false;
	}
	return true;
}

/*
Soluzione impropria (con fread/fwrite) dell'es10(filtralinee).
Contiene una apertura multipla del file di input, l'utilizzo di un buffer come stringa, e altra brutta roba
*/
void es10(const char * filenamein, const char * filenameout) {
	char parola[] = "ciao";

	FILE * fi = fopen(filenamein, "r");
	if (fi != NULL) {
		FILE * ft = fopen(filenamein, "r"); // ad esclusivo uso della fread
		int n = 0;
		int c;
		while((c=fgetc(fi))!=EOF) {
			n++;
			if (c=='\n'){
				char frase[n+1];
				int nr = fread(frase, sizeof(frase[0]), n, ft);
				frase[nr] = '\0';

				if (nr < n)
					// TODO: gestire errore
					;

				if (strstr(frase, parola)!=NULL) {
					// TODO: gestire errori
					FILE * fo = fopen(filenameout, "a");
					fwrite(frase, sizeof(frase[0]), nr, fo);
					fclose(fo);
				}
				n = 0;
			}
		}
		fclose(ft);
		fclose(fi);
	}
}