Miglioramento algoritmico in C: contare caratteri con fgetc()
Come ragionare per ottimizzare il codice in C, delegare calcoli a basso livello e migliorare le performance. Primo esercizio: contare le 'a' minuscole e i caratteri totali da file.

In questa nuova serie dedicata al miglioramento algoritmico in C (non un tutorial sul C puro) andiamo a vedere come ragionare meglio, come ottimizzare il codice e come ampliare la nostra capacità di visione e pensiero. Queste competenze sono fondamentali quando, durante il building pubblico, le risorse sul server aumentano e ci troviamo con software mal ottimizzati da sistemare. Impareremo a:
- allocare risorse in modo efficiente
- alleggerire il sovraccarico della CPU
- delegare parti di calcolo a un linguaggio di basso livello per ottimizzare il routing in uno di alto livello
👉 Link al Video (Video YT)
Il primo esercizio
L’esercizio proposto è il seguente:
Un file di testo, il cui nome viene richiesto all’utente, contiene caratteri qualsiasi. Scrivere un programma in C89 che:
- conti quante lettere
'a'minuscole sono presenti- conti quanti caratteri totali sono presenti
- visualizzi i due risultati. Utilizzare
fgetc().
Diagramma di flusso ragionato
Prima di scrivere una riga di codice, disegniamo il flusso logico:
- Start
- Input: nome del file dall’utente
- Apertura del file in lettura
- Se il file non esiste → errore e uscita
- Se esiste → ciclo di lettura carattere per carattere fino a EOF
- Per ogni carattere:
- se è
'a'→ incrementa contatorecount_a - se non è newline
'\n'→ incrementacount_total
- se è
- Stampa i due risultati
- Chiudi il file e termina
Implementazione in C89
Ecco il codice completo, con le accortezze necessarie per evitare errori comuni (come la segmentation fault dovuta a puntatori mal gestiti):
/* DOMANDA 1. (6 punti) Un file di testo, il cui nome viene richiesto all'utente, contiene caratteri qualsiasi. Scrivere un programma C89 che: - conti quante lettere 'a' minuscole sono presenti - conti quanti caratteri totali sono presenti - visualizzi i due risultati. Utilizzare fgetc(). */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 20 int main(){ char nome_file[MAX]; printf("Inserisci il nome file: "); scanf("%s", nome_file); FILE *fp; fp = fopen(nome_file, "r"); if(!fp){ return EXIT_FAILURE; } int ch, count_a = 0, count_total = 0; while ( (ch = fgetc(fp)) != EOF ){ if(ch == 'a'){ count_a = count_a + 1; } if (ch != '\n'){ count_total++; } } printf("Ci sono %d lettere 'a' in totale\n", count_a); printf("I caratteri totali sono: %d", count_total); fclose(fp); return EXIT_SUCCESS; }
Perché escludere \n?
Nel conteggio dei caratteri totali l’esercizio originale spesso si riferisce ai soli caratteri visibili o stampabili, escludendo il newline. Nel video abbiamo notato una discrepanza con i conteggi di un’intelligenza artificiale: il file conteneva 388 caratteri (esclusi i newline) e il programma, dopo aver aggiunto il controllo ch != '\n', ha prodotto lo stesso risultato. Senza quel filtro, i newline vengono contati in più, alterando il totale.
Lezioni di ottimizzazione implicite
Anche se l’esercizio è semplice, ci insegna principi importanti:
- Usare un solo ciclo per evitare di rileggere il file due volte (risparmio di I/O).
- Scartare subito i caratteri non necessari (come
\n) senza memorizzarli. - Gestire gli errori (file non trovato) con
EXIT_FAILURE. - Rispettare lo standard C89 (dichiarazioni all’inizio del blocco, niente commenti
//).
Delegare operazioni di conteggio a un linguaggio come C (basso livello) libera risorse nei linguaggi più alti (Python, JavaScript, ecc.) quando questi devono gestire routing o logiche complesse. Questo è il cuore della serie: non scrivere tutto in C, ma usare C per i colli di bottiglia computazionali.
Prossimamente: gestione della memoria, puntatori e ottimizzazione di algoritmi di ordinamento. Buon coding!