Stringhe, Date e Input Utente in C#

Manipolazione di testo, gestione del tempo e interazione con l’utente

📝 Operazioni sulle Stringhe

Le stringhe sono uno dei tipi di dati più utilizzati nella programmazione. In C#, le stringhe sono
oggetti immutabili che rappresentano sequenze di caratteri. La classe String
fornisce numerosi metodi per manipolare e trasformare il testo.

💡 Cosa Significa “Immutabile”?

Quando modifichi una stringa in C#, in realtà stai creando una nuova stringa
in memoria. La stringa originale non viene modificata. Questo è importante da capire per
ottimizzare le performance quando lavori con molte concatenazioni.

🔗 Creazione e Concatenazione

Metodi di Concatenazione
// Creazione di stringhe
string nome = "Mario";
string cognome = "Rossi";

// Concatenazione con l'operatore +
string nomeCompleto = nome + " " + cognome; // "Mario Rossi"

// Concatenazione con il metodo Concat
string nomeCompleto2 = String.Concat(nome, " ", cognome);

// Interpolazione di stringhe (C# 6.0+) - CONSIGLIATO
string saluto = $"Ciao, {nome} {cognome}!"; // "Ciao, Mario Rossi!"

// StringBuilder per concatenazioni multiple (più efficiente)
using System.Text;
StringBuilder sb = new StringBuilder();
sb.Append("Ciao, ");
sb.Append(nome);
sb.Append(" ");
sb.Append(cognome);
sb.Append("!");
string risultato = sb.ToString(); // "Ciao, Mario Rossi!"

⚡ Quando Usare StringBuilder?

Usa StringBuilder quando devi fare molte concatenazioni in loop o operazioni ripetute.
Per 2-3 concatenazioni semplici, l’operatore + o l’interpolazione $"" vanno benissimo.

🔍 Ricerca e Sostituzione

Metodi di Ricerca
string testo = "La programmazione in C# è divertente e potente";

// Ricerca
bool contiene = testo.Contains("C#");           // true
int posizione = testo.IndexOf("divertente");    // 26
bool iniziaCon = testo.StartsWith("La");        // true
bool finisceCon = testo.EndsWith("potente");    // true

// Sostituzione
string nuovo = testo.Replace("C#", "C Sharp"); 
// "La programmazione in C Sharp è divertente e potente"

// Divisione in base a un separatore
string[] parole = testo.Split(' ');
// ["La", "programmazione", "in", "C#", "è", "divertente", "e", "potente"]

Metodo Descrizione Ritorna
Contains(string) Verifica se contiene una sottostringa bool
IndexOf(string) Trova la posizione di una sottostringa int (-1 se non trovata)
Replace(old, new) Sostituisce tutte le occorrenze string (nuova)
Split(char) Divide in array in base a separatore string[]

✂️ Estrazione e Modifica

Operazioni di Estrazione
string email = "mario.rossi@example.com";

// Estrazione di sottostringhe
string username = email.Substring(0, email.IndexOf('@')); 
// "mario.rossi"

string dominio = email.Substring(email.IndexOf('@') + 1); 
// "example.com"

// Modifica del caso
string maiuscolo = email.ToUpper(); 
// "MARIO.ROSSI@EXAMPLE.COM"

string minuscolo = email.ToLower(); 
// "mario.rossi@example.com"

// Rimozione di spazi
string conSpazi = "   testo con spazi   ";
string senzaSpazi = conSpazi.Trim();           // "testo con spazi"
string senzaSpaziInizio = conSpazi.TrimStart(); // "testo con spazi   "
string senzaSpaziFinale = conSpazi.TrimEnd();   // "   testo con spazi"

📌 Metodi Utili per la Manipolazione

Estrazione

  • Substring(start, length)
  • Remove(start, count)
  • Insert(index, text)
Modifica

  • ToUpper() / ToLower()
  • Trim() / TrimStart() / TrimEnd()
  • PadLeft() / PadRight()

🎨 Formattazione Stringhe

Formattazione Avanzata
// Utilizzo di String.Format
string formato = String.Format("Nome: {0}, Età: {1}", "Mario", 30);
// "Nome: Mario, Età: 30"

// Formattazione di numeri
double prezzo = 1250.75;
string prezzoFormattato = prezzo.ToString("C");  // "€ 1.250,75"
string prezzoFormattato2 = prezzo.ToString("N2"); // "1.250,75"

