[AIUTO] esercizio istruzioni condizionali

di il
11 risposte

[AIUTO] esercizio istruzioni condizionali

Buongiorno , sono nuovo nel forum quindi spero di aver postato nella sezione giusta... ma bando alle ciance.
HO UN PROBLEMA.
E' da ieri che tento di creare un programma che chiede all'utente di inserire quattro numeri interi, li legge e stampa uno dei seguenti messaggi:
- "Ci sono esattamente 4 numeri fra loro uguali" (se i numeri sono ad esempio 1,1,1,1)
- "Ci sono esattamente 3 numeri fra loro uguali" (se i numeri sono ad esempio 1,1,1,2)
- "Ci sono esattamente 2 numeri fra loro uguali" (se i numeri sono ad esempio 1,1,2,3)
- "Ci sono due coppie di numeri fra loro uguali" (se i numeri sono ad esempio 1,1,2,2)
- "Ci sono esattamente 0 numeri fra loro uguali" (se i numeri sono ad esempio 1,2,3,4)

ho provato e riprovato, ma ogni volta c'e qualcosa che non va come per esempio:
inserisco (1,1,1,1) e ok
inserisco (1,1,2,2) e ok
inserisco (1,1,1,2) e invece di stamparmi solo il printf("Ci sono ..."); ,mi stampa anche altri printf...

Probabilmente ho sbagliato la condizione dell'if quindi vi metto qua sotto il codice per potergli dare un'occhiata..
int int1, int2, int3, int4;
     
     /* input */
     printf("Inserisci 4 numeri interi e ti dir%c quanti sono uguali fra loro\n", 149);
     scanf("%d%d%d%d", &int1, &int2, &int3, &int4);
     
     if((int1!=int2) && (int2!=int3) && (int3!=int4))
         printf("Ci sono esattamente 0 numeri uguali fra loro.\n");
         else{
         if(int1==int2 && int2==int3 &&  int3==int4)
             printf("Ci sono esattamente 4 coppie uguali.\n");
     }
      if(((int1==int2) && (int3==int4)) || ((int1==int4) && (int2==int4)))
                 printf("Ci sono due coppie di numeri fra loro.\n");
                 else{
                     if(int1==int2 || int2==int3 || int3==int4 || int1==int3 || int2==int4)
                         printf("Ci sono esattamente 2 numeri uguali fra loro.\n");
                         else{
                 if(int1!=int2 || int2!=int3 || int3!=int4 || int4!=int1 || int2!=int4)
                     printf("Ci sono esattamente 3 coppie uguali.\n");
             }
             
                         
         }

