esercizio su stringhe e strutture

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Non serve che riporti la firma della funzione all'interno del codice int strcmp(frasi[i].parola, frasi[i-s].parola);, è sbagliato per altro.
Piccolo consiglio: indenta anche meglio il codice, ti accorgerai di alcune cose da sistemare. 😉
 
  • Mi piace
Reazioni: bigendian

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Potresti spiegarmi come risolvere la questione dello strcmp?
Io ti consigliavo di utilizzare strncmp, comunque:

C:
   if(i=1 && strcmp(frasi[i].parola, frasi[i-s].parola) !=0){;}
       else{frasi[i].conta+1;}
     }
   }

Il modo in cui utilizzi strcmp è corretto: la funzione restituisce 0 se le stringhe sono uguali, un valore minore di 0 se il primo carattere diverso ha un valore minore nella prima stringa, e maggiore di 0 se il primo carattere diverso ha un valore maggiore nella prima stringa.
Insomma, se vuoi vedere se sono uguali devi usare strcmp(stringa1, stringa2) == 0.

Sempre nella parte di codice che ho riportato, c'è un errore: i=1 è un assegnamento, e visto che assegni il valore 1, viene valutato sempre a true.

Non ti serve lasciare quel "punto e virgola" nelle graffe se non ci sono istruzioni, inoltre non è proprio bello da vedere; avrebbe più senso invertire la condizione:

C:
    if(istrcmp(frasi[i].parola, frasi[i-s].parola) == 0){
        frasi[i].conta++;
    }

Anche in questa parte c'era un errore: frasi[i].conta+1;, questo incrementa il valore e scarta il risultato. In pratica l'incremento non viene mai memorizzato. Puoi usare l'operatore di incremento come ho fatto li sopra, oppure anche fare frasi[i].conta+=1 (preferibile il primo, ovvero ++, quando si tratta di 1 sola unità).

Ho dato una sistemata al codice, indentandolo meglio:
C:
#include <stdio.h>
#include <string.h>

int main(){
    int i, s;

    struct insieme {
     char parola[26+1];
     int conta;
    };
    
    struct insieme frasi[10];
    
    printf("Inserisci le parole\n");
    
    for(i=0;i<10;i++){
      for(s=0;s<10;s++){
      
            scanf("%s", &frasi[i].parola);
      
            if(strcmp(frasi[i].parola, frasi[i-s].parola) !=0){
                frasi[i].conta++;
            }
        }
    }
    
    for(i=0;i<100;i++){
        printf("la parola: %s è ripetuta : %d", frasi[i].parola, frasi[i].conta);
    }   

    return 0;   
}

Per evitare di mettere quel controllo sull'indice del ciclo (ovvero se è 0, non sottrarre), puoi leggere la prima stringa fuori dal ciclo, e iniziare il ciclo dal valore 1.

Ci sono poi altre cose che non vanno bene: ad esempio, stai allocando una struttura statica di 10 frasi, ma stai facendo 2 cicli innestati ciascuno da 0 a 10; non ha molto senso questa cosa se ci pensi bene: supponiamo di avere i=0 e s=5, qui avresti come indice -5, che non esiste (o meglio, stai andando a leggere altra memoria nello stack, ed è un errore grave).

Non ultimo, non ci sarà mai alcun match fatto in questo modo. Per ogni inserimento dovresti verificare l'intero array e verificare quindi le singole parole (scorrendo da indice 0 a indice N, dove N sono i valori inseriti sino a questo momento).

Poi: l'ultimo ciclo è su 100 elementi, ma ci sono 10 frasi allocate. Anche questo è un problema, perchè vai a leggere memoria non allocata (e nel migliore degli scenari, vedrai dati sbagliati, nel peggiore crasha il programma... e puoi sperare nel crash, almeno vedresti l'errore 😁 ).


Per come l'hai impostato non ti serve nemmeno fare una matrice: vuoi 100 frasi? Fai direttamente frasi[100]. Accedi già linearmente al vettore usando solo una variabile, quindi puoi rimuovere il ciclo interno (quello che usa s come contatore).
Una cosa tipo:

Codice:
// scanf elemento frasi[0].parola
for(int i=1; i < 100; i++) {
    // scanf....
    
    // FOR ogni singolo elemento del vettore...
        // IF strcmp(frasi[i-1].parola, frasi[i].parola) == 0
   // ENDFOR
}

Questo credo sia il risultato che vuoi ottenere. In questo caso però non avresti più delle frasi di lunghezza N, ma delle frasi di 1 parola di lunghezza max 26.
Però se vuoi farlo per prenderci la mano e capire meglio i concetti, mi sembra una buona idea.

Ti consiglierei però di ripassare anche i fondamenti: operatori di incremento/decremento etc, così come il modo in cui vengono valutate le condizioni etc etc (errori come i=1 invece di i==1 per distrazione capitano a tutti; infatti si utilizza solitamente l'assegnamento invertendo gli operandi: 1=i, in modo tale da avere un errore in compilazione visto che non puoi assegnare una variabile a un numero).

Se hai domande o dubbi, continua puoi a scriverci qui, il primo che può ti risponderà.
 
  • Mi piace
Reazioni: Ibernato e Mursey

Ibernato

Utente Èlite
4,330
2,047
OS
Windows 10 Pro / Ubuntu 22.04
All'ottima spiegazione di @DispatchCode , aggiungo che per evitare duplicazioni di frasi, piuttosto che fare la scanf sull'array, farei la scanf su una variabile stringa secondaria e nel secondo for scorri da 0 a N (n frasi inserite fino a quel momento) se la parola non è presente, aggiungila all'array, se è già presente, incrementa solo il contatore.
Ho avuto modo di scrivere il programmino e funziona perfettamente, ma lascio a te provare a scriverlo
Se usi questa variabile stringa di appoggio, ti occorre un flag per capire se la parola è stata trovata in modo da non accodarla all'array e un flag per contare quante parole sono state aggiunte
 

tsle

Nuovo Utente
13
1
Grazie mille Dispatchcode per la puntualissima analisi, si non padroneggio questi argomenti ma ci lavorerò. Apprezzo anche il fatto che non mi inviate direttamente il codice, per quanto sarebbe più facile ma non mi permettereste di imparare bene. Comunque ora proverò a risolvere un po' tutto. Grazie anche a Ibernato anche se non capisco come potrei implementare il tuo consiglio.

Post unito automaticamente:

Ho sistemato credo i cicli di for e il contatore, mi rimangono sempre dei problemi di compilazione con strcmp.
[Error] expression list treated as compound expression in initializer [-fpermissive] linea di strcmp
[Error] invalid conversion from 'char*' to 'int' [-fpermissive] sempre linea di strcmp
[Error] 'strcmp' cannot be used as a function


C:
#include <stdio.h>
#include <string.h>


int main(){
int i, s;
    

    
    struct insieme {
     char parola[26+1];
     int conta;
    };
    
    struct insieme frasi[10];
    
    printf("Inserisci le parole\n");

    for(i=0; i<10; i++){
      for(s=1; s<=i; s++){
      
         scanf("%s", &frasi[i].parola);
    
              int strcmp(frasi[i].parola, frasi[i-s].parola);
  
                   if( i==1 && strcmp(frasi[i].parola, frasi[i-s].parola) !=0)
                     else{frasi[i].conta++;}
      
     }
   }
    
    for(i=0; i<10; i++){
    printf("la parola: %s è ripetuta : %d", frasi[i].parola, frasi[i].conta);
     }   
return 0;   
    
}
 
Ultima modifica:

bigendian

Utente Attivo
749
432
OS
Linux
- quell "int strcmp(frasi.parola, frasi[i-s].parola);" e' da rimuovere
- frasi o parole ? Se cerchi una parola in una frase, dovresti usare piuttosto strstr
- vedo un if che non fa nulla, se non nell'else, non ha senso ma non e' un problema ora
 

tsle

Nuovo Utente
13
1
okok togliendo int strcmp (....) il programma viene compilato ed è funziona abbastanza bene ma:+
l' imput da inserire e davvero troppo
a volte il conteggio è sbagliato.

Si comunque cerco parole, la parola frasi è fuorviante.

Codice:
int main(){
int i, s;
    

    
    struct insieme {
     char parola[26+1];
     int conta;
    };
    
    struct insieme frasi[5];
    
    printf("Inserisci le parole\n");

    for(i=0;i<10;i++){
      for(s=1;s<=i;s++){
      
         scanf("%s", &frasi[i].parola);
    
              
              
                if(i==1 && strcmp(frasi[i].parola, frasi[i-s].parola) ==0){
                    frasi[i].conta++;
                }
                     else;
      
     }
   }
    
    for(i=0;i<10;i++){
    printf("la parola: %s ripetuta : %d\n", frasi[i].parola, frasi[i].conta);
     }   
return 0;   
    
}
 

bigendian

Utente Attivo
749
432
OS
Linux
Se leggo bene il testo dell'esercizio, il codice dovrebbe essere ben diverso.

1) leggi una riga, che dal testo puo avere piu parole separate da spazi.
2) ricava ogni parola (forse per te la cosa piu complessa).
3) cerca se c'e' gia nella tavola delle parole (semplice singolo ciclo for, strncmp) , se gia esiste, incrementa il suo contatore, se no aggiungila alla tavola.
4) stampa ogni parola e il conteggio dalla tavola

quindi in pseudo - code

Codice:
void aggiungi_o_incrementa_contatore(char *parola)
{
    la tua funzioncina di ricerca e aggiornamento
}

int main() {

    for (;;) {

        leggi linea
        invio linea vuota ? esci (break)

        do {

            parola = ricava_parola(linea);

            aggiungi_o_incrementa_contatore(parola)

        } while (parola);
    }
    Stampa banalmente parole e contatore
}
 
Ultima modifica:

Ibernato

Utente Èlite
4,330
2,047
OS
Windows 10 Pro / Ubuntu 22.04
1) leggi una riga, che dal testo puo avere piu parole separate da spazi.
anche io l'ho interpretato così ma forse meglio iniziare inserendo parole a mano (magari non 100, ma 10)

@tsle per implementare il mio consiglio, innanzitutto devi dichiarare una variabile di appoggio char[100] parola
Poi dopo il primo for, la scanf falla sulla parola
Codice:
scanf("%s", &parola);
Poi ti occorrono altre due variabili
Codice:
int found;
int countInsert;

Found ti serve per capire se la parola inserita è presente già nell'array di parole
Countinsert ti serve per tenere traccia di quante parole inserire

Quindi il primo for diventa così, poi lascio a te continuare.
Codice:
printf("Inserisci 5 parole battendo invio al termine di ciascuna\n");
scanf("%s", parola);
countInsert = 1;
strcpy(frasi[0].parola, parola);
for(i=1;i<5;i++){
        found = 0;
        scanf("%s", parola); 
        //continua tu

Il mio esempio l'ho fatto su 5 parole da inserire
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!