// Allineamento e padding
string testo = "test";
string allineato = testo.PadLeft(10);              // "      test"
string allineatoConCarattere = testo.PadRight(10, '-'); // "test------"

Formato Descrizione Esempio
C Valuta € 1.250,75
N2 Numero con 2 decimali 1.250,75
F1 Fixed point con 1 decimale 1250,8
P Percentuale 12,51 %

📅 Lavorare con le Date (DateTime)

La classe DateTime rappresenta un momento specifico nel tempo, espresso come data e ora.
Offre numerosi metodi per manipolare e formattare date e orari.

Creazione e Accesso
// Data e ora corrente
DateTime now = DateTime.Now;
DateTime today = DateTime.Today; // Solo data, ore a 00:00:00

// Creazione di una data specifica
DateTime compleanno = new DateTime(1990, 5, 15);
DateTime compleannoOra = new DateTime(1990, 5, 15, 14, 30, 0);

// Accesso alle componenti
int anno = now.Year;
int mese = now.Month;
int giorno = now.Day;
int ora = now.Hour;
int minuto = now.Minute;
int secondo = now.Second;

// Giorno della settimana
DayOfWeek giornoSettimana = now.DayOfWeek; // Sunday, Monday, ...

⏰ Proprietà Importanti di DateTime

Data e Ora

  • DateTime.Now – Data e ora attuali
  • DateTime.Today – Solo data (00:00:00)
  • DateTime.UtcNow – Ora UTC
Componenti

  • Year, Month, Day
  • Hour, Minute, Second
  • DayOfWeek, DayOfYear

🔧 Operazioni con DateTime

Addizione, Sottrazione e Formattazione
// Addizione e sottrazione
DateTime domani = DateTime.Today.AddDays(1);
DateTime treSettimaneFa = DateTime.Today.AddDays(-21);
DateTime unAnnoDopoOggi = DateTime.Today.AddYears(1);
DateTime traUnOra = DateTime.Now.AddHours(1);

// Differenza tra date
TimeSpan differenza = domani - DateTime.Today; // 1 giorno
double giorni = differenza.TotalDays;  // 1.0
double ore = differenza.TotalHours;    // 24.0

// Formattazione date
DateTime data = new DateTime(2024, 5, 15, 14, 30, 25);

string formato1 = data.ToString("dd/MM/yyyy");           // "15/05/2024"
string formato2 = data.ToString("dd/MM/yyyy HH:mm:ss");  // "15/05/2024 14:30:25"
string formato3 = data.ToString("dddd, d MMMM yyyy");    // "mercoledì, 15 maggio 2024"
string formato4 = data.ToString("HH:mm");                 // "14:30"

Formato Descrizione Esempio
dd/MM/yyyy Data breve 15/05/2024
dddd, d MMMM yyyy Data estesa mercoledì, 15 maggio 2024
HH:mm:ss Ora formato 24h 14:30:25
hh:mm tt Ora formato 12h 02:30 PM
💡 TimeSpan vs DateTime

TimeSpan rappresenta un intervallo di tempo (durata),
mentre DateTime rappresenta un momento specifico nel tempo.
Usa TimeSpan per calcolare differenze tra date o per rappresentare durate.

⌨️ Input Utente dalla Console

L’interazione con l’utente è fondamentale per molte applicazioni. In un’applicazione console,
utilizziamo la classe Console per ottenere input dall’utente.

Lettura di Input Base
// Lettura di una stringa
Console.Write("Inserisci il tuo nome: ");
string nome = Console.ReadLine();

// Lettura di un numero (con conversione sicura)
Console.Write("Inserisci la tua età: ");
string inputEta = Console.ReadLine();
int eta;

if (int.TryParse(inputEta, out eta)) 
{
    Console.WriteLine($"Tra 10 anni avrai {eta + 10} anni");
} 
else 
{
    Console.WriteLine("Input non valido");
}

// Lettura di un singolo carattere (tasto)
Console.WriteLine("Premi un tasto per continuare...");
char tasto = Console.ReadKey().KeyChar;

⚠️ Metodi di Lettura Console

ReadLine()

  • Legge un’intera riga
  • Ritorna una stringa
  • Attende INVIO
ReadKey()

  • Legge un singolo tasto
  • Ritorna ConsoleKeyInfo
  • Non attende INVIO

✅ Validazione dell’Input

È importante validare l’input dell’utente per evitare errori durante l’esecuzione del programma.
Ecco alcuni esempi di validazione robusta.

