Torna al blog
Cottimizzazionealgoritmiprogrammazione

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.

Pubblicato 14 maggio 20263 min di lettura
Miglioramento algoritmico in C: contare caratteri con fgetc()

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:

  1. Start
  2. Input: nome del file dall’utente
  3. Apertura del file in lettura
  4. Se il file non esiste → errore e uscita
  5. Se esiste → ciclo di lettura carattere per carattere fino a EOF
  6. Per ogni carattere:
    • se è 'a' → incrementa contatore count_a
    • se non è newline '\n' → incrementa count_total
  7. Stampa i due risultati
  8. 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!