Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - PROBLEMA CODICE INSERTION SORT
Forum - C/C++ - PROBLEMA CODICE INSERTION SORT - Pagina 3

Pagine: [ 1 2 3 ] Precedente | Prossimo
Avatar
Carlo (Member)
Guru


Messaggi: 1344
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 17:05
Mercoledì, 29/04/2020
Testo quotato

Postato originariamente da AldoBaldo:

Se non hai mai sentito parlare di rosettacode.org, questa potrebbe essere una buona occasione per farci una visitina:

https://rosettacode.org/wiki/Sorting_algorithms/Insertion_sort

Anche questo può essere un bello spunto:

https://www.tutorialspoint.com/cplusplus-program-to-impleme ...



Non so se li hai postati per me, questi link, ti ringrazio.

Ho già postato un algoritmo in C, insertion sort ma Iprogrammer voleva correggere il suo e non voleva un codice nuovo.

Nel caso specifico, bubblesort, insertion sort, selection sort, li conosco e non ho nessun problema a scriverli in VB.NET o C#, anche se oggi non servono più con le potenti funzioni implementate in VB.NET e C#, compresi i sort che si possono fare con le Tuple.

Per me è stato un esercizio, il C somiglia con inganno al C#, e l'esempio è strutturato in blocchi divisi, così da pemettermi di saggiare proprio le differenze tra C e C#.
Ammetto che senza le info di nessuno e Ultimo non avrei potuto risolvere gli errori, visto che per correggerli tutti bisognava capire perfettamente la logica di funzionamento.

Prima di postare il codice corretto aspetto di sentire Iprogrammer, per sapere a che punto sta.

Ultima modifica effettuata da Carlo il 29/04/2020 alle 17:09


in programmazione tutto è permesso
PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 700
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 21:43
Mercoledì, 29/04/2020
Carlo: "Non so se li hai postati per me, questi link, ti ringrazio."

In effetti, no. Li ho segnalati per chi ha avviato questo filone di discussione. E' ben vero che voleva correggere il codice che ci ha riportato, ma vedere come altri hanno risolto il problema è senz'altro un buon "cacciavite", un attrezzo utile per riuscire ad arrivare alle proprie soluzioni personali.

Ho trovato più volte spunti molto interessanti in rosettacode.org, anche se non ho mai fatto un vero e proprio "copia-e-incolla" delle soluzioni fornite (il copia-e-incolla è il più delle volte inadeguato per risolvere questioni specifiche). Vedere come gli altri affrontano e risolvono i problemi è una fonte preziosa di apprendimento. Amo i luoghi web nei quali volontari benintenzionati espongono il frutto dei propri sforzi, anche quando magari non danno luogo a soluzioni "da professionisti".


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6402
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 7:50
Giovedì, 30/04/2020
Senza polemica, questo e' un forum tecnico (come altri o almeno prima lo era) e chi chiede aiuto (esclusa la pappa pronta diseducativa) vorrebbe una indicazione o una spiegazione su cosa non va nel codice.

Fare una lunga discussione OT sulle basi del linguaggio (Carlo se hai dubbi apri un thread e fai domande ... se fossi stato il creatore del thread non avrei gradito i tuoi interventi OT) o suggerire spazi web (?) che soddisfano la sete di conoscenza di codici scritti da altri senza spiegarsi il perche' siano scritti in quel modo, e' altrettanto fuorviante ed inutile per l'op. E il fatto di non essere professionisti non significa che non si debbano utilizzare e studiare soluzioni da professionisti. Le soluzioni fai da te possono funzionare nel breve e limitato periodo o contesto ma si deve imparare bene come si fanno le cose. Molti studenti saranno i professionisti di domani non i pensionati hobbysti e bisogna dare loro una mano al massimo delle possibilita'.

Se questo forum si basera' su risposte da hobbysti e filosofia del fai da te avra' vita breve.

Fossi stato in lui sarei andato su altro forum.


Ultima modifica effettuata da nessuno il 30/04/2020 alle 7:58


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 1344
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 9:39
Giovedì, 30/04/2020
Testo quotato

Postato originariamente da nessuno:

Fossi stato in lui sarei andato su altro forum.




La stessa domanda l'ha postata su altri 3 forum, e forse anche di più, ma non si è interessato alle risposte.

Per tutti i lettori del futuro, oltre alle spiegazioni già postate alle 13:02 di Mercoledì, 29/04/2020
il codice funzionante commentato:

