[PROBLEMA] problema programma in c

Discussione in 'Programmazione' iniziata da StrLght98, 7 Dicembre 2017 alle 20:06.

  1. StrLght98

    • Developer

    Dal:
    13 Ottobre 2017
    Messaggi:
    55
    Mi Piace Ricevuti:
    8
    Specifiche Hardware
    Codice (Text):
    #include <stdio.h>
    #include <stdlib.h>
    #define MAX 20

    void riempiArray(int arr[], int elem, int count);
    void somma_diff_media(int arr[], int elem, int count, int *somma, int *diff, double *media);

    int main()
    {
        int num_elem = 10; /*10 è generico numero che poi viene sostituito, un riempitivo per evitare l'errore generato dal non dichiarare la dimensione dell'array*/
        int array[num_elem];
        int contatore;
        int sommaMAIN;
        int diffMAIN;
        double mediaMAIN;

        riempiArray(array, num_elem, contatore);

        somma_diff_media(array, num_elem, contatore, &sommaMAIN, &diffMAIN, &mediaMAIN);
        printf("La somma è %d \n", sommaMAIN);
        printf("La differenza è %d \n", diffMAIN);
        printf("La media è %f \n", mediaMAIN);

        return 0;

    }

    void riempiArray(int arr[], int elem, int count)
    {
        int num;
        int i=0;

        count=0;

        printf("Inserisci i numeri che compongono l'array, max 20. Inserisci un numero negativo per terminare il ciclo.");
        do{
           scanf("%d", &num);
           arr[i] = num;
           count = i;
           i++;
        }while (i < MAX && num >= 0);

        elem = count;


         for(i = 0; i<count; i++){
            printf("Il valore dell'array nel posto %d è: %d \n", i, arr[i]);
        }
    }

    void somma_diff_media(int arr[], int elem, int count, int *somma, int *diff, double *media) //funzione ancora incompleta, per ora dovrebbe calcolare solo la somma
    {
        int i=0;

        for(i=0; i<count; i++){
            *somma = *somma + arr[i];
        }

    }
     
    molto semplicemente questo codice deve essere composto dal main che chiama un'unica funzione (ovvero somma_diff_media) che poi calcola somma,differenza e media dei numeri inseriti e memorizzati in un array tramite la funzione riempiArray, la quale funziona.
    Il problema sta nel calcolo della somma (non ho ancora scritto niente per differenza e media). Essendo somma_diff_media una sola funzione che deve restituirmi 3 valori, l'unico modo è usare i puntatori.
    Però quando lo eseguo, al posto di calcolare la somma mi escono numeri stranissimi, probabilmente indirizzi di memoria anche se non ne sono sicuro. Ci sto lavorando da ore senza venirne a capo, perciò se qualcuno potesse farmi vedere come calcolare e passare correttamente la somma gliene sarei molto grato.
    Per completezza la consegna dell'esercizio è questo:

    Dati in ingresso massimo 20 numeri (ma possono essere anche meno, terminare la lettura inserendo un qualsiasi numero negativo), scrivere un programma che, attraverso funzioni, permetta di:
    1. Calcolare la somma e la differenza di tutti i numeri inseriti; 2. Calcolare la media (usando la funzione precedente) 3. Restituisce solo i numeri pari (non usare i puntatori) 4. Determinare se il numero è primo o meno (restituisce 1 se primo, 0 se non primo) 5. Restituisce solo i numeri primi (nuovo array).
     
  2. Andretti60

    • Utente Binario

    Dal:
    1 Febbraio 2011
    Messaggi:
    1.976
    Mi Piace Ricevuti:
    1.462
    Specifiche Hardware
    Questo e' uno di quei casi in cui se hai un debugger ti aiuterebbe tantissimo, eseguendo una istruzione alla volta, e guardando il risultato delle operazioni, perché hai fatto veramente molti errori. Il problema principale e' che passi variabili o per valore o per indirizzo, ma non le usi come dovresti. Per esempio, perché passare 'count' to riempiArray, dove e' solo una variabile locale? Perché passare 'elem' se poi non lo usi? Il tuo uso di MAX e' sbagliato, perché poi usi una variabile con lo stesso scopo ma con valore diverso.
    Molto importante, e qui e' che sbagli, quando sommi qualcosa a una variabile, assicurati prima di iniziare a sommare che la variabile sia inizializzata a zero.

    Codice (Text):

        *somma = 0;  // <<<-----
        for(i=0; i<count; i++){
            *somma = *somma + arr[i];
        }
     
     
    A StrLght98 piace questo elemento.
  3. StrLght98

    • Utente Binario

    Dal:
    13 Ottobre 2017
    Messaggi:
    55
    Mi Piace Ricevuti:
    8
    Specifiche Hardware
    Innanzitutto grazie per la risposta! Non capisco però quando dici che count e elem non le uso, è vero uno dei due non serviva e me ne sono reso conto, ma almeno una delle due non serve passarla al main come contatore? Perchè senza una variabile che mi facesse da contatore avevo il problema che poi nella chiamata mi passasse indici di array fino a 20 senza fermarsi prima come dovrebbe (chiaramente se inserisco meno di 20 numeri che è il limite massimo).
    MAX era inutile pure quella. Per quanto riguarda l'inizializzazione lo so, ma ho provato in tutti i modi sia inizializzandola sia no ma resistuisce sempre valori assurdi, sia inizializzandola a zero sia no.
    Ora provo con il debugger, non è che ci abbia molta dimestichezza ad essere sincero e vedo se riesco a sistemare. Intanto grazie della risposta, che mi ha comunque aiutato a snellire il programma da diverse cose inutili.

    EDIT: Trovato il problema. In pratica nella chiama a somma_diff_media, al posto di fermarsi al numero dettato da count il calcolatore si ferma al valore assegnato a num_elem, che teoricamente dovrebbere essere solo un riempitivo per non dare errore che poi viene sostituito dal valore di count quando chiamo il sottoprogramma. Ora provo a sistemare e nel caso riposto il codice come è ora (ho provato a sostituire il ciclo for alla fine con un ciclo do-while) che forse è più snello e leggibile.


    Codice (Text):
    #include <stdio.h>
    #include <stdlib.h>

    void riempiArray(int arr[], int count);
    void somma_diff_media(int arr[], int count, int *somma, int *diff, double *media);

    int main()
    {
        int num_elem =10; /*<---qui è il problema, al posto di sostituire questo 10 che consideravo come riempitivo con il valore di count, il calcolatore va avanti fino a quando non eguaglia questo numero. In poche parole, se ad esempio inserisco 3 numeri, lui ne processa 7 in più totalmente a caso generando risultati assurdi */
        int array[num_elem];
        int sommaMAIN;
        int diffMAIN;
        double mediaMAIN;


        riempiArray(array, num_elem);

        somma_diff_media(array, num_elem, &sommaMAIN, &diffMAIN, &mediaMAIN);
        printf("La somma è %d \n", sommaMAIN);
        printf("La differenza è %d \n", diffMAIN);
        printf("La media è %f \n", mediaMAIN);

        return 0;

    }

    void riempiArray(int arr[], int count)
    {
        int num;
        int i=0;
        count=0;

        printf("Inserisci i numeri che compongono l'array, max 20. Inserisci un numero negativo per terminare il ciclo.");
        do{
           scanf("%d", &num);
           arr[i] = num;
           count = i;
           i++;
        }while (i < 20 && num >= 0);



         for(i = 0; i<count; i++){
            printf("Il valore dell'array nel posto %d è: %d \n", i, arr[i]);
        }
    }

    void somma_diff_media(int arr[], int count, int *somma, int *diff, double *media) //funzione ancora incompleta, per ora dovrebbe calcolare solo la somma
    {
        int i=0;

        *somma = 0;

        do{
            *somma = *somma + arr[i];
            printf("La somma al posto %d è: %d ", i, *somma);
            i++;
        }while(i<count);

    }
     
     
    #3 StrLght98, 8 Dicembre 2017 alle 00:41
    Ultima modifica: 8 Dicembre 2017 alle 01:35
  4. Andretti60

    • Utente Binario

    Dal:
    1 Febbraio 2011
    Messaggi:
    1.976
    Mi Piace Ricevuti:
    1.462
    Specifiche Hardware
    Ci sei quasi.
    Il problema principale, tanto per iniziare, e' che nel main allochi un vettore di 10 elementi, ma in riempiArray se uno non entra un numero negativo arrivi fino a 20. Questo causa una bella corruzione di memoria, ossia vai a scrivere in una zona di memoria non riservata al vettore di ingresso, causando chissà quali danni. Quindi in riempiArray ti devi fermare al massimo quante volte e' specificato nel valore massimo che gli hai passato.
    Secondo, riempiArray deve tornare quanti valori sono stati entrati, altrimenti nelle operazioni successive non sai quando fermarti. Questo lo puoi fare dichiarando il metodo 'int' e ritornando il valore giusto, oppure passando un variabile per puntatore. Scegli tu, qualunque opzione e' valida.

    Eccoti un esempio del main:
    Codice (Text):

        int count =  riempiArray(array, num_elem);
        if (count == 0) {}  /// ... non fare nulla e fermati

        somma_diff_media(array, count, &sommaMAIN, &diffMAIN, &mediaMAIN);
     
     
    A StrLght98 piace questo elemento.
  5. Marcus Aseth

    • Utente Binario

    Dal:
    17 Aprile 2010
    Messaggi:
    258
    Mi Piace Ricevuti:
    53
    Specifiche Hardware
    Ma io non capisco, perchè tutte queste persone presentano problemi in C e nessuno in C++? Insegnano soltanto C nelle scuole? o_o
    Attenzione non sto affatto dicendo che C non serva, voglio soltanto dire che uno può andare anche nella direzione opposta, ovvero imparare C++ e poi quello che gli manca di C, che ad occhio e croce (da quello che vedo dai post della gente) si riduce all' uso del printf e scanf, mentre imparando C++ come base si hanno molti più strumenti come reference, vector, string, map, list, template, class, iterator ecc... e nulla vieta all'insegnante di dare esercizi dove ne proibisce l'uso per fare pratica con array e pointers.
    Bho, non capisco perchè in questo paese non si guardi al futuro più che al passato insomma :|
    Mi da quasi l'impressione che la maggior parte degli insegnati abbia imparato una sola cosa ai tempi, e non fossero abbastanza interessati al soggetto per mettersi d'impegno ed evolvere con i tempi (imparare un nuovo linguaggio ogni anno insomma, o qualcosa del genere), e quindi continuano ad insegnare soltanto quell' unica cosa che sanno. Attenzione non dico sia la realtà delle cose, solo l'impressione che io ho vedendo nel quasi 2018 praticamente tutti che iniziano da C anzichè C++.

    Scusate l' OT :P
     
    #5 Marcus Aseth, 8 Dicembre 2017 alle 09:00
    Ultima modifica: 8 Dicembre 2017 alle 09:09
    A StrLght98 piace questo elemento.
  6. rodhellas

    • Developer

    Dal:
    10 Agosto 2013
    Messaggi:
    1.238
    Mi Piace Ricevuti:
    333
    Specifiche Hardware
    Se uno deve imparare a guidare, userà una macchina sportiva con tutti i vari gadget e che fa praticamente tutta da sola o una vecchia carcassa con cambio manuale per imparare bene?
     
    A StrLght98 piace questo elemento.
  7. Marcus Aseth

    • Utente Binario

    Dal:
    17 Aprile 2010
    Messaggi:
    258
    Mi Piace Ricevuti:
    53
    Specifiche Hardware
    Chi và con lo zoppo impara a zoppicare.

    Una volta prese certe brutte abitudini, si scriverà codice con una montagna di new e dimenticando alcuni delete che poi dovrà essere mantenuto dalla generazione futura ed il ciclo non terminerà mai. Perchè invece non dire di quella possibilità, fare vari esercizi al riguardo (come detto vietando l'uso di smart pointers e simili, proprio per allenarsi nelle basi ), ma principalmente allenandosi nelle buone pratiche degli smart pointers ecc...?
    Un'analogia simile alla tua ma piu vicina alla realtà delle cose sarebbe quella di imparare a guidare con una vecchia macchina senza freni, e poi quando ti danno quella sportiva non hai idea di cosa sia il freno ed ormai sei abituato a compensare in altri modi (è difficile perdere le brutte abitudini) e quindi non ti curerai mai di frenare.

    E quando sara il turno di questa persona per insegnare le cose nelle quali lui si è allenato, alla nuova generazione insegnera le stesse cose, e quindi anche loro impareranno a guidare senza un freno :/
    Non mi pare affatto il modo migliore di muoversi verso il futuro.
     
    #7 Marcus Aseth, 8 Dicembre 2017 alle 12:23
    Ultima modifica: 8 Dicembre 2017 alle 12:51
    A StrLght98 piace questo elemento.
  8. rodhellas

    • Developer

    Dal:
    10 Agosto 2013
    Messaggi:
    1.238
    Mi Piace Ricevuti:
    333
    Specifiche Hardware
    Hai prove a riguardo? Di quali brutte abitudini stai parlando? La new e la delete esistono anche in C (con nomi diversi)

    P.S: Le analogie dovrebbero essere sensate (macchine senza freni?)
     
    A StrLght98 piace questo elemento.
  9. Marcus Aseth

    • Utente Binario

    Dal:
    17 Aprile 2010
    Messaggi:
    258
    Mi Piace Ricevuti:
    53
    Specifiche Hardware
    No non ho prove a riguardo non ho fatto sondaggi ne nulla :D , è solo una mia impressione.

    Ah, pensavo ci fossere anche in C con quei nomi. Ma quello che penso è, se C++ offre degli strumenti che rendono il tutto più sicuro evitando di dover andare in seguito a caccia di bug difficili da trovare...perchè ostinarsi con C? Sopratutto considerando che un insegnante può vietare ai suoi studenti l'uso di praticamente tutto quello in più che C++ offre e fargli svolgere gli stessi esercizi come se li stessero facendo in C, o sbaglio? Per poi poter dire alla fine "questo che abbiamo visto è il modo in cui si fà in C, ed ora vediamo l'equivalente in C++" e poter fare il paragone, mostrando entrambi i metodi ed aggiungendo gradualmente

    Nulla nello specifico, piu che altro di tutto quello che uno si perde non vedendo l'equivalente in C++. Cioè, Io sono partito con C++ e non mi son mai messo ad imparare C, eppure non ho trovato la cosa difficile come la gente lo descrive, inoltre penso di saper usare un array nello stesso modo uno che studia C lo usa, con la differenza che se mi viene data la scelta, preferisco usare un vector. Percui il fatto che uno persona non abbia quella scelta, mi sembra di per se una cosa negativa, "brutta abitudine" forse non è il termine migliore per descriverlo :/ Insomma, la vedo come una cosa negativa, sapendo (per esperienza) che si può giungere allo stesso risultato ma con più strumenti/scelte semplicemente partendo da C++.
     
    A StrLght98 piace questo elemento.
  10. rodhellas

    • Developer

    Dal:
    10 Agosto 2013
    Messaggi:
    1.238
    Mi Piace Ricevuti:
    333
    Specifiche Hardware
    Secondo me C ti permette di capire di più la "programmazione" perchè sei costretto a "tagliargliela giù" e a concentrarti sull'algoritmo. Tanto per dire, mi ricordo che per fare le liste puntate in C ci persi delle belle ore per capirle, ma ora mi vengono senza problemi e ho una comprensione più alta del programma/computer/memoria. Ovviamente ora che lavoro con Java e C# non tornerei mai indietro a C per le liste sia chiaro :asd:
    In altre parole, sempre IMHO, studiando C si vuole puntare a capire come programmare, in C++ (o java o c# etc) si punta ad ottenere il risultato.

    P.S: Mi scuso se son sembrato aggressivo
     
    A StrLght98 e Marcus Aseth piace questo messaggio.
  11. Marcus Aseth

    • Utente Binario

    Dal:
    17 Aprile 2010
    Messaggi:
    258
    Mi Piace Ricevuti:
    53
    Specifiche Hardware
    Niente affatto :)

    Le liste puntate sono le linked list, giusto? Bhe, si potrebbe dare lo stesso esercizio in C++ e cioè di non fare "#include <list>" ma di implementarne una, nessuno lo vieta (infatti ci provai) :P
    Non so bene cosa implichi farlo in C, ma suppongo che con le giuste "restrizioni" l'esercizio sarebbe pressochè identico in C++ (volendo magari aggiungendo anche qualche task extra che non si può fare in C, come ad esempio implementare l'overload del subscript operator per la list o dell'operatore ++ per andare all'elemento successivo o generalizzarne l'uso tramite template)

    Cmq non ho niente contro C in sè, se chi lo insegna lo fà come parte di un percorso o con le giuste motivazioni dietro, e non perchè semplicemente non conosce altro modo e quindi insegna quello. Non conosco neppure nessuno che insegna, quindi davvero non posso esprimermi sulla situazione :D
    Semplicemente sono perplesso vedendo la maggior parte dei post su questo forum chiedere su C, preferirei un 50-50 :D
     
    A StrLght98 piace questo elemento.
  12. Andretti60

    • Utente Binario

    Dal:
    1 Febbraio 2011
    Messaggi:
    1.976
    Mi Piace Ricevuti:
    1.462
    Specifiche Hardware
    È un discorso interessante e se ne siete interessati dovreste farlo in una discussione separata, a meno che non ne esista già una sull'argomento.
    Perché insegnare il C? Perché è un ottimo linguaggio educativo, lo stesso per il Pascal. Molti college americani nelle prime lezioni non usano nemmeno nessun linguaggio commerciale, solo metalinguaggi fatti solo per motivi educativi, per mantenere l'attenzione su "come" programmare e non per impare un linguaggio di programmazione, imparare un linguaggio è facile, imparare a programmare NO.
     
    A StrLght98 e Marcus Aseth piace questo messaggio.
  13. StrLght98

    • Utente Binario

    Dal:
    13 Ottobre 2017
    Messaggi:
    55
    Mi Piace Ricevuti:
    8
    Specifiche Hardware
    Grazie mille, sei statp gentilissimo! Domani ci riprovo tenendo presente i tuoi consigli e il suggerimento di codice che mi hai dato :)
     
    A Andretti60 piace questo elemento.
  14. StrLght98

    • Utente Binario

    Dal:
    13 Ottobre 2017
    Messaggi:
    55
    Mi Piace Ricevuti:
    8
    Specifiche Hardware
    Ti rispondo volentieri dando le motivazioni che il mio professore di informatica ci ha dato (io ho iniziato solo da qualche mese informatica e non posso che riportare le sue motivazioni, che dal mio punto di vista di studente mi sembrano più corrette). Sono al primo anno di ingegneria fisica al politecnico di Milano e solo il primo anno abbiamo informatica. Ho fatto questa specificazione per due motivi: il primo è che, essendo per l'appunto ingegneria fisica, non è un corso incentrato sull'informatica ma è solo un'infarinatura propedeutica a successivi approfondimenti in ambito sia universitario che lavorativo, il secondo è che è una scelta dettata da altri motivi e non da un'eventuale "ignoranza" di altri linguaggi da parte del mio professore, cosa che peraltro potrebbe essere anche possibile alle scuole superiore ma che vedo piuttosto difficile visto che siamo in un corso di ingegneria al politecnico di Milano e che il suddetto professore fa il programmatore come lavoro da una vita.
    Comunque secondo il mio professore, il c essendo uno dei linguaggi linguaggi che sono stati la base dell'attuale mondo informatico da cui poi sono derivati c++ e anche java se non sbaglio, si presta particolarmente ad imparare i meccanismi base di tutta una famiglia di linguaggi e, più in generale, dei meccanismi di programmazione.
    Essendo appunto l' unico nella triennale di programmazione ed essendo un corso semestrale, penso sia giusto che si parta dalle basi e secondo il nostro professore il c è un tipo di linguaggio che si presta molto bene a darci un'infarinatura discretamente approfondita del mondo della programmazione.
    Nell'ultima parte del semestre abbiamo invece iniziato lo studio di matlab in netto contrasto con c (uno è un linguaggio statico e l'altro dinamico) e su questo contrasto ha impostato tutta quest'ultima parte di corso. Peraltro matlab è un bel linguaggio che ci sarà sicuramente utile in un corso come il mio.
    Queste sono le motivazioni che ci sono state dette, di più non ti saprei dire :)
     
    A Marcus Aseth piace questo elemento.
  15. Marcus Aseth

    • Utente Binario

    Dal:
    17 Aprile 2010
    Messaggi:
    258
    Mi Piace Ricevuti:
    53
    Specifiche Hardware
    Molto interessante, grazie per aver condiviso :)
    Se fosse il mio professore avrei altre domende da fargli al riguardo, ad esempio, tutto il codice scritto da te sopra di fatto è C++, la differenza più ovvia magari (con la premessa di non usare vector o altre "data structure" che ci sono solo in C++ e non in C) sarebbe che se scritto in C++, probabilmente il "scanf" sarebbe rimpiazzato da "cin" e "printf" sarebbe rimpiazzato da "cout", ed essendo "cin" ed "cout" più "user friendly" o "eleganti" (imho) rispetto a "scanf" e "printf" (non devi memorizzarti una lista di %d %s ecc...), allora qual'è il vero vantaggio di farlo in C?!
    Insomma finirei per tormentarlo ad ogni lezione con le mie domande sul perchè :D

    Io sono per tenere tutte quelle basi di C che permettono di capire bene come programmare ma allo stesso tempo prendere certe parti di C++ (come il cout) che rimuovono complessità inutile e permettono di concentrarsi meglio sul problema che si sta cercando di risolvere :P
    Alla fine C++ è "plus plus" soltanto in base a quanto uno vuole che lo sia.
    Comunque, ognuno ha la sua opinione :)
     
    #15 Marcus Aseth, 8 Dicembre 2017 alle 21:05
    Ultima modifica: 8 Dicembre 2017 alle 21:10

Condividi questa Pagina