Validazione di un Numero
bool inputValido = false;
int numero = 0;

while (!inputValido) 
{
    Console.Write("Inserisci un numero tra 1 e 100: ");
    string input = Console.ReadLine();
    
    if (int.TryParse(input, out numero)) 
    {
        if (numero >= 1 && numero <= 100) 
        {
            inputValido = true;
        } 
        else 
        {
            Console.WriteLine("❌ Il numero deve essere compreso tra 1 e 100");
        }
    } 
    else 
    {
        Console.WriteLine("❌ Input non valido. Inserisci un numero intero");
    }
}

Console.WriteLine($"✅ Hai inserito: {numero}");

Validazione di una Data
DateTime dataNascita;
bool dataValida = false;

while (!dataValida) 
{
    Console.Write("Inserisci la tua data di nascita (gg/mm/aaaa): ");
    string input = Console.ReadLine();
    
    if (DateTime.TryParseExact(input, "dd/MM/yyyy", null, 
        System.Globalization.DateTimeStyles.None, 
        out dataNascita)) 
    {
        if (dataNascita <= DateTime.Today) 
        {
            dataValida = true;
            
            // Calcolo età precisa
            int eta = DateTime.Today.Year - dataNascita.Year;
            
            // Controllo se il compleanno è già passato quest'anno
            if (dataNascita.Month > DateTime.Today.Month || 
                (dataNascita.Month == DateTime.Today.Month && 
                dataNascita.Day > DateTime.Today.Day)) 
            {
                eta--;
            }
            
            Console.WriteLine($"✅ La tua età è: {eta} anni");
        } 
        else 
        {
            Console.WriteLine("❌ La data non può essere nel futuro");
        }
    } 
    else 
    {
        Console.WriteLine("❌ Formato data non valido. Usa: gg/mm/aaaa");
    }
}

🛡️ Best Practice per la Validazione
  • Usa sempre TryParse invece di Parse per evitare eccezioni
  • Fornisci messaggi di errore chiari e specifici
  • Usa loop while per ripetere la richiesta fino a input valido
  • Valida sia il formato che il range dei valori

🚀 Esempio Pratico: Gestione Appuntamenti

Vediamo un esempio completo che integra stringhe, date e input utente per creare
un semplice sistema di gestione appuntamenti.

Program.cs - Sistema Appuntamenti
using System;
using System.Collections.Generic;

class Appuntamento 
{
    public string Titolo { get; set; }
    public DateTime DataOra { get; set; }
    public string Descrizione { get; set; }
    
    public override string ToString() 
    {
        return $"{DataOra.ToString("dd/MM/yyyy HH:mm")} - {Titolo}";
    }
}

class Program 
{
    static List appuntamenti = new List();
    
    static void Main() 
    {
        bool continua = true;
        
        while (continua) 
        {
            Console.WriteLine("\n╔════════════════════════════════╗");
            Console.WriteLine("║  GESTIONE APPUNTAMENTI         ║");
            Console.WriteLine("╚════════════════════════════════╝");
            Console.WriteLine("1. Aggiungi appuntamento");
            Console.WriteLine("2. Visualizza appuntamenti");
            Console.WriteLine("3. Cerca appuntamenti per data");
            Console.WriteLine("4. Esci");
            Console.Write("\nScegli un'opzione: ");
            
            string scelta = Console.ReadLine();
            
            switch (scelta) 
            {
                case "1":
                    AggiungiAppuntamento();
                    break;
                case "2":
                    VisualizzaAppuntamenti();
                    break;
                case "3":
                    CercaAppuntamenti();
                    break;
                case "4":
                    continua = false;
                    Console.WriteLine("Arrivederci!");
                    break;
                default:
                    Console.WriteLine("❌ Opzione non valida");
                    break;
            }
        }
    }
    
    static void AggiungiAppuntamento() 
    {
        Appuntamento app = new Appuntamento();
        
        Console.Write("\nTitolo: ");
        app.Titolo = Console.ReadLine();
        
        DateTime dataOra;
        bool dataValida = false;
        
        while (!dataValida) 
        {
            Console.Write("Data e ora (dd/MM/yyyy HH:mm): ");
            string input = Console.ReadLine();
            
            if (DateTime.TryParseExact(input, "dd/MM/yyyy HH:mm", null, 
                System.Globalization.DateTimeStyles.None, 
                out dataOra)) 
            {
                app.DataOra = dataOra;
                dataValida = true;
            } 
            else 
            {
                Console.WriteLine("❌ Formato non valido. Riprova.");
            }
        }
        
        Console.Write("Descrizione: ");
        app.Descrizione = Console.ReadLine();
        
        appuntamenti.Add(app);
        Console.WriteLine("✅ Appuntamento aggiunto con successo!");
    }
    