Codice sorgente - presumibilmente C++

  1. /*
  2.  * codice per insertion sort
  3.  * descrizione: https://it.wikipedia.org/wiki/Insertion_sort
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8.  
  9. #define MAX_INPUT 10
  10.  
  11. void estrai_dati(int ac, char **av, int *vett, int *lung)
  12. {       // estrae dall'argomento
  13.         *lung = ac - 1;
  14.        
  15.         for (int i = 0; i < *lung; ++i)
  16.                 vett[i] = atoi(av[i + 1]);
  17. }
  18.  
  19. void fai_spazio(int posizione, int *vett, int lung)
  20. {       // scorre di una posizione
  21.         for (int j = lung; j > posizione; --j)
  22.                 vett[j] = vett[j - 1];
  23. }
  24.  
  25. void inserisci(int nuovo_dato, int num_dati_ord, int *vett)
  26. {      // riempimento dati_ordinati passato come puntatore
  27.         if (num_dati_ord == 0) { // il vettore è vuoto, facile
  28.                 vett[0] = nuovo_dato;
  29.                 return;
  30.         }
  31.         // se nuovodato è più piccolo va in testa
  32.         for (int i = 0; i < num_dati_ord; ++i) {
  33.                 if (nuovo_dato < vett[i]) {
  34.                         // sposta da vett[i] in poi di un posto sulla destra
  35.                         // prima di inserire il nuovo_dato
  36.                         fai_spazio(i, vett, num_dati_ord);
  37.                         vett[i] = nuovo_dato;
  38.                         return;
  39.                 }
  40.                 else {// altrimenti va nella stessa posizione che occupava in dati_non_ordinati
  41.                         vett[num_dati_ord] = nuovo_dato;
  42.                 }
  43.         }
  44. }
  45.  
  46. void ordina_dati(const int *dati_non_ordinati, int *dati_ordinati, int num_dati)
  47. {       // ciclo principale
  48.         for (int i = 0; i < num_dati; ++i)
  49.                 inserisci(dati_non_ordinati[i], i, dati_ordinati);
  50. }
  51.  
  52. void stampa_vettore(const int *vett, int lung)
  53. {       // visualizza
  54.         for (int i = 0; i < lung; ++i)
  55.                 printf("%d ", vett[i]);
  56.         printf("\n");
  57. }
  58.  
  59. int main(int argc, char **argv)
  60. {       // i valori vanno inseriti da riga comando dopo compilazione
  61.        
  62.         if (argc > MAX_INPUT + 1) {
  63.                 printf("Numero massimo di input %d\n", MAX_INPUT);
  64.                 return -1;
  65.         }
  66.         int dati_input[MAX_INPUT] = { 0 }; // matrice di 10 elementi
  67.         int dati_ordinati[MAX_INPUT] = { 0 }; // matrice di 10 elementi
  68.         int num_dati = 0; // passato come puntatore verrà calcolato in estrai_dati
  69.  
  70.         estrai_dati(argc, argv, dati_input, &num_dati);
  71.         ordina_dati(dati_input, dati_ordinati, num_dati);
  72.         stampa_vettore(dati_ordinati, num_dati);
  73.         return 0;
  74. }


Ultima modifica effettuata da Carlo il 30/04/2020 alle 9:44


in programmazione tutto è permesso
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6402
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 12:52
Giovedì, 30/04/2020
Carlo, i dati che già esistono si utilizzano, non si ricavano nuovamente. E vale per tutti i linguaggu

Codice sorgente - presumibilmente C++

  1. void estrai_dati(char **av, int *vett, int lung)
  2. {      
  3.         for (int i = 0; i < lung; ++i)
  4.                 vett[i] = atoi(av[i + 1]);
  5. }
  6.  
  7. int main(int argc, char **argv)
  8. {      
  9.         int dati_input[MAX_INPUT] = { 0 }; // vettore di 10 elementi
  10.         int dati_ordinati[MAX_INPUT] = { 0 }; // vettore di 10 elementi
  11.         int num_dati = argc-1;
  12.  
  13.         if (num_dati > MAX_INPUT) {
  14.                 printf("Numero massimo di input %d\n", MAX_INPUT);
  15.                 return -1;
  16.         }
  17.  
  18.         estrai_dati(argv, dati_input, num_dati);
  19.         ordina_dati(dati_input, dati_ordinati, num_dati);
  20.         stampa_vettore(dati_ordinati, num_dati);
  21.         return 0;
  22. }



Una considerazione ... l'algoritmo di ordinamento in genere si utilizza sullo STESSO vettore disordinato, non si utilizza un altro vettore. Per la didattica va bene ma in realtà se hai un milione di dati da ordinare non puoi usare un altro vettore parallelo di un altro milione di elementi ... (anche se in quel caso si userebbero altri algoritmi, ma è un'altra storia).

Quindi questo codice andrebbe riscritto usando solamente il primo vettore derivante da argv

Ultima modifica effettuata da nessuno il 30/04/2020 alle 12:56


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 1344
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 16:48
Giovedì, 30/04/2020
Testo quotato

Postato originariamente da nessuno:

Carlo, i dati che già esistono si utilizzano, non si ricavano nuovamente. E vale per tutti i linguaggi



Una considerazione ... l'algoritmo di ordinamento in genere si utilizza sullo STESSO vettore disordinato, non si utilizza un altro vettore. Per la didattica va bene ma in realtà se hai un milione di dati da ordinare non puoi usare un altro vettore parallelo di un altro milione di elementi ... (anche se in quel caso si userebbero altri algoritmi, ma è un'altra storia).

Quindi questo codice andrebbe riscritto usando solamente il primo vettore derivante da argv



Concordo, mi sono concentrato nel lasciare il codice uguale come richiesto, che è palesemente didattico e sparpagliato.
Per il mio archivio l'ho riscritto, uso lo stesso vettore con un algoritmo che proviene da un mio vecchio C#, che poi ho visto simile in molti siti, e dimensiono la matrice in accordo con il numero di interi immessi (se ho fatto qualcosa non C compatibile, graditi suggerimenti).
Le tue info sono essenziali, ma sempre circostanziate, e questa volta piacevolmente esaurienti. :yup:
Codice sorgente - presumibilmente C++

  1. /*
  2.  * codice per insertion sort
  3.  * descrizione: https://it.wikipedia.org/wiki/Insertion_sort
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8.  
  9. void stampa_vettore(const int *vett, int lung)
  10. {       // visualizza
  11.         for (int i = 0; i < lung; ++i)
  12.                 printf("%d ", vett[i]);
  13.         printf("\n");
  14. }
  15.  
  16. void insertion_sort(int *vett, int lung)
  17. {       // ordina modificando la matrice di ingresso
  18.         int provv, c1, c2 = 0;
  19.  
  20.         for (c1 = 1; c1 < lung; c1++)
  21.         {
  22.                 provv = vett[c1];
  23.                 c2 = c1 - 1;
  24.                 while ((vett[c2] > provv) && (c2 >= 0))
  25.                 {
  26.                         // scorrimento
  27.                         vett[c2 + 1] = vett[c2];
  28.                         c2--;
  29.                 }
  30.                 // progresso
  31.                 vett[c2 + 1] = provv;
  32.                 printf("Ciclo %d = ", c1);
  33.                 stampa_vettore(vett, lung);
  34.         }
  35. }
  36.  
  37. int main(int argc, char **argv)
  38. {       // i valori vanno inseriti da riga comando dopo compilazione release
  39.         // es \Release\InsertionSort4 12 23 62 7 4 5 2
  40.  
  41.         int num_dati = argc - 1; // numero di interi passati da riga comando
  42.         int* dati_inout = (int*)malloc(num_dati *  sizeof(int)); // dimensiono il vettore in out
  43.        
  44.         for (int i = 0; i < num_dati; ++i)
  45.                 dati_inout[i] = atoi(argv[i + 1]); // copio i dati dell'argomento nella matrice in out
  46.         printf("\n- Sono stati inseriti N. %d interi: \n\n", num_dati);
  47.        
  48.         // ordinamento
  49.         insertion_sort(dati_inout, num_dati);
  50.        
  51.  
  52.         printf("\n- Risultato = ");
  53.         stampa_vettore(dati_inout, num_dati);
  54.  
  55.         return 0;
  56. }




Ultima modifica effettuata da Carlo il 01/05/2020 alle 1:11


in programmazione tutto è permesso
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6402
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 19:25
Giovedì, 30/04/2020
Ok ... solo qualche precisazione.

E' buona norma restituire sempre un valore di stato in uscita ed è meglio che il punto di uscita sia unico (niente return in mezzo al codice). I valori in uscita devono essere chiaramente stabiliti e documentati.

Inoltre, considera che la mancanza di argomenti può essere trattato come un caso particolare.

Infine, controlla SEMPRE che l'allocazione di memoria vada a buon fine e che ad una allocazione corrisponda SEMPRE una free che libera la memoria allocata quando non serve più; anche se sembrano operazioni poco utili, sono buone abitudini che fanno risparmiare mal di testa in codici molto lunghi e complessi e differenziano il codice scritto da PROFESSIONISTI (chi vuole intendere mi intenda...).

Codice sorgente - presumibilmente C++

  1. #define ALL_OK          0
  2. #define OUT_OF_MEM -1
  3. #define NO_ARGS    -2
  4.  
  5. int main(int argc, char **argv)
  6. {       // i valori vanno inseriti da riga comando dopo compilazione release
  7.                 // es \Release\InsertionSort4 12 23 62 7 4 5 2
  8.  
  9.         int res = ALL_OK;
  10.         int num_dati = argc - 1; // numero di interi passati da riga comando
  11.  
  12.         if (num_dati)
  13.         {
  14.                 int* dati_inout = (int*)malloc(num_dati * sizeof(int)); // dimensiono il vettore in out
  15.  
  16.                 if (!dati_inout)
  17.                 {
  18.                         printf("Out of memory\n");
  19.                         res = OUT_OF_MEM;
  20.                 }
  21.                 else
  22.                 {
  23.                         for (int i = 0; i < num_dati; ++i)
  24.                                 dati_inout[i] = atoi(argv[i + 1]); // copio i dati dell'argomento nel VETTORE in out
  25.  
  26.                         printf("\n- Sono stati inseriti N. %d interi: \n\n", num_dati);
  27.  
  28.                         // ordinamento
  29.                         insertion_sort(dati_inout, num_dati);
  30.  
  31.                         printf("\n- Risultato = ");
  32.                         stampa_vettore(dati_inout, num_dati);
  33.  
  34.                         free(dati_inout);
  35.                 }
  36.         }
  37.         else
  38.         {
  39.                 printf("No args\n");
  40.                 res = NO_ARGS;
  41.         }
  42.  
  43.         return res;
  44. }



Ciao e buono studio.

P.S. La questione dell'operatore sizeof è semplice ... questo riporta la grandezza in byte del TIPO di dato che si pasa.
Se scrivi

char a[10];
printf("%d\n", sizeof(a));

vedrai che otterrai 10 perché il tipo di dato passato è char[10] e un carattere è in genere equivalente ad un byte.

Ma se passi il vettore ad una funzione, ad esempio (e questo vale sempre perché viene sempre passato per puntatore)

void test(char *v)
{
    printf("%d\n", sizeof(v));
}

otterrai SEMPRE 4 perché adesso il tipo di dato passato è un char * ovvero un puntatore che ha sempre grandezza 4 (nei sistemi a 32 bit) anche se il vettore è di 1000 elementi. Nei sistemi (e programmi) a 64 bit otterrai sempre 8 dato che il puntatore è a 8 byte. Quindi, in questo caso non potrai utilizzare questo operatore per determinare la grandezza del vettore. In realtà in C NON E' POSSIBILE sapere quanto sia grande il vettore passato per puntatore (ovvero non si può sapere quanti byte sono allocati e validi per un determinato puntatore e in questo forum c'è stata una lunga e controversa discussione sulla questione).

Questi sono errori comuni di chi inizia a programmare o chi rimane nello stato di "dilettante" come il fatto di non controllare la validità di una allocazione, di non liberare la memoria allocata o altro ...



Ultima modifica effettuata da nessuno il 30/04/2020 alle 19:52


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 1344
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 0:33
Venerdì, 01/05/2020
Grazie nessuno, tutto logico, la questione 4byte int, mi è rimasta chiara alla prima lettura dell'istruzione:

int* dati_inout = (int*)malloc(num_dati * sizeof(int));

di conseguenza 2byte char, 4byte int, 8byte long int ecc ecc.

Chiaro anche che i byte usati se passi un valore o un puntatore sarà diverso, anzi i puntatori servono proprio a non sprecare memoria, no?
Un po' come mandare una mail con un allegato video (valore), o una mail con allegato un link al video che sta in dropbox (riferimento) :rofl::yup:

Questione 32, 64bit, visto che per calcolare i byte utili uso sizeof(int), questa istruzione non mi restituirà 4 se il codice gira a 32bit e 8 se gira a 64bit?

Il controllo per la non immissione di valori l'avevo pensata, ma poi non scritta.

Il fallimento di allocazione, mi è chiaro, ma non ci avevo pensato per niente.

La norma del punto in uscita unico, penso che sia molto buona, la adotterò di sicuro.

Ultima modifica effettuata da Carlo il 01/05/2020 alle 0:55


in programmazione tutto è permesso
PM Quote
Pagine: [ 1 2 3 ] Precedente | Prossimo