Visualizzazione dei risultati da 1 a 7 su 7
  1. #1

    [C]Primi dubbi riguardo il tutorial

    Ciao a tutti, è la prima volta che scrivo, non sono un frequentatore abituale di forum anche perchè solitamente cerco di risolvere i problemi da me prima di "disturbare" altri utenti ma questa volta mi sono deciso ad iscrivermi anche perchè sono molto motivato ad avvicinarmi al mondo della programmazione e mi pare di aver capito che il fai da te in questo campo non è cosa facile, ed allora un po di umiltà e via..

    Ho cominciato con la guida di C presente sul sito, devo dire veramente ben strutturata e di facile comprensione.
    I primi 20 capitoli me li sono fumati anche grazie a qualche rimembranza dai tempi del ITI.
    Premetto che la mia motivazione nasce dalla pura curiosità/passione per questa disciplina, non lo faccio ne per motivi didattici ne tanto meno per possibili opportunità lavorative(anche se..magari in futuro.. ).

    Ora, dopo aver ripassato le prime istruzioni basilari a me tanto care e con le quali mi son sempre divertito a crear programmini che non avevano nulla a che fare con cio che mi veniva richiesto all'epoca, inizio a scontrarmi con le prime difficoltà..

    1)Nella fattispecie comincio con il linkare una porzione di codice che viene presentata nella "Guida C" al capitolo 20(http://programmazione.html.it/guide/...ile-for-break/) che non mi è molto chiara, non tanto per quanto riguarda le istruzioni di iterazione in se ma piu che altro rispetto ad una istruzione di controllo che prevede un operatore logico:

    [...]presentiamo un semplice codice in cui si legge un numero da tastiera che volgiamo sia compreso tra 0 e 100, se tale valore risulta essere negativo, si esce dal ciclo, mentre se è maggiore di cento si richiede di inserire un valore valido; se il valore è tra 1 e 100, si stampa a video il suo quadrato, se è zero si esce:

    codice:
    int valore;
    
    while (scanf("%d", &valore) == 1 && valore != 0)
    {
       if (valore < 0)
       {
          printf("Valore non consentiton");
          break;
          /* esce dal ciclo */
       }
    
       if (valore > 100)
       {
          printf("Valore non consentiton");
          continue;
       }
    
       int quadrato = valore * valore;
       printf("%d n", quadrato);
    }
    Il mio dubbio riguarda il boldato, secondo la mia interpretazione il ciclo while dovrebbe uscire solo nel momento in cui la condizione rappresentata da (valore==1 && valore!= 0) diventa falsa, ma in questo caso non dovrebbe essere consentito solo un valore di input=1 ?
    In tutti gli altri casi l'operatore AND non dovrebbe restituire false?
    Quindi per come lo percepisco io, il programma non funzione per quello che è stato progettato, cosa mi sfugge?

    2)Ne approfitto che chiedere un ulteriore chiarimento inerente ad un altro capitolo onde evitare di aprire un altro 3d dato che mi rendo conto che ai piu potrebbe risultare fin troppo noioso leggere discussioni simili...

    Dal Capitolo 24: (http://programmazione.html.it/guide/...2/le-funzioni/)
    [...]In C, quando si passano gli argomenti (variabili) alle funzioni, bisogna prestare attenzione al passaggio di array ad una o più dimensioni; la regola dice che la prima dimensione dell'array può non essere specificata, mentre la seconda e le altre devono esserlo. Un esempio chiarirà meglio il concetto:
    codice:
    void stampa_array_uni(int dim, int array_uni[])
    {
      int i;
      for(i=0; i < dim; i++)
      {
        printf("%d ", array_uni[i]);
      }
    }
    
    void stampa_array_bid(ind dimx, int dimy, int array_bid[][6]);
    {
      int i, j;
      for(i=0; i < dimx; i++)
      {
        for(j=0; j < dimy; j++)
        {
          printf("%d ", array_uni[i][j]);
        }
      
        printf("n");
      }
    }
    Ho provato simulare queste istruzioni mentalmente(ancora devo avvicinarmi ad un IDE ) e proprio non riesco a comprendere il fatto del perchè la seconda dimensione dell'array va per forza dichiarata..
    Mi spiego meglio; i parametri che servono a dimensionare l'array non sono gia specificati dagli argomenti della funzione (dimx, dimy)?
    Quel "[6]" che viene specificato è un numero messo li a caso o ha un senso?
    La seconda dimensione non dovrebbe acquisire il valore della variabile dimy tramite l'iterazione data dal ciclo for nidificato?

    Mi scuso per essermi dilungato un po troppo ma ce la sto mettendo tutta e ci tengo davvero ad essere il piu preciso possibile ed a farmi capire..

    Grazie a chiunque vorrà rispondermi.

  2. #2
    1) Il confronto con 1 non coinvolge la variabile valore, ma il valore restituito dalla funzione scanf.
    La scanf restituisce un numero pari al numero di campi correttamente acquisiti, pertanto, se l'acquisizione è andata bene, in questo caso deve restituire 1, se si ottengono altri valori probabilmente l'utente ha inserito caratteri non numerici. Pertanto la condizione "complessiva" del while risulta essere di continuare finché l'input avviene correttamente (scanf("%d", &valore) == 1) e ( && ) il valore inserito è diverso da zero (valore!=0).

    2) Gli array multidimensionali in memoria sono "linearizzati"; immaginati l'array come una tabella di numeri: per poterla memorizzare in una struttura sequenziale quale la memoria del computer, la dovrai necessariamente gestire in una dimensione, ad esempio concatenando tutte le righe, in modo da avere un'unica lunghissima riga che viene mantenuta in memoria.

    codice:
    +----+----+----+----+----+
    | 11 | 12 | 13 | 14 | 15 |
    +----+----+----+----+----+
    | 21 | 22 | 23 | 24 | 25 |
    +----+----+----+----+----+
    | 31 | 32 | 33 | 34 | 35 |
    +----+----+----+----+----+
    | 41 | 42 | 43 | 44 | 45 |
    +----+----+----+----+----+
    | 51 | 52 | 53 | 54 | 55 |
    +----+----+----+----+----+
    
               |||   
             \\|||//
              \\|//
               \|/
                V
    
    +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
    | 11 | 12 | 13 | 14 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 41 | 42 | 43 | 44 | 45 | 51 | 52 | 53 | 54 | 55 |
    +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
    (un ragionamento analogo si applica anche per gli array con più dimensioni)

    Ora che l'array è rappresentato in questa maniera, si pone un problema: per potervi accedere con gli stessi indici che userei sulla sua versione bidimensionale mi è necessario sapere quanto è lunga una riga; infatti per raggiungere l'elemento di coordinata (x, y) sulla tabella bidimensionale devo di fatto andare a prendere l'elemento y*lunghezza_riga+x nella sua versione "sequenzializzata".
    Se sei nello scope in cui è stato dichiarato l'array, il compilatore già dispone di questa informazione; se però vuoi passare questo array ad un'altra funzione questa informazione deve essere resa nota anche all'interno di essa, altrimenti risulta impossibile determinare l'offset dell'elemento desiderato partendo da coordinate bidimensionali.
    Un ragionamento analogo si applica con array di più dimensioni, per i quali è necessario specificare tutte le dimensioni tranne l'ultima (che non rientra all'interno della mia formula di passaggio dagli indici in N dimensioni all'indice sull'array sequenzializzato). Questo dunque è il motivo per cui è necessario specificare tale informazione nel prototipo della funzione: altrimenti il compilatore non saprebbe come generare il codice per accedere agli elementi dell'array.
    Il fatto che tu stia passando queste informazioni anche come parametri non è sufficiente, dato che il compilatore non sa che quelle variabili contengono le dimensioni dell'array, e quindi non può sfruttarle autonomamente.

    D'altra parte, se le dimensioni dell'array possono variare a runtime, è sempre possibile passare semplicemente un puntatore al primo elemento e le varie dimensioni come parametri, e costruirsi "a mano" gli offset dal primo elemento quando si vuole accedere ai vari elementi dell'array.
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Innanzi tutto ti ringrazio per la risposta, esaustiva ed immediata

    Devo dire che ora le mie curiosità sono aumentate esponenzialmente e mi rendo conto che una guida base è solo il primo piccolo passo..

    Il punto 1 l'ho recepito alla perfezione, non conoscendo ancora bene le varie sintassi ero convinto che l'espressione (scanf("%d", &valore) == 1 && valore != 0) avesse un significato diverso, invece adesso risulta tutto chiarissimo, insomma ==1 sta a significare che la funzione scanf restituisce valore true, e non ha invece nulla a che fare con il valore della variabile..

    Per quanto riguarda il punto 2 invece ammetto di aver capito solo in parte, o meglio, la spiegazione è molto chiara ma allo stesso tempo abbastanza tecnica e tieni conto che da questo punto di vista non ho alcun rudimento..

    Il concetto che descrive la logica di interpretaione degli array a livello macchina è chiara e ti ringrazio per le delucidazioni che ovviamente ignoravo completamente anche se poi a pensarci bene è abbastanza logico..(colsenno di poi ovviamente )

    Concetti come "scope" o "offset" li ignoro completamente..I puntatori invece devo ancora affrontarli quindi per ora paziento..

    Insomma, per riassumere quello che ho capito parlando proprio ter a ter(per questo mi scuso in anticipo con tutti ): l'array che è visto dalla macchina per forza su una sola dimensione ha bisogno di un parametro per tutte le altre dimensioni in maniera da far capire al compilatore quando dover "andare a capo"(cambiare riga).
    Ma quello che mi chiedo io, nell'esempio postato precedentemente , il valore 6 è casuale? cioè si tratta di una convenzione? Potevo metterci pure 1, tanto poi in base all'argomento dimy la dimensione dell'array sarebbe comunque cambiata?

    Non so se riesco a spiegarmi..Grazie

  4. #4
    Originariamente inviato da Yellowline
    Innanzi tutto ti ringrazio per la risposta, esaustiva ed immediata

    Devo dire che ora le mie curiosità sono aumentate esponenzialmente e mi rendo conto che una guida base è solo il primo piccolo passo..

    Il punto 1 l'ho recepito alla perfezione, non conoscendo ancora bene le varie sintassi ero convinto che l'espressione (scanf("%d", &valore) == 1 && valore != 0) avesse un significato diverso, invece adesso risulta tutto chiarissimo, insomma ==1 sta a significare che la funzione scanf restituisce valore true, e non ha invece nulla a che fare con il valore della variabile..
    Occhio: scanf non restituisce true o false - che, per inciso, in C "classico" (C89) non esistono -, ma il numero dei campi correttamente convertiti. Se fosse stato scanf("%d %d", &valore1, &valore2) il numero con cui confrontare il valore restituito sarebbe stato 2.
    Concetti come "scope" o "offset" li ignoro completamente..I puntatori invece devo ancora affrontarli quindi per ora paziento..
    Lo "scope" è l'area di visibilità di una variabile. Se una variabile è dichiarata dentro una funzione, il suo scope è la funzione in questione, infatti da "fuori dalla funzione" non è possibile vederne le variabili locali.
    Offset è come dire "sfasamento", "scostamento". In sostanza, in questo caso, di quanto devo andare avanti dall'inizio dell'array per raggiungere l'elemento che mi interessa.
    Insomma, per riassumere quello che ho capito parlando proprio ter a ter(per questo mi scuso in anticipo con tutti ): l'array che è visto dalla macchina per forza su una sola dimensione ha bisogno di un parametro per tutte le altre dimensioni in maniera da far capire al compilatore quando dover "andare a capo"(cambiare riga).
    Esatto.
    Ma quello che mi chiedo io, nell'esempio postato precedentemente , il valore 6 è casuale? cioè si tratta di una convenzione? Potevo metterci pure 1, tanto poi in base all'argomento dimy la dimensione dell'array sarebbe comunque cambiata?
    No, è proprio qui il punto. L'array che tu passi a quella funzione come argomento deve avere necessariamente quella dimensione, altrimenti ti viene generato un errore in fase di compilazione; la funzione infatti si aspetta di lavorare con un array con quelle dimensioni (e dunque genera il codice per accedere ai vari elementi in una certa maniera), passarle un array con dimensioni diverse ti farebbe ottenere risultati errati (ad esempio la funzione cercherebbe di accedere ad un array che ha righe lunghe 8 "credendo" che le righe siano lunghe 6, pescando quindi numeri sbagliati).
    Come dicevo prima, se vuoi mantenere a runtime la flessibilità su tutte le dimensioni devi passare un puntatore al primo elemento, la lunghezza della riga (ed eventualmente delle altre dimensioni per array multidimensionali) e calcolarti "a mano" l'offset dal primo elemento per raggiungere l'elemento che ti interessa.

    Comunque, ti consiglio di recuperare un libro "vero", a mio avviso i tutorial non sono un granché per imparare un nuovo linguaggio (e quello di questo sito non è neanche fatto troppo bene).
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Perfetto, adesso tutto torna..Ti ringrazio ancora, anche per avermi ulteriormente specificato come si comporta la funzione scanf nell'esempio..
    Anche il discorso degli array, un po complicato all'inizio, devo familiarizzare un po, ora molto piu chiaro..
    Grazie per la pazienza..

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

  7. #7
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,465

    Moderazione

    Originariamente inviato da Yellowline
    Ne approfitto che chiedere un ulteriore chiarimento inerente ad un altro capitolo onde evitare di aprire un altro 3d dato che mi rendo conto che ai piu potrebbe risultare fin troppo noioso leggere discussioni simili...
    In futuro, come da Regolamento, apri discussioni separate per problemi o domande non correlati tra loro.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

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 © 2025 vBulletin Solutions, Inc. All rights reserved.