Portál AbcLinuxu, 10. května 2025 05:09

Dotaz: Pointer k multidim. array ako parameter pre funkciu (C++)

26.10.2010 00:33 PeterS. | skóre: 10
Pointer k multidim. array ako parameter pre funkciu (C++)
Přečteno: 466×
Odpovědět | Admin

Ahoj
toto je otázka ktorá suvisí s mojimi predošlými dvoma otázkami, snažím sa na nete najisť nejaký návod ale nejako mi to nejde.
Mám array, povedzme image_ar[width][height][4], pričom výška a šírka (obrázka) nie je pevne daná, záleží od obrázka ktorý programu predhodím.
Potrebujem tento array dať ako parameter funkcii - ale ako pointer - aby sa zmeny urobené vo vnútri funkcie odrazili aj v main.

našiel som napríklad tento príklad:

   // three dimensions with pointer
   void function(int (*a)[20][30]);
   int array[10][20][30];
   function(array);


ale jednak mi nie je jasné, ako to urobiť, keže ja vopred prvý a druhý rozmer array nepoznám a potom neviem ako by som mal s daným array pracovať. Čítať pozície a vkladať do pozícií...

Takže ešte raz prosím o pomoc a navedenie

vďaka


Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

26.10.2010 05:04 zulu
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Odpovědět | | Sbalit | Link | Blokovat | Admin
toto je otázka ktorá suvisí s mojimi predošlými dvoma otázkami
Podle nich bych řekl, že žádné šaškování s polem nepotřebuješ a, jak ti Messa napsal hned v první odpovědi, vystačíš s funkcemi CImg.
#include "cimg/cimg.h"
#include "cimg/examples/img/CImg_demo.h"

using namespace cimg_library;

void func(CImg<unsigned char> &img, int x, int y)
{
  img(x,y) ^= 255;
}

int main()
{
  CImg<unsigned char> image(data_foot,200,200,1,3,false);
  CImgDisplay disp(image);
  while (!disp.is_closed()) {
    disp.wait();
    if (disp.button()) {
      func(image, disp.mouse_x(), disp.mouse_y());
      disp = image;
    }
  }
  return 0;
}
26.10.2010 08:16 PeterS. | skóre: 10
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
No cimg umožnuje prave ukladanie iba integerov 0-255, ja si RGB hodnoty vytiahnem, aplikujem gamu a konvertujem na rozsah 0-1 - a povedzme po dalších operáciach sa tieto môžu dostať do rozsahu povedzme na -0.5 - 1.5. Takže potrebujem aj ten Cimg obrázok - ako zdroj dat, ale pracovné dáta by boli v tejto multidimenzionalnej array... a na konci by sa zase konvertovali do rozsahu 0-255 a uložili ako obrazok...
26.10.2010 10:46 zulu
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Odpovědět | | Sbalit | Link | Blokovat | Admin
Fajn, tak třeba takhle:
class mydata
{
  float *data;
  unsigned dimx, dimy, dimz;
public:
  mydata(unsigned dx, unsigned dy, unsigned dz)
  {
    dimx = dx; dimy = dy; dimz = dz;
    data = new float[dimx * dimy * dimz];
  }
  ~mydata()
  {
    delete[] data;
  }
  float& operator()(unsigned x, unsigned y, unsigned z)
  {
    return data[y*dimx + x*dimz + z]; // toto je teda asi to, na co ses ptal
  }
};

void func(mydata &d)
{
  float a = d(0,0,0);
  d(0,0,0) = a;
}

int main()
{
  unsigned sirka = 10, vyska = 10;
  mydata d(sirka, vyska, 4);
  func(d);
}
27.10.2010 08:36 PeterS. | skóre: 10
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)

Takže nakoniec som sa rozhodol že to skusim s týmto kódom, vyzerá že to funguje, ale mám otázku ku 'unsigned sirka = 10, vyska = 10' - dobre tomu rozumiem, že výška a šírka môže byť iba do 255?
Ked som do func dal toto:

void func(mydata &d)
{ 
 d(500,10,5)=0.6;        // treti parameter akceptovalo 5 ????
 cout << d(500,10,5); 
 } 

int main()
{
 unsigned sirka = 1000, vyska = 10; // unsigned vs 1000 ????
 mydata d(sirka, vyska, 4);
... }


tak nerozumiem prečo to funguje, vid komentáre pri kode...

Keby si sa mi vedel ku tomu vyjadriť - aby som nezačal stavať ten program na niečom čo nepracuje korektne a aby som nemusel neskôr to komplikovane meniť....


Inak, nemal by sa tam niekde vyskytovať takéto niečo: 'x+sirka*y+sirka*vyska*z'. Máš tam nejaké vzorce ale celkom nerozumiem čo majú robiť...

27.10.2010 09:03 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)

A proč by to fungovat nemělo? Když si nezkontrolujete meze sám, nikdo to za vás neudělá. Ale stejně pořád nechápu, proč tak zarputile trváte na použití pole pro něco, k čemu se vůbec nehodí (reprezentace pixelu). Pokud se chcete C++ opravdu naučit, bez struktur a tříd to nepůjde.

Inak, nemal by sa tam niekde vyskytovať takéto niečo: 'x+sirka*y+sirka*vyska*z'. Máš tam nejaké vzorce ale celkom nerozumiem čo majú robiť...

Ano, ten index prvku počítaný jako y*dimx + x*dimz + z je samozřejmě nesmysl, buď by tam mělo být x*dimy*dimz + y*dimz + z (po řádcích) nebo y*dimx*dimz + x*dimz + z (po sloupcích). To, co navrhujete vy, by sice fungovalo také, ale považoval bych za vhodnější, aby hodnoty jednoho pixelu byly pohromadě (pokud už tedy z nějakého důvodu trváte na reprezentaci složek pixelu polem).

27.10.2010 09:45 PeterS. | skóre: 10
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)

ako som už povedal - možno ste to prehliadli - C++ sa venujem týžden, jediný iný jazyk ktorý poznám je python a aj ten tak na strednej úrovní. Triedam proste nerozumiem, určite by bolo dobre ich ovládať a raz možno budem, ale teraz potrebujem niečo čo budem mať plne pod kontrolou a budem tomu rozumieť. Ten váš navrh som vybral preto že mu aspon tak na 30 % rozumiem. Dokonca by som ho chcel zmodifikovať takto:

{
if (x >= dimx) {
cout << "Out of scope: x >= dimx" << "\n";
exit (1) ;}
else if (y >= dimy) {
cout << "Out of scope: y >= dimy" << "\n";
exit (1) ;}
else if (z >= dimz) {
cout << "Out of scope: z >= dimz" << "\n";
exit (1) ;}
return data[x*dimy*dimz + y*dimz + z];
}

Skusim isť zatiaľ touto cestou... a dufam že sa už konečne dostanem ku tomu čo ma zaujíma - práca s obrázkami....

27.10.2010 10:01 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)

Jen pro pořádek: to není můj návrh. :-)

A technická poznámka: chybová hlášení patří na chybový výstup (std::cerr), ne na standardní (std::cout).

27.10.2010 10:26 PeterS. | skóre: 10
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)

cerr som upravil, inak technická otázka, hodnoty pre stlpce/riadky/"vrstvy" ak je veľkost definovaná ako 10 su v rozmedzi 1-10. Nie 0-9, správne? Ale v "data" sa ukladajú od nuly, teda tento posledný riadok som upravil tiež:

  {
if (x > dimx || x == 0) {
cerr << "Out of scope: x = " <<< "\n";
exit (1) ;}
else if (y > dimy || y == 0) {
cerr << "Out of scope: y = " << y << "\n";
exit (1) ;}
else if (z > dimz || z == 0) {
cerr << "Out of scope: z = " <<< "\n";
exit (1) ;}
return data[x*dimy*dimz + y*dimz + z-1]; // tu som pridal -1 !
}

