[C] Esercizio con aritmetica dei puntatori

di il
14 risposte

[C] Esercizio con aritmetica dei puntatori

Salve sono messy e frequento il primo anno di informatica presso uniparthenope, sono nuovo del forum. Ho letto le regole e spero di non vìolarne alcuna con questo post.
Allora devo fare questo esercizio:
" Creare una matrice NxM di interi(con N e M definiti dall'utente). Impostare la matrice con tutti gli elementi a '0'. Definire un puntatore ad interi che punti all'elemento (0,0) della matrice. Scrivere un algoritmo che sposti il puntatore di i caselle in basso e di j caselle a destra ( dove i e j sono numeri casuali compre tra 0 e N e tra 0 e M). Ripetere l'operazione di spostamento del puntatore un numero di volte definito dall'utente e incrementare di 1 ogni elemento della matrice che viene puntato dal puntatore. Stampare le coordinate di tutti i movimenti del puntatore e la matrice ottenuta alla fine degli spostamenti del puntatore."

Il problema è che non mi fa modificare gli elementi della matrice quando creo un nuovo puntatore con coordinate random.
Il più delle volte quando ristampo la matrice dopo gli spostamenti visualizzo indirizzi al posto di numeri nella matrice.

Questo è il codice:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
int main()
{
    int n,m,i,j;
    int k,g=3; // g è il numero di volte in cui si deve spostare il puntatore
    int ir,jr;
    int *pr;
    srand(time(NULL));
 
    printf("\nInserire numero righe: ");
    scanf("%d",&n);
    printf("\nInserire numero colonne: ");
    scanf("%d",&m);
    int matr [n][m];
    int *p;
    p=&matr[0][0];
 
    // INIZIALIZZA MATRICE
    for(j=0;j<m;j++){
        for(i=0;i<n;i++){
            *(p+i)=0;
        }
    }
 
    // STAMPA MATRICE
    for(j=0;j<m;j++){
        for(i=0;i<n;i++){
            printf("\t%d",*(p+i));
        }
        printf("\n\n");
    }
 
    // NUOVO PUNTATORE CHE PUNTA A UNA POSIZIONE CASUALE DELLA MATRICE
    for(k=0;k<g;k++){
    ir= rand()%(n);
    jr=rand()%(m);
    printf("\n%d,%d",ir,jr);
    pr=&matr[ir][jr];
    *pr+=1;
 
   }
 
   // STAMPA MATRICE
    for(j=0;j<m;j++){
        for(i=0;i<n;i++){
            printf("\t%d",*(p+i));
        }
        printf("\n\n");
    }
 
    return 0;
}
Ringrazio anticipatamente a chi si impegnerà a darmi una mano.
-messy

