Visualizzazione dei risultati da 1 a 9 su 9
  1. #1
    Utente di HTML.it
    Registrato dal
    Dec 2012
    Messaggi
    16

    [C] Rilevazione elementi uguali in un array

    Ciao a tutti! Sto cercando di scrivere un programmino che riceva in input un array, lo stampi a video, riconosca se ci sono elementi uguali nell'array e comunichi se questo avviene o meno.

    codice:
    #include<stdio.h>
    #define N 2
    
    int main () {
         int ar[N*N];
         int i, j;
         int flag;
    
         for(i=0; i<=(N*N)-1; i++){
         printf("\nInserire un numero intero (%d interi restanti): ", (N*N)-i);
         scanf("%d", &ar[i]);
         }
    
         printf("\n");
         for(i=0; i<=(N*N)-1; i++)
         printf("%d ", ar[i]);
         printf("\n");
    
         for(i=0; i<=(N*N)-1; i++) {
              for(j=i++; j<=(N*N)-1; j++)
              if(ar[i]==ar[j])
                   flag=1;
              if(ar[i]!=ar[j])
                   flag=0;
         }
    
         if(flag==1)
              printf("\nCi sono elementi ripetuti!\n");
         if(flag==0)
              printf("\nNon ci sono elementi ripetuti!\n");
    
         return 0;
    }
    Sorge questo problema (tenendo presente che in questo caso N=2):
    -se inserisco interi tutti diversi, il programma mi riconosce giustamente che non ci sono elementi ripetuti;
    -se inserisco un massimo di 2 interi uguali sul totale di 4, mi riconosce giustamente che ci sono elementi ripetuti;
    -se inserisco 3 o più interi uguali, mi comunica che non ci sono elementi ripetuti!!

    Ho provato anche a sostituire questo pezzo di codice
    codice:
    for(i=0; i<=(N*N)-1; i++) {
         for(j=i++; j<=(N*N)-1; j++)
         if(ar[i]==ar[j])
              flag=1;
         if(ar[i]!=ar[j])
              flag=0;
    }
    con questo
    codice:
    for(i=0; i<=(N*N)-1; i++) {
         for(j=0; j<=(N*N)-1; j++)
         if(ar[i]==ar[j] && i!=j)
              flag=1;
         if(ar[i]!=ar[j] && i!=j)
              flag=0;
    }
    ma non è cambiato nulla, l'errore rimane lo stesso.

    Mi sono incartata qui e non riesco a risolvere il problema!! e sì che credevo fosse un programmino semplice....

    Vi ringrazio in caso abbiate tempo/voglia di darmi una mano!

  2. #2
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,465
    Prova a dare un'occhiata a questo

    codice:
    flag=0;
    for(i=0; i<=(N*N)-1; i++) 
    {
       for(j=i+1; j<=(N*N)-1; j++)
          if(ar[i]==ar[j])
             flag=1;
    }
    e anche

    codice:
    if(flag==1)
       printf("\nCi sono elementi ripetuti!\n");
    else
       printf("\nNon ci sono elementi ripetuti!\n");
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  3. #3
    Sicuramente ci sono dei problemi qui:
    codice:
         for(i=0; i<=(N*N)-1; i++) {
              for(j=i++; j<=(N*N)-1; j++)
              if(ar[i ]==ar[j])
                   flag=1;
              if(ar[i ]!=ar[j])
                   flag=0;
         }
    - scrivi j=i++ quando probabilmente intendi j=i+1; le due cose sono molto diverse: j=i++ fa sì che a j venga assegnato i e poi i venga incrementato di 1 (quindi fai due errori: j parte "indietro di uno" e i viene incrementato quando non dovrebbe); al contrario, j=i+1 "fa partire" j l'elemento dopo quello corrente.
    - il for ripete solo l'istruzione che lo segue, per cui il tuo blocco di codice di fatto è:
    codice:
         for(i=0; i<=(N*N)-1; i++) {
              for(j=i++; j<=(N*N)-1; j++) {
                   if(ar[i ]==ar[j])
                        flag=1;
              }
              if(ar[i ]!=ar[j])
                   flag=0;
         }
    che ovviamente non è quello che intendevi; per ovviare al problema, usa le graffe correttamente (qui correggo anche il j=i++):
    codice:
         for(i=0; i<=(N*N)-1; i++) {
              for(j=i+1; j<=(N*N)-1; j++) {
                   if(ar[i ]==ar[j])
                        flag=1;
                   if(ar[i ]!=ar[j])
                        flag=0;
              }
         }
    o, anche più chiaro:
    codice:
         for(i=0; i<=(N*N)-1; i++) {
              for(j=i+1; j<=(N*N)-1; j++) {
                   if(ar[i ]==ar[j])
                        flag=1;
                   else
                        flag=0;
              }
         }
    Nota però che il programma così è ancora sbagliato: ad ogni iterazione flag viene sovrascritto, per cui se l'ultima coppia esaminata è uguale all'uscita del ciclo flag rimarrà impostato a zero. Per ovviare a questo problema, ti basta impostare flag a 1 quando individui duplicati e non impostarlo mai a zero in seguito. Dato poi che, una volta che hai individuato una coppia di duplicati, il tuo lavoro è finito, puoi anche uscire con un break subito dopo aver impostato flag a 1:
    codice:
         for(i=0; i<=(N*N)-1; i++) {
              for(j=i+1; j<=(N*N)-1; j++)
              {
                   if(ar[i ]==ar[j])
                   {
                        flag=1;
                        break;
                   }
              }
         }
    Amaro C++, il gusto pieno dell'undefined behavior.

  4. #4
    Utente di HTML.it
    Registrato dal
    Dec 2012
    Messaggi
    16
    aaaah, funge!!! Grazie delle dritte Oregon!!

    Stavo giusto per chiedere delle spiegazioni in più, quindi grazie mille MItaly, mi hai tipo letto nel pensiero

    Maledette graffe, tutta presa a trovare errori logici non avevo badato al fatto che il for aveva più di un'istruzione


    Però non riesco a capire questo passaggio:
    Nota però che il programma così è ancora sbagliato: ad ogni iterazione flag viene sovrascritto, per cui se l'ultima coppia esaminata è uguale all'uscita del ciclo flag rimarrà impostato a zero.
    se in input inserisco gli interi 1, 2, 3, 3 il programma mi riconosce giustamente la ripetizione, ma da quello che dici tu (se ho capito bene) flag dovrebbe rimanere 0 e quindi mi dovrebbe comunicare che non ci sono ripetizioni.

  5. #5
    Originariamente inviato da Hiroe
    se in input inserisco gli interi 1, 2, 3, 3 il programma mi riconosce giustamente la ripetizione, ma da quello che dici tu (se ho capito bene) flag dovrebbe rimanere 0 e quindi mi dovrebbe comunicare che non ci sono ripetizioni.
    Pardon, intendevo dire "se l'ultima coppia è diversa"; se fai 1, 1, 2, 3 ti dirà che non ci sono ripetizioni.
    Amaro C++, il gusto pieno dell'undefined behavior.

  6. #6
    Utente di HTML.it
    Registrato dal
    Dec 2012
    Messaggi
    16
    Sì infatti hai ragione. Non avevo fatto caso neppure a questo...

    quindi il codice corretto è questo
    codice:
    flag=0;
    for(i=0; i<=(N*N)-1; i++) {
         for(j=i+1; j<=(N*N)-1; j++) {
              if(ar[i]==ar[j])
                  flag=1;
         }
    }
    
    if(flag==1)
       printf("\nCi sono elementi ripetuti!\n");
    else
       printf("\nNon ci sono elementi ripetuti!\n");
    Non ho usato il break perché all'uni ci hanno consigliato di evitarlo a meno che non sia strettamente necessario. In realtà non so se ce l'hanno detto a scopo didattico o per altri motivi..secondo te perché? L'istruzione break ha aspetti negativi?

  7. #7
    Originariamente inviato da Hiroe
    Non ho usato il break perché all'uni ci hanno consigliato di evitarlo a meno che non sia strettamente necessario. In realtà non so se ce l'hanno detto a scopo didattico o per altri motivi..secondo te perché? L'istruzione break ha aspetti negativi?
    Se serve perché non usarlo? Alcuni sostengono che non sia una buona idea per gli stessi motivi per cui si dovrebbe evitare il goto (fai un salto non condizionale al termine del ciclo, in un certo senso "complicando" il flusso del programma), ma personalmente ritengo che sia una sciocchezza. Il goto può saltare dovunque e dare origine a "spaghetti code", il break e il continue si capisce al volo dove vanno, e in ogni caso capita spesso di avere una seconda condizione da controllare a metà del codice del for, e in tal caso le alternative a break/continue risultano ben più illeggibili.

    In ogni caso, dato che hai già un flag in giro, potresti più semplicemente modificare le condizioni dei for:
    codice:
    flag=0;
    for(i=0; i<=(N*N)-1 && !flag; i++) {
         for(j=i+1; j<=(N*N)-1 && !flag; j++) {
              if(ar[i]==ar[j])
                  flag=1;
         }
    }
    (tra parentesi, il break che avevo specificato prima non era sufficiente per saltare tutte le restanti iterazioni inutili, dato che esce solo dal for più interno)

    Infine, un paio di consigli "stilistici": perché usi "N*N" come dimensione dell'array? Usa semplicemente N.
    Inoltre, i vari <=N-1 possono essere semplificati scrivendo <N (in C tipicamente un for che cicla sugli elementi di un array è del tipo:
    codice:
    for(i=0; i<N; i++)
    )

    Poi, per verificare se un flag è diverso da zero basta scrivere
    codice:
    if(flag)
    dato che l'if viene eseguito appunto se l'espressione specificata è diversa da zero.

    Per cui:
    codice:
    #include<stdio.h>
    #define N 4
    
    int main () {
         int ar[N];
         int i, j;
         int flag=0;
    
         for(i=0; i<N; i++){
              printf("\nInserire un numero intero (%d interi restanti): ", N-i);
              scanf("%d", &ar[i]);
         }
    
         printf("\n");
         for(i=0; i<N; i++)
              printf("%d ", ar[i]);
         printf("\n");
    
         for(i=0; i<N && !flag; i++)
              for(j=i+1; j<N && !flag; j++)
                   if(ar[i]==ar[j])
                        flag=1;
    
         if(flag)
              printf("\nCi sono elementi ripetuti!\n");
         else
              printf("\nNon ci sono elementi ripetuti!\n");
         return 0;
    }
    Amaro C++, il gusto pieno dell'undefined behavior.

  8. #8
    Utente di HTML.it
    Registrato dal
    Dec 2012
    Messaggi
    16
    Ho usato N*N perché inizialmente questo codice faceva parte di un altro programma in cui dovevo copiare gli elementi di una matrice[N][N] in un array, che quindi avrebbe dovuto avere dimensioni N*N! In effetti in questo caso non c'azzecca granché.

    Grazie di avermi fatto notare quel i<=N-1 anziché i<N, che non ha proprio senso, e di avermi schiarito le idee su break, continue e goto!!

    Super utile anche la dritta sul flag..in effetti prima di discuterne con voi avevo delle difficoltà ad uscire dai cicli for in caso usassi if, flag e compagnia bella.

    Vi ringrazio molto, siete stati gentilissimi!

    a presto

  9. #9
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.