[C] Progetto di programmazione.

Messaggioda Yuyu_13 » 24/09/2021, 08:47

Buongiorno, sto svolgendo un esercizio dove si richiede l'uso delle stringhe per determinare la parola più "grande" e "piccola" tra quelle inserite e si arresti quando la parola inserita abbia una lunghezza di quattro caratteri.
Codice:
#include<stdio.h>
#include<string.h>

#define MAX_WORD 20
#define NUM_WORD 20
int read_line(char str[], int n);

int main(void){
  int i, j, len, count=0;
  char smallest_word[MAX_WORD], largest_word[MAX_WORD];
  char str[MAX_WORD];
 
   
 
     for(; ;){
        if(count==NUM_WORD){
          printf("--Spazio insufficiente--\n");
          goto done;
        }
       
        printf("Inserire parola: ");
        len=read_line(str, MAX_WORD);                   // Chiamata a funzione read_line
        if(len==4){
          goto done;
        }
        strcpy(smallest_word, strcpy(largest_word, &str[0]));         // Sia la stringa smallest_word che largest_word contengono la stringa str[0]
       
       
        if(count>=1){                           // Quando count è maggiore o uguale a uno posso effettuare il confronto
          for(i=0; i<=count-1; i++){
                if(strcmp(smallest_word, &str[i+1])<0){
                   strcpy(smallest_word, &str[i+1]);
                  }
             }
   
       
          for(j=0; j<=count-1; j++){
                if(strcmp(largest_word, &str[j+1])>0){
                   strcpy(largest_word, &str[j+1]);
                  }
             }
         }

        count++;
     }
     done:
          printf("small word: %s\n", smallest_word);
          printf("large word: %s\n", largest_word);
return 0;
}

                                                                                     // Funzione per lettura stringa
int read_line(char str[], int n){
   int ch, i=0;
   
   while((ch=getchar())!='\n'){
      if(i<n){
        str[i]=ch;
        i++;
      }
   }
   str[i]='\0';
   
return i;
}


Output


Immagine

Ho fatto vari tentativi ma nulla, dove sbaglio. Sono in crisi !
Yuyu_13
Junior Member
Junior Member
 
Messaggio: 90 di 373
Iscritto il: 14/06/2021, 14:44

Re: [C] Progetto di programmazione.

Messaggioda apatriarca » 24/09/2021, 18:13

Che cosa contiene la stringa str? E le stringhe smallest_word e largest_word? Prova a spiegare il tuo procedimento a parole e confrontarlo con quello che hai scritto. In particolare ti invito a porre particolare attenzione a &str[j + 1], non credo sia quello che ti aspetti.

In seguito possiamo parlare di come migliorare il tuo algoritmo, che fa molte più operazioni del necessario.
apatriarca
Moderatore
Moderatore
 
Messaggio: 5588 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] Progetto di programmazione.

Messaggioda Quinzio » 24/09/2021, 18:16

Tante cose da dire...
l'uso del "goto" nel 2021 fa davvero inorridire. Posso sapere dove stai imparando, in quale corso da quale libro ?
Cerca in tutti i modi di evitare i "goto", non e' difficile.

Ad ogni ciclo che esegui copi sempre l'ultima parola scritta nella smallest e nella largest.
Ovviamente cio' non ha senso.

La funzione strcmp non va bene per confrontare la lunghezza delle stringhe.
Cerca di capire bene cosa fa la strcmp e quindi cerca un'altra funzione che misura la lunghezza delle stringhe.
Quinzio
Cannot live without
Cannot live without
 
Messaggio: 4577 di 10552
Iscritto il: 24/08/2010, 06:50

Re: [C] Progetto di programmazione.

Messaggioda Yuyu_13 » 24/09/2021, 20:18

Vi ringrazio avermi risposto, premetto che da poco che sto programmando.

@apatriarca
Rispondo in ordine.
Contiene la parola k-esima al passo k,
Contiene la parola più corta,
Contiene la parola più grande.
I cicli dovrebbero servire per confrontare le parole.

@ quinzio
Sono uno studente di matematica, invece, il libro è Programmazione in C, Kim N. King.
Per quanto riguarda l'uso del goto, hai usato le stesse parole del mio prof., perché non va bene usarlo ?
Il strcmp non confronta le lunghezze delle parole? Sul mio libro ci sta scritto che serve per confrontare le lunghezze delle parole mediante gli operatori di $<, >....$?
Ultima modifica di Yuyu_13 il 24/09/2021, 20:45, modificato 1 volta in totale.
Yuyu_13
Junior Member
Junior Member
 
