Newsgroup: it.comp.lang.c
Titolo: Array mono trattati come bidimensionali

Salve,
desideravo porvi un quesito;
avendo
char scrn[320*200];
char sprt[16*16];
char *pScrn, *pSprt;
pScrn = scrn;
pSprt = sprt;
pSprt[0] = 1, pSprt[1] = 2, pSprt[2] = 3, pSprt[3] = 4;
memset(pScrn, 0, sizeof(scrn));
posX = 2;
posY = 2;
// come faccio a scrivere i valori di pSprt seguendo i posizionamenti di
// posX e posY?
// io ho fatto cosi' ma, logicamente, non tiene conto dei pos e quindi stampa i
// valori partendo sempre dai primi elementi di pScrn
  for (y=0; y<SPRY; y++)
    for (x=0; x<SPRX; x++)
      pScrn[SCRY*20+x]= pSprt[SPRX*x+y];
  return 0;
}
// grazie a tutti ;-)

      pScrn[SCRY*20+x]= pSprt[SPRX*x+y];
Immagino che SPRY e SPRX siano le dimensioni (rispettivamente y e x)
della versione bidimensionale dell'array sprt, per cui definisco allo
stesso modo per l'array scrn i due valori SCRX e SCRY.
for ( y = 0; y < SPRY; y++ ) {
     scrn_start = (y + posY) * SCRX + posX;
     sprt_start = y * SPRX;
     for ( x = 0; x < SPRX; x++ )
         pScrn[scrn_start + x] = pSprt[sprt_start + x];
}
Cosi` _dovrebbe_ andare. Non l'ho provato, ma l'ho dedotto disegnandomi
su carta i vari elementi in gioco e ragionandoci un po'.
Saluti,
Marco

 su carta i vari elementi in gioco e ragionandoci un po'.
Ciao Marco,
grazie infinite per la tua risposta ma non e' proprio quello che cercavo.
Attualmente sono arrivato a una soluzione piu' performante ma ancora errata
  for (y=0; y<SPRY; y++)
    for (x=0; x<SPRX; x++)
      pScrn[(SCRX*posY)+posX+x+(SCRY*posX)+posY+y]= pSprt[SPRX*y+x];
Credo che l'errore sia nella seconda parte della matrice pScrn.
Spero vi sia ancora qualcuno che non ha letto che sa come aiutarmi.
La funzione non e' altro che una funzione di blit che, per adesso, non usa la memcpy
grazie

 grazie infinite per la tua risposta ma non e' proprio quello che cercavo.
Allora non sono sicuro di aver capito quello che deve fare il tuo
codice: dai nomi scrn e sprt mi pare che siano uno "schermo" e uno
"sprite" e il tuo obiettivo sia quello di copiare lo sprite sullo
schermo in posizione posX e posY.
In questo caso, guarda bene il codice che ti ho mandato nella
precedente risposta, perche' e` quello che dovrebbe fare.
Saluti,
Marco

salvator...@gmail.com
 (salvo) wrote:

   pScrn = scrn + posY*320+posX;
   pSprt = sprt;
   for (y=0; y<16; y++, pScrn+=320-16)
     for (x=0; x<16; x++)
       *pScrn++ = *pSprt++;
-- 
Horst

        *pScrn++ = *pSprt++;
Ciao Horst,
la tua soluzione mi piace anche perche' ti muovi con i puntatori ma
non capisco perche' non funziona :-\

Marco Pallante <no_pallante_spam@no_wind.it_spam> wrote in message news:<Pine.WNT.4.61.0504081112430.2524@spira>...

