PROBLEMA [C] Ripetizione dei caratteri dell'alfabeto in un testo

Pubblicità

Mr. Coder

Nuovo Utente
Messaggi
43
Reazioni
10
Punteggio
29
Ho un problema nella risoluzione di questo esercizio. Devo trovare il numero di ripetizioni delle varie lettere dell'alfabeto in delle stringhe.

Con il seguente codice riesco a contare solo le lettere minuscole, ma la consegna mi richiede di conteggiare maiuscole e minuscole insieme. Come potrei fare :boh:?

C:
/* Esercizio 8.19
   Scrivete un programma, basato su quello dell'Esercizio 8.18, che prenda in input
   diverse righe di testo e utilizzi la funzione strchr per determinare il totale
   delle occorrenze nelle righe di testo di ogni carattere incluso nell'alfabeto.
   Le lettere maiuscole e quelle minuscole dovranno essere contate insieme.
   Immagazzinate i totali di ogni lettera in un vettore e, una volta che saranno
   stati determinati, visualizzate i suddetti valori in un formato tabulare.
*/
#include <stdio.h>
#include <string.h>

#define MAX_LINES   5

int main()
{
    //  Le righe di testo su cui verrà svolta l'analisi
    const char *str[MAX_LINES] =
    {
        "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
        "Aenean commodo ligula eget dolor. Aenean massa.",
        "Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
        "Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.",
        "Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu."
    };

    char letter; //Contatore per la lettera selezionata
    int line; //Contatore per la riga di testo selezionata
    int counter[26] = {0}; //Vettore che contiene il numero delle occorrenze a -> z (26 lettere)

    /*
        Calcola il numero delle occorrenze delle varie lettere
        dell'alfabeto all'interno delle righe di testo
    */
    for(letter = 'a'; letter <= 'z'; letter++)
    {
        for(line = 0; line < MAX_LINES; line++)
        {
            char *search_ptr = strchr(str[line], letter);
            while(search_ptr != NULL)
            {
                counter[letter - 'a']++;
                search_ptr = strchr(search_ptr + 1, letter);
            }
        }
    }

    //  Stampa il risultato in formato tabulare
    for(letter = 'a'; letter <= 'z'; letter += 2)
        printf("%c: %d\t%c: %d\n", letter, counter[letter - 'a'], letter + 1, counter[letter - 'a' + 1]);

    return 0;
}
 
Ciao Mr. Coder,

è da troppo tempo che non scrivo in C, ma ho pensato che potrei darti spunto scrivendo un piccolo codice in Go al volo :)

Codice:
package main

import "fmt"

func main() {
    lines := []string{
        "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
        "Aenean commodo ligula eget dolor. Aenean massa.",
        "Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
        "Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.",
        "Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.",
    }

    
    upperDistance := 'A' - 'a'
    var counter [26]int
    for char := 'a'; char <= 'z'; char++ {
        for _, line := range lines {
            for _, lineChar := range line {
                if lineChar == char || lineChar == (char+upperDistance) {
                    counter[char-'a']++
                }
            }
        }
    }

    fmt.Println(counter)
}
 
Direi che usare strchr per un problema del genere sia una scelta PESSIMA, ma purtroppo e' quello che l'esercisio richiede. Non vedo alternativa che usare due cicli, uno usando la lettera minuscola e uno quella maiuscola (ugh...)
 
Ho un problema nella risoluzione di questo esercizio. Devo trovare il numero di ripetizioni delle varie lettere dell'alfabeto in delle stringhe.

Con il seguente codice riesco a contare solo le lettere minuscole, ma la consegna mi richiede di conteggiare maiuscole e minuscole insieme. Come potrei fare :boh:?

C:
/* Esercizio 8.19
   Scrivete un programma, basato su quello dell'Esercizio 8.18, che prenda in input
   diverse righe di testo e utilizzi la funzione strchr per determinare il totale
   delle occorrenze nelle righe di testo di ogni carattere incluso nell'alfabeto.
   Le lettere maiuscole e quelle minuscole dovranno essere contate insieme.
   Immagazzinate i totali di ogni lettera in un vettore e, una volta che saranno
   stati determinati, visualizzate i suddetti valori in un formato tabulare.
*/
#include <stdio.h>
#include <string.h>

#define MAX_LINES   5

int main()
{
    //  Le righe di testo su cui verrà svolta l'analisi
    const char *str[MAX_LINES] =
    {
        "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
        "Aenean commodo ligula eget dolor. Aenean massa.",
        "Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
        "Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.",
        "Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu."
    };

    char letter; //Contatore per la lettera selezionata
    int line; //Contatore per la riga di testo selezionata
    int counter[26] = {0}; //Vettore che contiene il numero delle occorrenze a -> z (26 lettere)

    /*
        Calcola il numero delle occorrenze delle varie lettere
        dell'alfabeto all'interno delle righe di testo
    */
    for(letter = 'a'; letter <= 'z'; letter++)
    {
        for(line = 0; line < MAX_LINES; line++)
        {
            char *search_ptr = strchr(str[line], letter);
            while(search_ptr != NULL)
            {
                counter[letter - 'a']++;
                search_ptr = strchr(search_ptr + 1, letter);
            }
        }
    }

    //  Stampa il risultato in formato tabulare
    for(letter = 'a'; letter <= 'z'; letter += 2)
        printf("%c: %d\t%c: %d\n", letter, counter[letter - 'a'], letter + 1, counter[letter - 'a' + 1]);

    return 0;
}
Perchè non usare i codici ASCII? puoi calcolare la maiuscola in poco tempo.
Oppure devi fare due cicli per forza.
 
Direi che usare strchr per un problema del genere sia una scelta PESSIMA...
Esattamente quello che ho pensato anch'io!
Ciao Mr. Coder,
è da troppo tempo che non scrivo in C, ma ho pensato che potrei darti spunto scrivendo un piccolo codice in Go al volo :)
Se non avessi dovuto utilizzare la funzione strchr come da consegna, avrei optato anche io per una cosa del genere.

Credo che utilizzerò un doppio ciclo. Alla fine è solo un esercizio (del cavolo :lol:)
 
Potresti sempre adottare una soluzione più "smart" e sviluppare un esempio più concreto per strchr da portare al professore lol
 
Potresti sempre adottare una soluzione più "smart" e sviluppare un esempio più concreto per strchr da portare al professore lol
No.
Gli esercizi che si danno a scuola sono fatti per capire se gli studenti hanno imparato i concetti e la tecnica, come in questo caso. Per esempio "come costruire una sedia senza usare un martello". Ovvio che nella vita reale userei un martello :) ma quello non è lo scopo dell’esercizio.
 
Beh è chiaro, era una risposta provocatoria :) - diciamo che per quanto riguarda la mia provocazione anche il tuo esempio calza: posso realizzarti un vaso senza martello e dimostrarti ugualmente che sono in grado di usare le mani senza il martello :)

Spesso e volentieri ho creduto fermamente che i tipici esempi vogliano in realtà distogliere l'attenzione dallo strumento per farti pensare in modo laterale. Ma allora chiamiamolo esercizio di logica, non di programmazione :) possibile che non esista un esempio di utilizzo di strchr calzante?
 
... possibile che non esista un esempio di utilizzo di strchr calzante?
Quando si fa un "esercizio" non sempre l'esempio "calza". E' normale in ogni campo, non solo l'informatica. Succede specialmente quando un esercizio fa parte di una lunga catena, in cui ogni nuovo esercizio "aggiunge" qualcosa al precedente.
Capisco comunque che volevi "provocare" :) ma meglio di no, non si puo' mai sapere come la prende l'insegnante. Io per esempio ti avrei dato "zero" perche' non hai risolto come ho chiesto io di farlo, e come ben sappiamo non esiste UN solo metodo per risolvere un problema. Non esiste neppure IL metodo migliore, ogni programmatore ha le sue preferenze.
PS e' lo stesso nei colloqui di lavoro. MAI rispondere in maniera diversa. Fare sempre quello che chiedono di fare, se si ha tempo poi si puo' discutere e infatti e' quello che succede durante il colloquio, dove il test e' solo un modo formale per inziare la discussione.
 
Pensandoci un pò su, mi è venuto in mente un altro modo :D

Se invece del doppio ciclo, usassi la funzione strchr due volte all'interno dello stesso ciclo? Si risparmierebbe qualcosa in termini di costi in accesso in memoria?
C:
/*
    Calcola il numero delle occorrenze delle varie lettere
    dell'alfabeto all'interno delle righe di testo
*/
for(letter = 'a'; letter <= 'z'; letter++)
{
    for(line = 0; line < MAX_LINES; line++)
    {
        char *search_ptr = strchr(str[line], letter);
        while(search_ptr != NULL)
        {
            counter[letter - 'a']++;
            search_ptr = strchr(search_ptr + 1, letter);
        }

        search_ptr = strchr(str[line], toupper(letter));
        while(search_ptr != NULL)
        {
            counter[toupper(letter) - 'A']++;
            search_ptr = strchr(search_ptr + 1, toupper(letter));
        }
    }
}
 
Così ad occhio il counter delle lettere maiuscole dovrebbe sempre far riferimento ad 'a', non ad 'A' (se conti le maiuscole e le minuscole insieme). Inoltre ottimizzerei la la funzione chiamando toupper una sola volta :D
 
Il codice funziona perfettamente e conta maiuscole/minuscole assieme (ho testato).
Se trasformo le lettere del ciclo in maiuscole e le sottraggo ad 'A', incremento sempre il contatore. Infatti alla prima iterazione 'A' - 'A' = 0, e quindi viene incrementato counter[0] che è il contatore per le lettere a.

Per "richiamare la funzione toupper() una volta sola" intedi inserire il suo valore all'interno di una variabile, e poi usare quest'ultima per le operazioni?
C:
/*
    Calcola il numero delle occorrenze delle varie lettere
    dell'alfabeto all'interno delle righe di testo
*/
for(letter = 'a'; letter <= 'z'; letter++)
{
    for(line = 0; line < MAX_LINES; line++)
    {
        char *search_ptr = strchr(str[line], letter);
        while(search_ptr != NULL)
        {
            counter[letter - 'a']++;
            search_ptr = strchr(search_ptr + 1, letter);
        }

        char upper_letter = toupper(letter);
        search_ptr = strchr(str[line], upper_letter);
        while(search_ptr != NULL)
        {
            counter[upper_letter - 'A']++;
            search_ptr = strchr(search_ptr + 1, upper_letter);
        }
    }
}
 
Ultima modifica:
Esatto. Non so come sia l'implementazione, ma mi sembra brutale richiamare due volte la stessa funzione per lo stesso risultato :D

Sul punto hai ragione, m'era sfuggito che facevi touppoer(letter) - 'A' e non letter - 'A'... ma a questo punto, tanto per ottimizzare il tutto... non vedi che stai duplicando almeno 5 righe? :D Metterei i cicli in una funzione dedicata... ma questa è deformazione professionale :D
 
Beh, è pur sempre un doppio ciclo, uno per le minuscole e uno per le maiuscole, è quello che intendevo io. Puoi migliorare creando una funzione ma non è fondamentale.
 
Pubblicità
Pubblicità
Indietro
Top