Messaggio: 91 di 373
Iscritto il: 14/06/2021, 14:44

Re: [C] Progetto di programmazione.

Messaggioda apatriarca » 24/09/2021, 20:38

Prova a mettere dei printf per verificare che la tua ipotesi sia corretta (non lo è). In particolare str è una stringa, ma nella tua descrizione dovrebbe essere un array di stringhe (e quindi un array bidimensionale).
apatriarca
Moderatore
Moderatore
 
Messaggio: 5590 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] Progetto di programmazione.

Messaggioda Yuyu_13 » 25/09/2021, 10:38

@apatriarca ho provato....hai ragione :-D
Dovrei cambiare strategia, potrei memorizzare le parole all'interno delle riga di un array bidimensionale e poi leggere tra queste e selezionare quella più grande e più piccola.
Può andare bene cosi, oppure diversamente ?

Saluti
Yuyu_13
Junior Member
Junior Member
 
Messaggio: 93 di 373
Iscritto il: 14/06/2021, 14:44

Re: [C] Progetto di programmazione.

Messaggioda apatriarca » 25/09/2021, 13:18

La funzione standard strcmp è implementata più o meno come segue:
Codice:
int strcmp(const char *s1, const char *s2) {
    while (*s1 == *s2 && *s1 != '\0') { ++s1; ++s2; }
    return (int)*(unsigned char *)s1 - (int)*(unsigned char *)s2;
}

Confronta due stringhe in ordine lessicografico, restituisce cioè la differenza del primo carattere diverso. Non considera quindi la lunghezza delle stringhe: "b" > "abcdef" per questa funzione per esempio. Non è tuttavia chiaro dal testo dell'esercizio che cosa si intenda come stringa più grande o più piccola e la funzione strcmp fornisce un tipo di ordine che si può usare.

Una soluzione al tuo problema può certamente essere quella di memorizzare tutte le stringhe inserite in un array bidimensionale, (quindi salvi ogni nuova stringa in una riga diversa). L'esercizio può tuttavia essere risolto senza memorizzare tutte le stringhe. Nota infatti che smallest_word e largest_word già contengono la parola più piccola e più grande fino all'iterazione precedente a quella che stai considerando. È quindi davvero necessario confrontare di nuovo queste parole con tutte quelle precedenti? (No...) Hai qualche idea di come si potrebbero aggiornare queste due variabili considerando solo il loro valore e quello della nuova parola inserita?

Il goto è mal visto perché tende a rendere il codice più difficile da seguire perché ci sono più modi di arrivare a una specifica riga del codice. Nel tuo caso sarebbe stato tuttavia sufficiente fare uso della parola chiave break che permette di uscire da un ciclo.
apatriarca
Moderatore
Moderatore
 
Messaggio: 5591 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] Progetto di programmazione.

Messaggioda Quinzio » 25/09/2021, 21:03

Yuyu_13 ha scritto:@ quinzio
Sono uno studente di matematica, invece, il libro è Programmazione in C, Kim N. King.
Per quanto riguarda l'uso del goto, hai usato le stesse parole del mio prof., perché non va bene usarlo ?
Il strcmp non confronta le lunghezze delle parole? Sul mio libro ci sta scritto che serve per confrontare le lunghezze delle parole mediante gli operatori di $<, >....$?


Il libro che hai non lo conosco ma non ho dubbi che sia di alto livello.
Veniamo al GOTO.
La questione e' una di quelle capaci di far litigare anche programmatori che per 8 ore stanno mansueti davanti al monitor senza dire una parola.
Non e' facile spiegare il perche' usare il GOTO e' male e su internet ci sono decine di discussioni al merito. Basta cercare su google "why goto is evil in C".
Ti do la mia spiegazione: evitare di usare il GOTO fa si che i programmi assumano una struttura gerarchica. Ossia ci sono funzioni che chiamano altre funzioni, che chiamano altre funzioni, ecc. E in ogni funzione ci possono essere cicli di esecuzione che contengono annidati altri cicli, e cosi' via.
Per ciclo di esecuzione intendo il "for loop", ovvero un gruppo di istruzioni eseguito diverse volte.
Il punto chiave e' che non si esce a un ciclo se il ciclo non e' terminato.
Ovvero non si salta da un ciclo all'altro.
Il GOTO rende possibile il salto da un punto all'altro in modo indiscriminato, anche se il ciclo non e' terminato si puo' saltare fuori anche da diversi cicli annidati. Questo rompe la struttura gerarchica di un programma e rende molto piu' difficile la comprensione di un programma da parte dello sviluppatore.
E' anche vero che ogni linguaggio di programmazione contiene dei GOTO camuffati e dissimulati sotto altro nome.
Anche la "if else" in realta' non e' altro che un GOTO, per non parlare poi dell'istruzione "break" e continue.
Pero' queste istruzioni non rompono la gerarchia del codice e non effettuano dei salti fuori dal blocco di istruzioni dove sono collocati.