Ciao Marco,
ti ringrazio ancora del tuo post, non ho provato il tuo codice perche'
non e', purtroppo, ottimizzato come vorrei renderlo io, cioe'
solamente con i 2 cicli for che mi danno la posizione esatta con
un'unica espressione (e' anche vero che l'ottimizzazione massima
l'avrei con un memcpy, ma non devo usarlo adesso).
In pratica quello che ho e' uno schermo con dimensioni SCRW e SCRH e
uno sprite con dimensioni SPRW e SPRH.
Questo sprite e' nelle posizioni posX e posY in pScrn.
Se, ad esempio, le posizioni sono posX=2 e posY=2 e lo schermo e'
SCRW=320 e SCRH=200 il risultato dovrebbe essere, dentro scrn[]:
sPsrt[0] nell'elemento 642 (se non ho sbagliato il calcolo
posY*SCRW+posX)
sPrst[1] nell'elemento 643
sPrst[2] nell'elemento 962
sPrst[3] nell'elemento 963
in modo da formare un quadrato
il codice completo e' questo:
<CODE>
#include <stdio.h>
#define SCRW  15
#define SCRH  10
#define SPRW  2
#define SPRH  2
// buffer che finge d'essere uno schermo
char scrn[SCRW*SCRH];
// buffer che finge d'essere uno sprite
char sprt[SPRW*SPRH];
int main(int argc, char *argv[])
{
  char *pScrn, *pSprt;
  char posX, posY;  // posizione x e y dello sprite
  int x, y;
  // setto la posizione dove disegnare lo sprite
  posX = 3;
  posY = 2;
  // punto ai primi elementi degli array
  pScrn = scrn;
  pSprt = sprt;
  // inserisco questi numeri cosi' capisco bene dove vengono copiati e
in
  // che sequenza
  pSprt[0] = 1, pSprt[1] = 2, pSprt[2] = 3, pSprt[3] = 4;
  // pulisco lo schermo
  memset(pScrn, 0, sizeof(scrn));
  for (y=0; y<SPRH; y++)
    for (x=0; x<SPRW; x++)
      pScrn[(SCRW+posY+y)+(SCRH+posX+x)*SPRW]= pSprt[SPRW*y+x];  //
errata!!!
  // stampo il contenuto del buffer pScrn
  for (x=0, y=0; x<SCRW*SCRH; x++, y++)
  {
    if (y == SCRW)
      y = 0, printf("\n");
    printf("%i ", pScrn[x]);
  }
  printf("\n");
  // se usi windows potrebbe servirti system("PAUSE");
  return 0;
}

 l'avrei con un memcpy, ma non devo usarlo adesso).
Bene, allora quello che avevo capito era corretto e il codice
che ho proposto dovrebbe farlo esattamente.
Poi, veniamo all'ottimizzazione.
Ricorda una cosa fondamentale (scusate le maiuscole)
    CODICE PIU` BREVE =/= CODICE PIU` EFFICIENTE
-Esempio:
Questo e` il tipo di codice che vorresti tu
     for ( i = 0; i < n; i++ )
         for ( j = 0; j < m; j++ )
             mat[i][j] = funzione_lentissima(i) + funzione(j);
Questo e` quello che propongo io
     for ( i = 0; i < n; i++ ) {
         temp = funzione_lentissima(i);
         for ( j = 0; j < m; j++ )
             mat[i][j] = temp + funzione(j);
     }
Nel primo caso funzione_lentissima() viene eseguita n*m volte,
nel secondo _solo_ n volte, cioe` il secondo codice e` m volte
piu` veloce del primo.
-Fine esempio.
Tornando a noi, il mio codice fa quello che ho cercato di esprimere
nell'esempio: prende una sottoespressione comune ad ogni iterazione
del ciclo interno e la calcola una volta sola, quindi in teoria e`
piu` efficiente.
Dico in teoria perche' non sto contando il compilatore. Con un
compilatore poco ottimizzante l'affermazione e vera. Un
compilatore piu` decente (probabilmente tutti quelli che trovi
in giro oggi), invece, farebbe automaticamente quello che io ho
fatto a mano, cioe` cercherebbe le sottoespressioni comuni e le
eseguirebbe il numero di volte strettamente necessario.
In piu` conta che gli otto byte che sembra io sprechi per tenere
dei valori temporanei probabilmente sarebbero usati anche da un
compilatore, che tende ad introdurre _molte_ variabili temporanee
quando traduce espressioni complesse.
Morale della favola: con i compilatori di oggi i due codici sarebbero
tradotti in sequenze di istruzioni molto simili, quindi ugualmente
efficienti.
La mia soluzione, pero`, mi sembra molto piu` leggibile di una che
piazza una mega-espressione nel ciclo interno, quindi a conti
fatti e` superiore... ma questa e` una questione di stile: a te
scegliere quello che preferisci (ma nota che un codice piu` pulito
tipo il mio _aiuta_ il compilatore nelle ottimizzazioni).
Saluti,
Marco
PS. Forse sono apparso un po' polemico. In tal caso mi scuso perche'
-- come sempre -- non sono affatto interessato ad alimentare flame.

 -- come sempre -- non sono affatto interessato ad alimentare flame.
nessuna polemica anzi sei stato molto eloquente :))
io pero' ho risolto cosi'
  for (y=0; y<SPRH; y++)
    for (x=0; x<SPRW; x++)
      pScrn[(x+Xpos)+(y+Ypos)*SCRW] = (char)*(pSprt++);
oppure la migliore (ma che non avevo domandato :) )
   for (y=0; y<SPRW*SPRH; y++)
     memcpy(pScrn[(x+Xpos)+(y+Ypos)*SCRW], (pSprt+y), sizeof(pSprt[0]));
grazie a tutti :)