    static void VisualizzaAppuntamenti() 
    {
        if (appuntamenti.Count == 0) 
        {
            Console.WriteLine("\n📭 Nessun appuntamento presente");
            return;
        }
        
        Console.WriteLine("\n📋 Elenco degli appuntamenti:");
        appuntamenti.Sort((a, b) => a.DataOra.CompareTo(b.DataOra));
        
        for (int i = 0; i < appuntamenti.Count; i++) 
        {
            Console.WriteLine($"{i+1}. {appuntamenti[i]}");
            if (!string.IsNullOrEmpty(appuntamenti[i].Descrizione))
            {
                Console.WriteLine($"   → {appuntamenti[i].Descrizione}");
            }
        }
    }
    
    static void CercaAppuntamenti() 
    {
        if (appuntamenti.Count == 0) 
        {
            Console.WriteLine("\n📭 Nessun appuntamento presente");
            return;
        }
        
        DateTime dataRicerca;
        bool dataValida = false;
        
        while (!dataValida) 
        {
            Console.Write("\nInserisci la data da cercare (dd/MM/yyyy): ");
            string input = Console.ReadLine();
            
            if (DateTime.TryParseExact(input, "dd/MM/yyyy", null, 
                System.Globalization.DateTimeStyles.None, 
                out dataRicerca)) 
            {
                dataValida = true;
                
                Console.WriteLine($"\n📅 Appuntamenti del {dataRicerca.ToString("dd/MM/yyyy")}:");
                
                bool trovato = false;
                foreach (var app in appuntamenti) 
                {
                    if (app.DataOra.Date == dataRicerca.Date) 
                    {
                        Console.WriteLine($"• {app.DataOra.ToString("HH:mm")} - {app.Titolo}");
                        if (!string.IsNullOrEmpty(app.Descrizione))
                        {
                            Console.WriteLine($"  → {app.Descrizione}");
                        }
                        trovato = true;
                    }
                }
                
                if (!trovato) 
                {
                    Console.WriteLine("📭 Nessun appuntamento per questa data");
                }
            } 
            else 
            {
                Console.WriteLine("❌ Formato data non valido. Usa: dd/MM/yyyy");
            }
        }
    }
}

💡 Funzionalità del Programma
  • Aggiunta: Crea nuovi appuntamenti con validazione dell'input
  • Visualizzazione: Mostra tutti gli appuntamenti ordinati per data
  • Ricerca: Trova appuntamenti per una data specifica
  • Validazione: Controlla formato date e gestisce errori

💪 Esercizi Pratici

📝 Esercizio 1: Analizzatore di Email

Crea un programma che chiede all'utente di inserire un indirizzo email e poi:

  • Estrae e visualizza il nome utente (parte prima della @)
  • Estrae e visualizza il dominio (parte dopo la @)
  • Verifica se l'email contiene un punto nel dominio
  • Converte l'email in maiuscolo e minuscolo

📝 Esercizio 2: Calcolatore di Età

Crea un programma che:

  • Chiede all'utente la data di nascita (formato dd/MM/yyyy)
  • Calcola l'età esatta in anni, mesi e giorni
  • Mostra quanti giorni mancano al prossimo compleanno
  • Indica il giorno della settimana in cui è nato l'utente

📝 Esercizio 3: Formattatore di Testo

Crea un programma che chiede all'utente di inserire un testo e poi offre un menu per:

  • Convertire tutto in maiuscolo
  • Convertire tutto in minuscolo
  • Invertire maiuscole/minuscole
  • Contare parole e caratteri
  • Rimuovere spazi iniziali e finali

🎯 Riepilogo Lezione

Hai imparato:

  • Manipolazione stringhe
  • Gestione date con DateTime
  • Input utente e validazione
  • Formattazione avanzata
Concetti chiave:

  • Stringhe sono immutabili
  • TryParse per conversioni sicure
  • TimeSpan per intervalli
  • Sempre validare l'input

Lezione 11 del Corso C# Completo

Torna in alto