Per te che sei agli inizi, la morale della storia e' questa: non usare MAI il GOTO, MAI e poi MAI. E' fuorilegge.

La strcmp.
La strcmp significa STRing CoMPare, ossia confronta due stringhe.
Ossia la funzione prende due stringhe, dove ogni stringa e' una sequenza di bytes.
La stringa finisce al primo 0x00 che si incontra. Attenzione, non il numero '0' (0x30 in ASCII), ma 0x00 scritto nel byte.
Se le due stringhe sono uguali (fino al primo 0x00 compreso) allora la strcmp restituisce 0, altrimenti restituisce un numero diverso da zero.
Ora, vedi subito che la strcmp non e' utile per avere informazioni sulla lunghezza di una stringa.
La funzione che ti serve e' la strlen, ovvero string length. :smt023
Quinzio
Cannot live without
Cannot live without
 
Messaggio: 4581 di 10552
Iscritto il: 24/08/2010, 06:50

Re: [C] Progetto di programmazione.

Messaggioda apatriarca » 26/09/2021, 11:17

@Quinzio: In realtà non ha bisogno di calcolare la lunghezza della stringa perché è il valore restituito dalla funzione read_line. Continuo comunque a trovare il testo ambiguo sul significato di stringa più grande e più piccola. L'ordine fornito dalla lunghezza della parola è comunque solo parziale e sarebbe a quel punto necessario decidere quale tra le parole della stessa lunghezza la funzione dovrebbe restituire (la prima? una qualsiasi? La più piccola lessicograficamente?).

Sia io che @Yuyu_13 abbiamo usato '\0' e non '0'. Il primo è effettivamente un carattere con valore 0, mentre il secondo è effettivamente il valore corrispondente al carattere zero. L'uso di '\0' rispetto a 0x00 o 0 è consigliato perché aiuta il lettore e alcuni tool a comprendere che stai cercando il terminatore della stringa. Per il resto è uguale.

Per quanto riguarda il GOTO vorrei solo aggiungere che rende a volte difficile comprendere il valore di alcune variabili locali al blocco all'interno del quale stai saltando. Non mi risulta ci siano regole specifiche a riguardo nello standard e quindi il comportamento potrebbe essere diverso tra un compilatore e un altro o anche tra diverse opzioni dello stesso compilatore. In effetti più il linguaggio è complicato, più l'uso di qualcosa come il goto diventa problematico. Ma a livello di assembly quasi tutto è implementato usando salti tipo il goto...
apatriarca
Moderatore
Moderatore
 
Messaggio: 5593 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] Progetto di programmazione.

Messaggioda Quinzio » 26/09/2021, 12:43

@apatriarca

Non ho tenuto conto del valore di ritorno della read_line. Ok

Non sono sicuro che un 'beginner' abbia chiaro al 100% la differenza tra 0x00, 0, "0", '0', "\0", '\0' e si potrebbe continuare.
Il mio era solo un primo tentativo di far capire che quando uno crede di aver capito in realta' non ha capito. :-)

L'assembly e' complicato da leggere, ma almeno il comportamento e' determinato.
Tant'e' vero che in assembly tutto e' un goto. Se poi a un certo punto qualcuno si e' preoccupato di aver salvato l'indirizzo di ritorno sullo stack, allora lo si va a leggere e si fa un altro goto (leggasi: un return).
Invece il sorgente C e' relativamente piu' facile da leggere, ma poi deve passare dentro a quella macina che il compilatore e allora addio alla certezza di essere sempre sicuri del risultato che si vuole.
Quinzio
Cannot live without
Cannot live without
 
Messaggio: 4585 di 10552
Iscritto il: 24/08/2010, 06:50

Prossimo

Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite