Vai al contenuto

Stringhe, date e input utente

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

πŸ–₯️ In pratica con Windows Forms: TextBox e Label per l'input.

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<Appuntamento> appuntamenti = new List<Appuntamento>();

    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
Mostra la soluzione

Soluzione Esercizio 1

using System;

class Program
{
    static void Main()
    {
        Console.Write("Inserisci un indirizzo email: ");
        string email = Console.ReadLine();

        // Verifica che contenga @
        if (!email.Contains("@"))
        {
            Console.WriteLine("❌ Email non valida: manca @");
            return;
        }

        // Estrazione username e dominio
        int posChiocciola = email.IndexOf('@');
        string username = email.Substring(0, posChiocciola);
        string dominio = email.Substring(posChiocciola + 1);

        // Output informazioni
        Console.WriteLine("\n=== ANALISI EMAIL ===");
        Console.WriteLine($"Email completa: {email}");
        Console.WriteLine($"Username: {username}");
        Console.WriteLine($"Dominio: {dominio}");

        // Verifica punto nel dominio
        if (dominio.Contains("."))
        {
            Console.WriteLine("βœ… Il dominio contiene un punto");
        }
        else
        {
            Console.WriteLine("⚠️ Il dominio non contiene un punto");
        }

        // Conversioni
        Console.WriteLine($"\nMaiuscolo: {email.ToUpper()}");
        Console.WriteLine($"Minuscolo: {email.ToLower()}");
    }
}

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
Mostra la soluzione

Soluzione Esercizio 2

using System;

class Program
{
    static void Main()
    {
        DateTime dataNascita;
        bool dataValida = false;

        // Input con validazione
        while (!dataValida)
        {
            Console.Write("Inserisci la data di nascita (dd/MM/yyyy): ");
            string input = Console.ReadLine();

            if (DateTime.TryParseExact(input, "dd/MM/yyyy", null,
                System.Globalization.DateTimeStyles.None,
                out dataNascita))
            {
                if (dataNascita <= DateTime.Today)
                {
                    dataValida = true;
                }
                else
                {
                    Console.WriteLine("❌ La data non può essere nel futuro");
                }
            }
            else
            {
                Console.WriteLine("❌ Formato non valido. Usa: dd/MM/yyyy");
            }
        }

        // Calcolo etΓ 
        DateTime oggi = DateTime.Today;
        int anni = oggi.Year - dataNascita.Year;

        // Aggiusta se il compleanno non Γ¨ ancora passato quest'anno
        DateTime compleannoQuestAnno = new DateTime(oggi.Year,
                                                     dataNascita.Month,
                                                     dataNascita.Day);

        if (compleannoQuestAnno > oggi)
        {
            anni--;
        }

        // Calcolo giorni al prossimo compleanno
        DateTime prossimoCompleanno = compleannoQuestAnno > oggi
            ? compleannoQuestAnno
            : compleannoQuestAnno.AddYears(1);

        int giorniAlCompleanno = (prossimoCompleanno - oggi).Days;

        // Output
        Console.WriteLine("\n=== INFORMAZIONI ===");
        Console.WriteLine($"Data di nascita: {dataNascita.ToString("dddd, dd MMMM yyyy")}");
        Console.WriteLine($"Sei nato/a di: {dataNascita.ToString("dddd")}");
        Console.WriteLine($"EtΓ : {anni} anni");
        Console.WriteLine($"Giorni al prossimo compleanno: {giorniAlCompleanno}");

        if (giorniAlCompleanno == 0)
        {
            Console.WriteLine("πŸŽ‰ Buon compleanno!");
        }
    }
}

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
Mostra la soluzione

Soluzione Esercizio 3

using System;

class Program
{
    static void Main()
    {
        Console.Write("Inserisci un testo: ");
        string testo = Console.ReadLine();

        bool continua = true;

        while (continua)
        {
            Console.WriteLine("\n╔═══════════════════════════╗");
            Console.WriteLine("β•‘  FORMATTATORE DI TESTO    β•‘");
            Console.WriteLine("β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•");
            Console.WriteLine("1. MAIUSCOLO");
            Console.WriteLine("2. minuscolo");
            Console.WriteLine("3. Inverti Maiuscole/minuscole");
            Console.WriteLine("4. Conta parole e caratteri");
            Console.WriteLine("5. Rimuovi spazi");
            Console.WriteLine("6. Inserisci nuovo testo");
            Console.WriteLine("7. Esci");
            Console.Write("\nScegli: ");

            string scelta = Console.ReadLine();

            switch (scelta)
            {
                case "1":
                    Console.WriteLine($"\n→ {testo.ToUpper()}");
                    break;

                case "2":
                    Console.WriteLine($"\n→ {testo.ToLower()}");
                    break;

                case "3":
                    string invertito = "";
                    foreach (char c in testo)
                    {
                        if (char.IsUpper(c))
                            invertito += char.ToLower(c);
                        else if (char.IsLower(c))
                            invertito += char.ToUpper(c);
                        else
                            invertito += c;
                    }
                    Console.WriteLine($"\n→ {invertito}");
                    break;

                case "4":
                    int caratteri = testo.Length;
                    string[] parole = testo.Split(new char[] {' ', '\t'},
                        StringSplitOptions.RemoveEmptyEntries);
                    Console.WriteLine($"\n→ Caratteri: {caratteri}");
                    Console.WriteLine($"β†’ Parole: {parole.Length}");
                    break;

                case "5":
                    Console.WriteLine($"\n→ '{testo.Trim()}'");
                    break;

                case "6":
                    Console.Write("\nInserisci nuovo testo: ");
                    testo = Console.ReadLine();
                    break;

                case "7":
                    continua = false;
                    break;

                default:
                    Console.WriteLine("❌ Opzione non valida");
                    break;
            }
        }
    }
}

🎯 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