Vyzera to správne?
27.10.2010 10:33 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
To samozřejmě záleží na tom, co přesně má znamenat x a y. Pokud to je od nuly do w-1 a h-1, pak je to v pořádku, pokud ne, musíte tu jedničku odečíst. Co se "z souřadnice", tedy barevných složek pixelu, týká, k tomu už jsem své řekl tolikrát, že mne to už opravdu nebaví opakovat.
27.10.2010 10:54 PeterS. | skóre: 10
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
ta "-1" sa netýka špecificky z-tka. Ide oto že ak data ma veľkosť x*y*z, tak pixel uplne prvý pixel v prvej farbe ( 1,1,1 ) ukladá svoju hodnotu do data[0] (bez ohľadu na vzorec), a pixel x,y,z ukladá svoju hodnotu do poslednej pozície v data a to je práve data[x*y*z-1].

Len sa snažím pochopiť ako celá ta schéma pracuje. Co je triviálne pre vás nie je triviálne aj pre mna.

A FAKT som vdačný za pomoc...
26.10.2010 13:11 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Odpovědět | | Sbalit | Link | Blokovat | Admin

To nepůjde, neznámý může být pouze jeden rozměr pole, a to ten první. Jinak by volaná funkce nevěděla, jak adresovat jednotlivé prvky pole, protože k tomu potřebuje znát všechny rozměry kromě prvního.

Jednou možností je předat to takto:

  void fce(float (*a)[4], unsigned w, unsigned h)

a ve funkci index pole a dopočítávat. Případně si rozmyslete, jestli nebude lepší si na to rovnou nenapsat třídu, např. nějak takto (při reprezentaci po řádcích):

struct pixel {
  float r;
  float g;
  float b;
  float a;
};

class image {
protected:
  pixel* data;

public:
  unsigned width;
  unsigned height;

  image(unsigned w, unsigned h);
  ~image() { delete [] data; }

  pixel*& operator [](unsigned y) { return (data + y*width); }
};

image::image(unsigned w, unsigned h)
  : width(w), height(h)
{
  data = new pixel[w*h];
}
26.10.2010 13:12 Sten
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Odpovědět | | Sbalit | Link | Blokovat | Admin
Jednoduše předejte referenci (je to C++, tak žádný pointer!) na trojdimenzionální pole:
void function(int*** &a)
Samozřejmě musíte potom ještě nějak funkci předat rozměry.

Pokud byste to ale chtěl opravdu C++, tak si to pole obalíte nějakým objektem, které bude spravovat rozměry i alokace:
#include <boost/noncopyable.hpp>
#include <boost/scoped_array.hpp>
#include <stdexcept>