14 Risposte

  • Re: [C] Esercizio con aritmetica dei puntatori

    Il problema è che quando stampi la matrice stampi sempre la prima riga e nei for per inizializzare e stampare, dovresti mettere j<n e i<m perché prima prendi una riga e la scorri in tutte le sue colonne, poi prendi un'altra riga ecc, mi sa che hai scambiato righe e colonne infatti le stampa al contrario. se gli dici 1 riga e 5 colonne ti fa 5 righe e 1 colonna
  • Re: [C] Esercizio con aritmetica dei puntatori

    Ho visto avevo fatto un po di confusione con gli indici ma il problema rimane.
    CODICE AGGIORNATO:
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    int main()
    {
        int n,m,i,j;
        int k,g=3; // g è il numero di volte in cui si deve spostare il puntatore
        int ir,jr;
        int *pr;
        srand(time(NULL));
    
        printf("\nInserire numero righe: ");
        scanf("%d",&n);
        printf("\nInserire numero colonne: ");
        scanf("%d",&m);
        int matr [n][m];
        int *p;
        p=&matr[0][0];
    
        // INIZIALIZZA MATRICE
        for(i=0;i<n;i++){
            for(j=0;j<m;j++){
                *(p+j)=0;
            }
        }
    
        // STAMPA MATRICE
        for(i=0;i<n;i++){
            for(j=0;j<m;j++){
                printf("\t%d",*(p+j));
            }
            printf("\n\n");
        }
    
        // NUOVO PUNTATORE CHE PUNTA A UNA POSIZIONE CASUALE DELLA MATRICE
        for(k=0;k<g;k++){
        ir= rand()%(n);
        jr=rand()%(m);
        printf("\n%d,%d",ir,jr);
        pr=&matr[ir][jr];
        *pr+=1;
    
       }
    
       // STAMPA MATRICE
        for(i=0;i<n;i++){
            for(j=0;j<m;j++){
                printf("\t%d",*(p+j));
            }
            printf("\n\n");
        }
    
        return 0;
    }
    
    Non riesco a capire dov'è che sbaglio, o se funziona proprio diversamente da come sto gestendo i puntatori e matrice.
    Allegati:
    21095_4e1650148764ed503cfcf6a87b7df9ba.jpg
    21095_4e1650148764ed503cfcf6a87b7df9ba.jpg

    21095_d9428bfe4fefe7ef882c23a3151a4258.jpg
    21095_d9428bfe4fefe7ef882c23a3151a4258.jpg
  • Re: [C] Esercizio con aritmetica dei puntatori

    Sbagli a stamparla. Stampi sempre la prima riga
  • Re: [C] Esercizio con aritmetica dei puntatori

    Non riesco a capire come fare diversamente, puoi scrivermi la porzione di codice esatta.
  • Re: [C] Esercizio con aritmetica dei puntatori

    Purtroppo coi puntatori sono una frana, ma credo di avere la soluzione. Provo a spiegartela senza darti direttamente il codice: tu nei for usi due cicli, quindi ripeti n volte una cosa ripetuta per m volte. Però se ragioni sui cicli che usi, il secondo ciclo viene ripetuto n volte, senza però che all'interno del secondo ciclo ci sia un'influenza di i. Quello che ti voglio far capire, è che la prima volta che viene eseguito il ciclo grande, quello piccolo parte da 0 e arriva a m, ma la seconda volta, riparte di nuovo da 0 e arriva di nuovo a m, senza che cambi nulla. In pratica il ciclo grande, quello di n, non influisce minimamente su quello che stampi o inizializzi. Comunque questa cosa è molto più facile da capire senza i puntatori, però se devi usarli, allora cerca di trovare un modo per usare il for grande dentro il for piccolo
  • Re: [C] Esercizio con aritmetica dei puntatori

    Allora, io dalle mie modeste conoscenze so che una matrice viene allocata in memoria come un array 1D. Quindi praticamente tu dici che facendo i due cicli in quel modo non scorre l' "array" da 0 a n*m?
  • Re: [C] Esercizio con aritmetica dei puntatori

    Ho trovato la soluzione al problema su un pdf della professoressa. Nell'inizializzazione e nella stampa uso *(p+num_colonne*i+j). Vorrei capire perchè e come funziona.
    Codice:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    int main()
    {
        int n,m,i,j;
        int k,g; // g è il numero di volte in cui si deve spostare il puntatore
        int ir,jr;
        int *pr;
        srand(time(NULL));
    
        printf("\nInserire numero righe: ");
        scanf("%d",&n);
        printf("\nInserire numero colonne: ");
        scanf("%d",&m);
        int matr [n][m];
        int *p;
        p=&matr[0][0];
    
    
        // INIZIALIZZA MATRICE
        for(i=0;i<n;i++){
            for(j=0;j<m;j++){
                *(p+m*i+j)=0;
    
            }
        }
    
        // STAMPA MATRICE
        for(i=0;i<n;i++){
            for(j=0;j<m;j++){
                printf("\t%d",*(p+m*i+j));
            }
            printf("\n\n");
        }
        // scegli quante volte vuoi fare spostamenti
        printf("\nInserisci numero di spostamenti: ");
        scanf("%d",&g);
        // NUOVO PUNTATORE CHE PUNTA A UNA POSIZIONE CASUALE DELLA MATRICE
        for(k=0;k<g;k++){
        ir= rand()%(n);
        jr=rand()%(m);
        printf("\n%d,%d",ir,jr);
        pr=&matr[ir][jr];
        *pr+=1;
    
       }
    
       // STAMPA MATRICE
        for(i=0;i<n;i++){
            for(j=0;j<m;j++){
    
                printf("\t%d",*(p+m*i+j));
    
            }
            printf("\n\n");
        }
    
        return 0;
    }
    
  • Re: [C] Esercizio con aritmetica dei puntatori

    Perché se tu usi p+j, inizializzi per n volte la prima riga della matrice. Perché a ogni ciclo grande, j viene resettata e alla fine rimane sempre p+0 p+1p+2...p+(m-1) Invece così arrivi più avanti fino all'ultima riga e inizializzi e stampi tutta la matrice. Basta che simuli mentalmente l'avanzare di i e j e calcoli la somma. Vedrai che prima veniva sempre da 0 a m-1 quindi solo la prima riga
  • Re: [C] Esercizio con aritmetica dei puntatori

    Penso si possa eliminare il doppio ciclo "for":
    ......
      // INIZIALIZZA MATRICE
        for(i=0;i<(n*m);i++){
            *(p + i)=0;
        } 
    
        // STAMPA MATRICE
        for(i=0;i<(n*m);i++){
            printf("\t%d", *(p+i));
            if (((i+1) % m) == 0)
                printf("\n\n");
        } 
    ......
    ......
    // STAMPA MATRICE
        for(i=0;i<(n*m);i++){
            printf("\t%d", *(p+i));
            if (((i+1) % m) == 0)
                printf("\n\n");
        }
    ......
    Forse si può anche eliminare il secondo Puntatore:
    ......
    ......
    for(k=0;k<g;k++){
        ir= rand()%(n);
        jr=rand()%(m);
        printf("\n%d,%d",ir,jr);
    
        *(p+((ir*m)+jr)) +=1;
    
       }
    ......
    ......
  • Re: [C] Esercizio con aritmetica dei puntatori

    Si può accedere linearmente alla finta matrice solo quando viene allocata staticamente. Cercare "Row Major Order" per saperne di più.
  • Re: [C] Esercizio con aritmetica dei puntatori

    Quindi cosa è corretto fare? Quello che ho fatto io o quello che ha postato @vuott?
    Ho visto il metodo "row major order", è il metodo che usa il C, (a00,a01,..,a0n,a10,a11,...,a1n,...,...,).
  • Re: [C] Esercizio con aritmetica dei puntatori

    ANDPRI ha scritto:


    Perché se tu usi p+j, inizializzi per n volte la prima riga della matrice. Perché a ogni ciclo grande, j viene resettata e alla fine rimane sempre p+0 p+1p+2...p+(m-1) Invece così arrivi più avanti fino all'ultima riga e inizializzi e stampi tutta la matrice. Basta che simuli mentalmente l'avanzare di i e j e calcoli la somma. Vedrai che prima veniva sempre da 0 a m-1 quindi solo la prima riga
    Grazie ANDPRI, ho capito cosa faceva con *(p+i) non andava avanti ritornava a scrivere sempre sulla prima riga.
    Ora vorrei capire cosa è meglio o giusto usare perche ho visto un paio di metodi.
  • Re: [C] Esercizio con aritmetica dei puntatori

    Ha ragione @vuott. Partendo da quel che ha scritto lui arrivi alla soluzione. L'unica cosa è che % e / sono troppo operazioni troppo dispendiose e nella fattispecie si possono evitare cerccando alcuni post di M.A.W. 1968 sulle proprietà delle matrici, qui e sugli altri forum più conosciuti.
  • Re: [C] Esercizio con aritmetica dei puntatori

    Grazie a tutti per l'aiuto, ho capito meglio l'uso dei puntatori, siete stati gentilissimi.
Devi accedere o registrarti per scrivere nel forum
14 risposte