11 Risposte

  • Re: [AIUTO] esercizio istruzioni condizionali

    Posta il codice utilizzando gli appositi tag, altrimenti non si capisce nulla.
  • Re: [AIUTO] esercizio istruzioni condizionali

    Nippolo ha scritto:


    Posta il codice utilizzando gli appositi tag, altrimenti non si capisce nulla.
    giusto sry, l'ho appena fatto
  • Re: [AIUTO] esercizio istruzioni condizionali

    Innanzitutto ho modificato il tuo codice al fine di renderlo più chiaro e leggibile:
    #include <stdio.h>
    
    int main()
    {
        int a = 1;
        int b = 1;
        int c = 1;
        int d = 2;
        if(a != b && b != c && c != d)
        {
            printf("Ci sono esattamente 0 numeri uguali fra loro.\n");
        }
        else
        {
            if(a == b && b == c && c == d)
            {
                printf("Ci sono esattamente 4 coppie uguali.\n");
            }
        }
        if(a == b && c == d || a == d && b == d)
        {
            printf("Ci sono due coppie di numeri fra loro.\n");
        }
        else
        {
            if(a == b || b == c || c == d || a == c || b == d)
            {
                printf("Ci sono esattamente 2 numeri uguali fra loro.\n");
            }
            else
            {
                if(a != b || b != c || c != d || d != a || b != d)
                {
                    printf("Ci sono esattamente 3 coppie uguali.\n");
                }
            }
        }
        return 0;
    }
    
    non è complicato, basta rispettare l'indentazione e la spaziatura ed evitare di abbondare con le parentesi tonde solo perché non si conosce la precedenza fra gli operatori.
    Occupiamoci ora della parte logica:
    - dal momento che i 5 messaggi sono associati a 5 casistiche distinte che non possono verificarsi contemporaneamente, gli if/else devono essere strutturati in modo che per ogni quaterna di valori venga stampato un unico messaggio. Prova ad inserire i valori 1 2 1 3, cosa succede?
    - volendo entrare nel dettaglio, soffermiamoci per esempio sulla prima condizione:
    a != b && b != c && c != d
    per la quaterna 1 2 1 2 la suddetta condizione risulta vera, ma non mi sembra che "Ci sono esattamente 0 numeri uguali fra loro".

    Come vedi tutto l'impianto logico è completamente da rifare!

    Una domanda: l'esercizio deve essere risolto utilizzando soltanto if/else ed espressioni logiche, giusto?
  • Re: [AIUTO] esercizio istruzioni condizionali

    Nippolo ha scritto:


    Innanzitutto ho modificato il tuo codice al fine di renderlo più chiaro e leggibile:
    #include <stdio.h>
    
    int main()
    {
        int a = 1;
        int b = 1;
        int c = 1;
        int d = 2;
        if(a != b && b != c && c != d)
        {
            printf("Ci sono esattamente 0 numeri uguali fra loro.\n");
        }
        else
        {
            if(a == b && b == c && c == d)
            {
                printf("Ci sono esattamente 4 coppie uguali.\n");
            }
        }
        if(a == b && c == d || a == d && b == d)
        {
            printf("Ci sono due coppie di numeri fra loro.\n");
        }
        else
        {
            if(a == b || b == c || c == d || a == c || b == d)
            {
                printf("Ci sono esattamente 2 numeri uguali fra loro.\n");
            }
            else
            {
                if(a != b || b != c || c != d || d != a || b != d)
                {
                    printf("Ci sono esattamente 3 coppie uguali.\n");
                }
            }
        }
        return 0;
    }
    
    non è complicato, basta rispettare l'indentazione e la spaziatura ed evitare di abbondare con le parentesi tonde solo perché non si conosce la precedenza fra gli operatori.
    Occupiamoci ora della parte logica:
    - dal momento che i 5 messaggi sono associati a 5 casistiche distinte che non possono verificarsi contemporaneamente, gli if/else devono essere strutturati in modo che per ogni quaterna di valori venga stampato un unico messaggio. Prova ad inserire i valori 1 2 1 3, cosa succede?
    - volendo entrare nel dettaglio, soffermiamoci per esempio sulla prima condizione:
    a != b && b != c && c != d
    per la quaterna 1 2 1 2 la suddetta condizione risulta vera, ma non mi sembra che "Ci sono esattamente 0 numeri uguali fra loro".

    Come vedi tutto l'impianto logico è completamente da rifare!

    Una domanda: l'esercizio deve essere risolto utilizzando soltanto if/else ed espressioni logiche, giusto?
    Si bisogna usare solo if-else.
    E come lo dovrei impostare il programma?
  • Re: [AIUTO] esercizio istruzioni condizionali

    Io farei qualcosa del genere:
    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>
    
    int main()
    {
        srand(time(0));
        int a, b, c, d;
        for(int i = 0; i < 20; ++i)
        {
            a = rand() % 4;
            b = rand() % 4;
            c = rand() % 4;
            d = rand() % 4;
            printf("%d %d %d %d --> VALORI UGUALI = ", a, b, c, d);
            if(a == b && a == c && a == d)
            {
                printf("4\n");
            }
            else if(a == b && (a == c || a == d) || c == d && (c == a || c == b))
            {
                printf("3\n");
            }
            else if(a == b && c == d || a == c && b == d || a == d && b == c)
            {
                printf("2-2\n");
            }
            else if(a == b || a == c || a == d || b == c || b == d || c == d)
            {
                printf("2\n");
            }
            else
            {
                printf("0\n");
            }
        }
        return 0;
    }
    Se qualcuno ha una soluzione più efficiente/elegante mi faccia sapere.

    @denisoi se non riesci a dedurre la logica che sta dietro a quelle condizioni fammi sapere che cerco di spiegartela.
  • Re: [AIUTO] esercizio istruzioni condizionali

    Risolto grazie, ho rivisto tutta la parte logica e adesso mi va.
  • Re: [AIUTO] esercizio istruzioni condizionali

    Nippolo ha scritto:



    Se qualcuno ha una soluzione più efficiente/elegante mi faccia sapere.
    La tua soluzione è ottima dato il topic (istruzioni condizionali)
    ma io ho pensato ad una strada alternativa, che non enumera i possibili casi, si limita a contare le ripetizioni
    ho pensato ad un array, invece di alciìune variabili "slegate"
    e ho pensato di inglobarla in una funzione, per renderla generica
    come lavorerei: ciclo lo array, cerco e conto le ripetizioni, sostituisco al numero il suo conto delle ripetizioni e cancello dallo array gli elementi ripetuti
    ecco il codice
    
    #include <stdio.h>
    
    void contadoppi(int * a, int sa);
    // conta i doppi nello array 'a' di dimensione 'sa'
    
    int main(int argc, char **argv)
    {
       // genero lo array e calcolo la sua dimensione
       int a[] = {1, 2, 3, 4, 5, 1, 2, 3, 4, 4, 4, 4, 5, 10, 3, 10};
       int sa = sizeof(a) / sizeof(a[0]);
       // per semplicità lo passo ad una funzione, ma potrebbe anche essere nel main()
       contadoppi(a, sa);
       return 0;
    }
    
    void contadoppi(int * a, int sa)
    // conta i doppi nello array 'a' di dimensione 'sa'
    {
       // se servisse non toccare lo array originale lo duplicherei in locale qui
       for(int i = 0; i < sa; i++)
       {
          int attuale = a[i]; // valore da cercare
          a[i] = 0; // sostituisco il valore con il numero di ripetizioni
    
          // cerco le ripetizioni
          for(int j = i + 1; j < sa; j++)
          {
             // vediamo se è una ripetizione
             if(a[j] == attuale)
             {
                // lo è, lo conto e lo elimino, accorciando lo array
                a[i]++;
                sa--;
    
                for(int k = j; k < sa; k++)
                {
                   a[k] = a[k + 1];
                }
    
                // siccome ho accorciato lo array devo tornare indietro di un passo
                j--;
             }
          }
    
          // ok, qui ho contato le ripetizioni
          if(a[i])
          {
             // almeno una ripetizione
             printf("%d ", a[i] + 1); // conta le ripetizioni, ma a me serve di contare anche il primo trovato
          }
       }
    }
    
    mi sembra più elegante e più espandibile
  • Re: [AIUTO] esercizio istruzioni condizionali

    Se lo scopo è quello di contare le occorrenze in un array, allora le strade percorribili sono tante, considerando ovviamente anche la tua.

    Per esempio io, sia per sganciarsi dal tipo dell'array sia per rendere i risultati più facilmente interpretabili, farei qualcosa del genere:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void get_occurrence(char *v_data, unsigned int data_size, unsigned int *v_first_index, unsigned int *v_occurrence, unsigned int *occurrence_size)
    {
        *occurrence_size = 0;
        int flag;
        for(unsigned int i = 0; i < data_size; ++i)
        {
            flag = 1;
            for(unsigned int j = 0; j < *occurrence_size; ++j)
            {
                if(v_data[v_first_index[j]] == v_data[i])
                {
                    flag = 0;
                    ++v_occurrence[j];
                    break;
                }
            }
            if(flag)
            {
                v_first_index[*occurrence_size] = i;
                v_occurrence[(*occurrence_size)++] = 1;
            }
        }
    }
    
    int main()
    {
        //int a[] = {1, 2, 3, 4, 5, 1, 2, 3, 4, 4, 4, 4, 5, 10, 3, 10};
        //int sa = sizeof(a) / sizeof(*a);
        char a[] = "farfalla";
        unsigned int sa = strlen(a);
        unsigned int *u = malloc(sa * sizeof(unsigned int));
        unsigned int *v = malloc(sa * sizeof(unsigned int));
        unsigned int n;
        get_occurrence(a, sa, u, v, &n);
        for(unsigned int i = 0; i < n; ++i)
        {
            printf("%c: %d\n", a[u[i]], v[i]);
        }
        free(u);
        free(v);
        return 0;
    }
  • Re: [AIUTO] esercizio istruzioni condizionali

    Sì, però non ti sei prorpio proprio sganciato dal tipo dell'array
    io ho provato a passare un array di int, ma non va (ovviamente)
    se vgliamo proprio renderci indipendenti dal tipo dell'array dobbiamo cambiare un po' il punto di vista
    per cominciare non possiamo stampare l'elemento (non dalla funzione almeno, dato che non sa che tipo dovrebbe stampare)
    ci tocca di indicare l'ordinale dell'elemento trovato doppio, ma non il suo valore (al limite potrebbe anche essere una struttura.........)
    ecco cosa ho tirato fuori:
    
    #include <stdio.h>
    #include <string.h>
    
    void contadoppi(void * a, size_t sa, size_t dimensione);
    // conta i doppi in un array generico di oggetti generici
    
    int main(int argc, char **argv)
    {
       int a[] = {1, 2, 1, 2, 4, 3, 3, 3, 3};
       int sa = sizeof(a) / sizeof(a[0]);
       int dima = sizeof(a[0]);
       char b[] = "Una stringa piena di doppioni aabbccdd";
       int sb = sizeof(b) / sizeof(b[0]);
       int dimb = sizeof(b[0]);
       float c[] = {1.0, 2.0, 3.0, 1.0, 1.0};
       int sc = sizeof(c) / sizeof(c[0]);
       int dimc = sizeof(c[0]);
       contadoppi(a, sa, dima);
       contadoppi(b, sb, dimb);
       contadoppi(c, sc, dimc);
       return 0;
    }
    
    void contadoppi(void * a, size_t sa, size_t dimensione)
    // conta i doppi in un array generico di oggetti generici di dimensione (sizeof) conosciuta
    {
       for(size_t i = 0; i < sa; i++)
       {
          size_t contatore = 0;
          // per tutti gli elementi
          void * attuale = a + i * dimensione;
    
          for(size_t j = 0; j < sa; j++)
          {
             // cerchiamo i doppi
             void * candidato = a + j * dimensione;
    
             // ora, se sono lo stesso elemento, lo ignoro
             if(attuale == candidato)
             {
                continue;
             }
    
             // altrimenti devo vedere se sono due elementi uguali
    
             if(!memcmp(attuale, candidato, dimensione))
             {
                // sono uguali
                // se il puntatore è inferiore
                if(candidato < attuale)
                {
                   // già trovato e già contato in precedenza
                   // lo scarto
                   break;
                }
    
                else
                {
                   // non ancora trovato ne contato in precedenza
                   contatore++;
                }
             }
          }
    
          // ok, se il contatore è alto
          if(contatore)
          {
             // lo segnalo
             printf("L'elemento numero %d è ripetuto nel complessivo %d volte\n", i, contatore + 1);
          }
       }
    }
    
    
    come vedi passo oltre al numero di elementi anche la loro dimensione, ma uso solo void *
    quindi posso fare un test con la memcmp(), e uso l'aritmetica dei puntatori per trovare il vero indirizzo dell'oggetto
    come vedi funzia con interi, caratteri e float
    non ho provato con struct, ma confido in bene........
  • Re: [AIUTO] esercizio istruzioni condizionali

    Lo scopo del mio codice era di utilizzare un algoritmo efficiente, di avere risultati utilizzabili anche al ritorno nel main e di sganciarsi dal tipo dell'array nel senso che nel mio codice basta solo modificare il tipo dell'argomento v_data.
    Per quanto riguarda il codice che hai postato vorrei farti notare che lo standard C/C++ non consente di effettuare l'aritmetica dei puntatori su puntatori void; probabilmente se a te compila stai utilizzando il compilatore GCC (che considera sizeof(void)=1) con il flag -pedantic-errors disattivato (ciò si traduce nel fatto che il tuo codice non è portabile).
    "Se vogliamo proprio renderci indipendenti dal tipo dell'array", dal momento che in C non esistono i template e l'overloading delle funzioni, si potrebbe ricorrere a delle macro. Volendo invece adottare la soluzione da te proposta, bisognerebbe effettuare il casting del puntatore void a char* (visto che lo standard prevede che sizeof(char)=1) prima di giocare con l'aritmetica dei puntatori. Per esempio nel mio precedente codice basterebbe sostituire la riga di codice
    if(v_data[v_first_index[j]] == v_data[i])
    con
    if(!memcmp((char*)v_data + v_first_index[j] * data_type_size, (char*)v_data + i * data_type_size, data_type_size))
  • Re: [AIUTO] esercizio istruzioni condizionali

    Verissimo, tutto chiaro. Grazie
Devi accedere o registrarti per scrivere nel forum
11 risposte