class Image
    : private boost::noncopyable
{
public:
    Image(const std::size_t width,
          const std::size_t height)
        : width(width)
        , height(height)
        , data(new int[width * height * 4])
    {}


    class Line;


    class Pixel
    {
    public:
        Pixel(Line &line,
              const std::size_t column)
            : line(line)
            , column(column)
        {}


        int& operator [](const std::size_t color)
        {
            if (color >= 4) {
                throw std::range_error("color >= 4");
            }
            return this->line.image[(this->line.line * this->line.image.width + this->column)
                    * 4 + color];
        }


        Line &line;
        const std::size_t column;
    };



    class Line
    {
    public:
        Line(Image &image,
             const std::size_t line)
            : image(image)
            , line(line)
        {}


        Pixel operator [](const std::size_t column)
        {
            if (column >= this->image.width) {
                throw std::range_error("column >= image.width");
            }
            return Pixel(*this, column);
        }


        Image ℑ
        const std::size_t line;
    };


    Line operator [](const std::size_t line)
    {
        if (line >= this->image.height) {
            throw std::range_error("line >= image.height");
        }
        return Line(*this, line);
    }


    const std::size_t width;
    const std::size_t height;

protected:
    boost::scoped_array<int> data;
};
26.10.2010 15:16 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Pozor, konstrukce "int*** &a" není reference na třírozměrné pole. I třírozměrné pole je pořád jen posloupnost za sebou narovnaných hodnot. To, co jste napsal vy, je reference na pointer na pointer na pointer na int.
26.10.2010 16:04 Sten
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Ano, samozřejmě je nutné to potom správně převést pomocí reinterpret_cast podle konstantních parametrů, které by měla funkce dostat (nebo se někde jinde dozvědět):
void funkce(int ***&a,
            const std::size_t width,
            const std::size_t height,
            const std::size_t x,
            const std::size_t y)
{
    int (&image)[width][height][4] = *reinterpret_cast<int(*)[width][height][4]>(a);
    ·
    ·
    ·
}
26.10.2010 16:08 Sten
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Koukám, že mi tam chybí v tom reinterpret_cast ampersand, má tam být
*reinterpret_cast<int(*)[width][height][4]>(&a);
26.10.2010 16:33 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Když už to chcete tak jako tak castovat, tak je jedno, na co je to vlastně pointer. Já chtěl jen upozornit, že třírozměrné pole je v podstatě zase jako pointer na typ samotný, ne pointer na pointer (na pointer).
26.10.2010 14:21 PeterS. | skóre: 10
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Odpovědět | | Sbalit | Link | Blokovat | Admin

diky za odpovede, tie navrhovane riešenia sú pre mna príliš komplikované, rozhodol som sa že to budem riešiť styrmi jednodimenzionálnymi arrayami a funkcii posuniem aj x*y rozmery obrázka a nejako si s tým poradím. Asi tak nejako (pre jednu array):

void populate (float* aaa, int img_size) {
}

float * ar_R;        
ar_R = new float[w_img_size];        
populate (&ar_R[0],img_size);    // w_img_size je velkost array

V každom prípade vďaka za ochotu...

26.10.2010 15:17 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Ve výsledku vlastně děláte totéž co my. Rozdíl je v tom, že vy budete muset tu "špinavou práci" s počítáním indexu dělat při každém použití znovu, zatímco u našich "příliš komplikovaných" řešení si ji uděláme jednou zvlášť a pak už to jen používáme.
26.10.2010 15:19 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Ještě bych dodal, že rozdíl poznáte hlavně v okamžiku, kdy se z nějakého důvodu rozhodnete formát dat změnit - my si to opravíme na jednom místě, vy to budete muset udělat všude, kde tu datovou strukturu používáte.
26.10.2010 15:22 zulu
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Komplikované to není, jen jsi to nepochopil. Data obrázku 3x3:
A1,A2,A3
B1,B2,B3
C1,C2,C3
prostě vypadají takhle:
A1,A2,A3,B1,B2,B3,C1,C2,C3
A ty jen musíš přepočítat souřadnice na pozici v tom poli. Navíc tady už máš kód, se kterým nemusíš nic dělat a stačí ho obšlehnout.
Saljack avatar 26.10.2010 20:25 Saljack | skóre: 28 | blog: Saljack | Praha
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Odpovědět | | Sbalit | Link | Blokovat | Admin
Na tohle už bych si vyrobil objekt (strukturu), kam budeš moct všechno ukládat a budeš si z toho také ty data brát.
Sex, Drugs & Rock´n Roll.
27.10.2010 21:45 mato
Rozbalit Rozbalit vše Re: Pointer k multidim. array ako parameter pre funkciu (C++)
Odpovědět | | Sbalit | Link | Blokovat | Admin
Příloha:
caf,
osobne by som sa tiez priklonil k rieseniu, ze by si predaval fcii pointer na strukturu, ktora v sebe obsahuje potrebne data (pole + suradnice).
v prilohe som poslal kod, ako by som vytvaral dynamicke pole ja. m3d_action simuluje tvoj dotaz ako fcii predat maticu na menenie
dalo by sa to robit viacerymi sposobmi, toto je len ukazka

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.