transmitere tablou 2d ca 1d

Intrebari despre limbajul C++, standardul C++, STL, OOP in C++ sau alte subiecte nelegate de VisualC++
User avatar
zlatomir
Membru++
Membru++
Posts: 282
Joined: 04 Jul 2009, 23:59
Location: Arad
Contact:

Re: transmitere tablou 2d ca 1d

Post by zlatomir » 26 Jan 2011, 23:46

Codul ala ar trebui sa fie ceva de genul: bmp1[i*row +j ] = i+j;



viorel2005
Membru
Membru
Posts: 208
Joined: 24 May 2008, 09:41

Re: transmitere tablou 2d ca 1d

Post by viorel2005 » 27 Jan 2011, 03:45

Uita-te la apelul acesta:
memcpy(bmp2+i*3*sizeof(int),&(*bmp1), 3 ); //si nu ma leg de operatii inutile cu pointeri
Si la documentatia memcpy, si o sa vezi de ce nu merge bine.


Multumesc pentru sfat. Codul corect este urmatorul:

Code: Select all

for(int i=0;i<M;i++)
		memcpy(bmp2+i*N,&(*bmp1[i]),N*sizeof(int));

viorel2005
Membru
Membru
Posts: 208
Joined: 24 May 2008, 09:41

Re: transmitere tablou 2d ca 1d

Post by viorel2005 » 27 Jan 2011, 03:57

viorel2005 wrote:
Am recitit problema ta si ma ia cu ameteli!

daca apela afis2 astfel: afis2(&(*bmp1)), afisarea era corecta. Totusi, aces lucru ma costa M-1 apeluri de functie.

cu alte cuvinte... tu te gandeai la o solutie de genul
CODE: SELECT ALL
for (int i = 0; i < M; i++)
afis2(&(*bmp1))

Sorry, nu am cuvinte...


Ma gandeam sa evit o astfel de solutie. As fi vrut ceva de genul "afis2(bmp1)", dar am constatat ca nu se poate daca se foloseste alocarea dinamica.
Regret doar ca, in graba, nu am citit foarte atent ce vrei sa zici tu cu cele M apeluri... si ti-am dat un sfat badaran a.i. sa nu ai nevoie de atatea apeluri.
Silviu Ardelean wrote:
Viorel, daca tot vrei sa folosesti bmp1, de ce nu-l folosesti ca membru al unei clase sau membru global (daca nu lucrezi OOP)? Atunci in functia ta de afisare il apelezi direct fara a-l mai pasa la functie.


Anyway... renunta la abordarea cu array-ul 2D si rezolva-ti problema cu un banal array 1D via bmp1[i*row + coloum] = i+j;


Intr-adevar memcpy nu e cea mai eficienta functie pentru ce am nevoie. O copiere banala ar fi suficienta. Si asa o sa procedez.
Totusi, libraria JBIGKIt a fost scrisa in C. Integrarea unei librarii C in C++ folosind POO nu e asa usoara
cum pare la prima vedere. Incer sa o export intr-un dll, unde imi doresc sa am o functie care sa imi intoarca un array 1D de tip unsigned char,
care reprezinta imaginea compresata, precum si lungimea sa.Astfel evit Matlab-ul si imi pot face prelucrarea mai usoara.
Din fericire, ma ajuta si un cod open source de la adresa: http://trac.wxwidgets.org/raw-attachmen ... agjbig.cpp
O sa va tin curent cu evolutia proiectului, deoarece daca totul merge bine, o sa scriu un articol pe codexpert.
Ceea ce m-a oprit sa particip la ultimul concurs pe codexpert a fost aceasta librarie, care nu o integrasem inntr-o librarie dll sau lib.
Vroiam sa evit o solutie bazata pe WinExecute sau ceva asemanator.

Grunt
Junior
Junior
Posts: 3
Joined: 31 Aug 2009, 23:16
Judet: Iaşi

Re: transmitere tablou 2d ca 1d

Post by Grunt » 29 Jan 2011, 21:30

Silviu Ardelean wrote:Viorel, daca tot vrei sa folosesti bmp1, de ce nu-l folosesti ca membru al unei clase sau membru global (daca nu lucrezi OOP)? Atunci in functia ta de afisare il apelezi direct fara a-l mai pasa la functie.
lol ce?

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: transmitere tablou 2d ca 1d

Post by Silviu Ardelean » 29 Jan 2011, 22:06

Grunt wrote:
Silviu Ardelean wrote:Viorel, daca tot vrei sa folosesti bmp1, de ce nu-l folosesti ca membru al unei clase sau membru global (daca nu lucrezi OOP)? Atunci in functia ta de afisare il apelezi direct fara a-l mai pasa la functie.
lol ce?
Capish?

xxscorp
Junior
Junior
Posts: 7
Joined: 31 Jan 2011, 15:01
Judet: Timiş

Re: transmitere tablou 2d ca 1d

Post by xxscorp » 31 Jan 2011, 15:21

LLE definitiv: Imi cer scuze pentru acest useless junk. Daca incomodeaza, stergeti-l. Daca il lasati, sper sa serveasca macar ca o curiozitate. Conform wikipedia "As of Visual Studio 2010, there are no plans to support C99" si exact C99 ar fi fost necesar ca sa functioneze codul meu. Whatever...

LE: un cod frumos, dar se pare că nu-l va ajuta dacă nu trece la gcc.
Originalul:
Viorel2005, încearcă te rog codul de mai jos, poate te ajută cu ceva (vezi că trebuie maximă receptivitate!)

arr.cpp :

Code: Select all

#include <stdio.h>
#include <malloc.h>

void afisare(const char *buf, const unsigned int buflen)
{
    for (int i=0; i<buflen; i++)
        printf("%d ", (int) buf[i]);
    printf("\n");
}

int main()
{
    int N, M;
    N = 2;
    M = 3;
    unsigned int len = sizeof (int) * N * M;
    
    /* Cum se declara si initializeaza matricea */
    int (*a)[M] = (int (*)[M]) malloc(len);
            
    for (int i=0; i<N; i++)
        for (int j=0; j<M; j++)
            a[i][j] = i+j;
	    
    /* Cum se transmite ca parametru */
    afisare((char *) a, len);

    /* Verfica aici daca stau corect in memorie elementele */
    printf("%p %p %p\n%p %p %p\n",
            &a[0][0], &a[0][1], &a[0][2], 
            &a[1][0], &a[1][1], &a[1][2]);
	    
    free(a);
    return 0;
}
Grijă ce bagi în int-urile alea, să nu zici că nu merge funcţia din jbig sau că nu se transmite corect parametrul.

P.S. Nu am încercat cu VC++, doar cu g++. Dacă nu merge - ţeapă! LE: Nah, se pare ca nu vrea cu VC++, deci ţeapă! E ceva extensie non-standard în C++ pe care o suportă gcc, nu şi alte compilatoare (what a shame!). Poate găseşti un workaround. Sau foloseşti codul "corect" al tău, dar vezi să-l mai corectezi că acum nu merge (unde calculezi offset-ul la buffer e o mică scăpare).
P.P.S. All credits go to Yoda (nu întrebaţi cine e, o să ştie el)
P.P.P.S. Viorel.... aştept articolul! ;)
P.P.P.P.S. Nu sunt un expert tipic

viorel2005
Membru
Membru
Posts: 208
Joined: 24 May 2008, 09:41

Re: transmitere tablou 2d ca 1d

Post by viorel2005 » 31 Jan 2011, 16:46

Am rulat urmatorul cod in Visual C++ 2010:

Code: Select all

// PointTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <malloc.h>

void afisare(const char *buf, const unsigned int buflen)
{
    for (int i=0; i<buflen; i++)
        printf("%d ", (int) buf[i]);
    printf("\n");
}

int main()
{
    int N, M;
    N = 2;
    M = 3;
    unsigned int len = sizeof (int) * N * M;
    
    /* Cum se declara si initializeaza matricea */
    int (*a)[M] = (int (*)[M]) malloc(len);
            
    for (int i=0; i<N; i++)
        for (int j=0; j<M; j++)
            a[i][j] = i+j;
       
    /* Cum se transmite ca parametru */
    afisare((char *) a, len);

    /* Verfica aici daca stau corect in memorie elementele */
    printf("%p %p %p\n%p %p %p\n",
            &a[0][0], &a[0][1], &a[0][2], 
            &a[1][0], &a[1][1], &a[1][2]);
       
    free(a);
    return 0;
}
Iar rezultatul e urmatorul:

Code: Select all

1>------ Build started: Project: PointTest, Configuration: Debug Win32 ------
1>Build started 31.01.2011 15:32:26.
1>PrepareForBuild:
1>  Creating directory "c:\PointTest\Debug\".
1>InitializeBuildStatus:
1>  Creating "Debug\PointTest.unsuccessfulbuild" because "AlwaysCreate" was specified.
1>ClCompile:
1>  stdafx.cpp
1>  PointTest.cpp
1>c:\pointtest\pointtest\pointtest.cpp(9): warning C4018: '<' : signed/unsigned mismatch
1>c:\pointtest\pointtest\pointtest.cpp(22): error C2057: expected constant expression
1>c:\pointtest\pointtest\pointtest.cpp(22): error C2466: cannot allocate an array of constant size 0
1>c:\pointtest\pointtest\pointtest.cpp(22): error C2540: non-constant expression as array bound
1>c:\pointtest\pointtest\pointtest.cpp(22): error C2440: 'initializing' : cannot convert from 'int (*)[1]' to 'int (*)[]'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>c:\pointtest\pointtest\pointtest.cpp(26): error C2036: 'int (*)[]' : unknown size
1>c:\pointtest\pointtest\pointtest.cpp(33): error C2036: 'int (*)[]' : unknown size
1>c:\pointtest\pointtest\pointtest.cpp(33): error C2036: 'int (*)[]' : unknown size
1>c:\pointtest\pointtest\pointtest.cpp(33): error C2036: 'int (*)[]' : unknown size
1>c:\pointtest\pointtest\pointtest.cpp(34): error C2036: 'int (*)[]' : unknown size
1>c:\pointtest\pointtest\pointtest.cpp(34): error C2036: 'int (*)[]' : unknown size
1>c:\pointtest\pointtest\pointtest.cpp(34): error C2036: 'int (*)[]' : unknown size
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:00.66
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Exista vreo solutie sa se compileze cu Visual C++?

xxscorp
Junior
Junior
Posts: 7
Joined: 31 Jan 2011, 15:01
Judet: Timiş

Re: transmitere tablou 2d ca 1d

Post by xxscorp » 31 Jan 2011, 17:14

Cum ziceam, nu poti (din cate imi dau seama). Am pus un LLE la postul meu, chiar la inceput.

codexpert
Administrator
Administrator
Posts: 5
Joined: 12 Jul 2010, 14:06

Re: transmitere tablou 2d ca 1d

Post by codexpert » 31 Jan 2011, 18:15

xxscorp wrote:Am pus un LLE la postul meu, chiar la inceput.
Ce-i aia "LLE"?
Inainte de a posta citeste te rog "Inainte de a posta"!

viorel2005
Membru
Membru
Posts: 208
Joined: 24 May 2008, 09:41

Re: transmitere tablou 2d ca 1d

Post by viorel2005 » 01 Feb 2011, 00:41

Am modificat un pic codul si merge sub Visual C++. Problema este acum cum modific valoarea unui const int in Visual C++ 2010?

Code: Select all

// PointTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <malloc.h>
#include<conio.h>

const int M=4;
const int N=3;

void afisare(char *buf, int buflen)
{
	int i;
    for (i=0; i<buflen; i+=sizeof(int))
        printf("%d ", (int) buf[i]);
    printf("\n");
}

int main()
{
   
   	int i,j,k;
    k=0;
	
	unsigned int len = sizeof (int) * N * M;
    
    /* Cum se declara si initializeaza matricea */
    int (*a)[M] = (int (*)[M]) malloc(len);
            
    /* Cum se declara si initializeaza matricea */
	for (i=0; i<N; i++)
        for (j=0; j<M; j++)
            {
				k++;
				a[i][j] = k;
			}
       
    /* Cum se transmite ca parametru */
    afisare((char *) a, len);

    /* Verfica aici daca stau corect in memorie elementele */
    printf("%p %p %p\n%p %p %p\n",
            &a[0][0], &a[0][1], &a[0][2], 
            &a[1][0], &a[1][1], &a[1][2]);
       
    free(a);
	getch();
    return 0;
}
Va multumesc pentru ajutorul dat pana acum.

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: transmitere tablou 2d ca 1d

Post by Silviu Ardelean » 01 Feb 2011, 00:59

viorel2005 wrote:Problema este acum cum modific valoarea unui const int in Visual C++ 2010?
Vad ca te incapatanezi sa te gandesti la matrice de array-uri doar ca asa ai invatat la scoala.
Ce intelegi tu prin const int? :D

Daca asta nu e permisa in C++ standard

Code: Select all

int N = 2, M = 3;
int (*a)[M] = (int (*)[M]) malloc(sizeof (int) * N * M);
asta este permisa:

Code: Select all

int rows = 10, cols = 12;
int* bmp1 = new int[rows * cols];

xxscorp
Junior
Junior
Posts: 7
Joined: 31 Jan 2011, 15:01
Judet: Timiş

Re: transmitere tablou 2d ca 1d

Post by xxscorp » 01 Feb 2011, 16:06

Fiind aici un subforum de C++, ma asteptam la o solutie C++. Cum nu zice nimeni nimic, va propun eu, cu titlul de exercitiu, urmatoarele doua fisiere.
Ca mentiuni:
Se va folosi notatia A(i, j, k) in loc de A[j][k]. Cauza este ca nu se poate suprascrie operatorul [][], iar ca sa ocolesc aceasta problema ar fi fost necesare obiecte temporare (complet ineficient).
Eventualele griji ca va merge mai incet fiind datele ascunse intr-o clasa nu sunt fondate. Am testat eu si merge doar marginal mai lent decat codul scris direct. S-ar putea face incercari de optimizare prin reducerea numarului de inmultiri, dar acolo ne vom ciocni de cache. Concret, la testele de acces aleatoriu e mai rapid cu inmultiri (se pare ca inmultirea pe intregi e mai putin costisitoare decat un cache miss), iar la teste cu acces localizat sunt cam la fel (give or take). Precizare - am testat implementarea de array 2D.

Arr3D.h

Code: Select all

#ifndef _ARR3D_H
#define _ARR3D_H

#include <assert.h>
//#include "Arr2D.h"

template <typename T>
class Arr3D
{
public:
	Arr3D(const unsigned int d1, const unsigned int d2, const unsigned int d3);
	
	// Select the 2D matrix at a given plane
//	Arr2D<T> operator()(const unsigned int i1) { assert (i1<d1); return Arr2D<T>(data+i1*d2*d3, d2, d3); }

	// Select the 2D matrix at a given plane
	T *operator ()(const unsigned int i1) { assert (i1<d1); return data+i1*d2*d3; }
	// Select a given line from a given plane
	T *operator ()(const unsigned int i1, const unsigned i2) { assert (i1<d1); assert(i2<d2); return data+i1*d2*d3+i2*d3; }
	// Select an element
	T &operator ()(const unsigned int i1, const unsigned int i2, const unsigned int i3);

	// Return as type T buffer
	operator T*(){ return data; };

	// Return element count
	unsigned int GetElemCount() { return d1*d2*d3; }

	// Return buffer as char*
	operator char*(){ return (char *) data; };

	// Return size of binary buffer
	unsigned int GetBufLen() { return GetElemCount()*sizeof(T); }
	
	~Arr3D();
private:
	// Careful with these. Reimplement as needed
	Arr3D(const Arr3D<T> &a) { };
	T &operator =(const Arr3D<T> &a) { };

	unsigned int d1, d2, d3;
	T *data;
};

template<typename T> Arr3D<T>::Arr3D(const unsigned int d1, const unsigned int d2, const unsigned int d3)
{
	this->d1 = d1;
	this->d2 = d2;
	this->d3 = d3;

	data = new T[d1*d2*d3];
}

template <typename T> T& Arr3D<T>::operator () (const unsigned int i1, const unsigned int i2, const unsigned int i3)
{
	assert(i1<d1);
	assert(i2<d2);
	assert(i3<d3);

	return data[i1*d2*d3+i2*d3+i3];
}

template<typename T> Arr3D<T>::~Arr3D()
{
	delete []data;
}

#endif /* _ARR3D_H */
test.cpp

Code: Select all

#include <stdio.h>
//#include "Arr2D.h"
#include "Arr3D.h"

void afisare_char(const char *p, const unsigned int len)
{
	for (unsigned int i=0; i<len; i++)
		printf("%d ", (int) p[i]);
	printf("\n");
}

void afisare_int(const int *p, const unsigned int len)
{
	for (unsigned int i=0; i<len; i++)
		printf("%d ", p[i]);
	printf("\n");
}

int main()
{
	int d1 = 2;
	int d2 = 3;
	int d3 = 4;
	int i, j, k, count=0;
	Arr3D<int> a(d1, d2, d3);

	for (i=0; i<d1; i++)
		for (j=0; j<d2; j++)
			for (k=0; k<d3; k++)
				a(i, j, k) = count++;

	printf("As a(i, j, k) matrix:\n");
	for (i=0; i<d1; i++)
	{
		printf("Plane %d:\n", i);
		for (j=0; j<d2; j++)
		{
			for (k=0; k<d3; k++)
				printf("%d ", a(i, j, k));
			printf("\n");
		}
	}

	
//	printf("As distinct planes:\n");
//	for (i=0; i<d1; i++)
//	{
//		printf("Plane %d:\n", i);
//		Arr2D<int> plane = a(i);
//		for (j=0; j<d2; j++)
//		{
//			for (k=0; k<d3; k++)
//				printf("%d ", plane(j, k));
//			printf("\n");
//		}
//		printf("\n");
//	}
	

	printf("As distinct lines:\n");
	for (i=0; i<d1; i++)
		for (j=0; j<d2; j++)
		{
			printf("Line with i=%d, j=%d:\n", i, j);
			int *line = a(i, j);
			for (k=0; k<d3; k++)
				printf("%d ", line[k]);
			printf("\n");
		}

	printf("As int buffer:\n");
	afisare_int((int *) a, a.GetElemCount());

	printf("As char* buffer:\n");
	afisare_char((char *) a, a.GetBufLen());

	return 0;
}
Imi cer scuze pentru eventualele greseli de C++, intelegeti ca eu sunt doar un programator de C. Ah, si... varianta 2D este tema de casa ;) (sau poate scrie Viorel2005 un articol).

P.S. Am testat pe VS2005. Daca apar probleme cu gcc, o sa corectez si o sa marchez cu LE (de la later edit)

xxscorp
Junior
Junior
Posts: 7
Joined: 31 Jan 2011, 15:01
Judet: Timiş

Re: transmitere tablou 2d ca 1d

Post by xxscorp » 02 Feb 2011, 13:46

Ala eu, ala eu...
Out of the kindness of my heart (dar repede, pana nu ajung in colimatorul celor doi, stiti voi care :biggrin: ) - o matrice care poate fi accesata ca A[j] si are functie care returneaza datele liniarizate ca si char * (adica asa le si tine, nu se copiaza aiurea pe acolo). S-a pierdut cast-ul la char* pentru ca se zapaceste compilatorul cand scrii acel A[j], nu stie daca vreau operatorul direct, cum am scris, sau daca nu vreau sa se si cast-uie inainte la char* (duh!). Deci va trebui sa se utilizeze acea neeleganta metoda GetAsCharBuf().
@viorel2005 - sper ca de data asta te ajuta. Am incercat sa-l fac fara quiz-uri si alte intrebari cu talc incorporate (mai ramane sa te asiguri tu ca nu se acceseaza si altfel. De exemplu nu vad cu ochi buni ceva de genul matricebuclucasa1=matricebuclucasa2).

MatriceaBuclucasa.h

Code: Select all

#ifndef _MATRICEABUCLUCASA_H
#define _MATRICEABUCLUCASA_H

#include <assert.h>

template <typename T>
class MatriceaBuclucasa
{
public:
	MatriceaBuclucasa(const unsigned int N, const unsigned int M);
	T *operator [](const unsigned int i);
	char* GetAsCharBuf(){ return (char *) data; };
	unsigned int GetCharBufCount() { return N*M*sizeof (T); }
	
	~MatriceaBuclucasa();

private:
	unsigned int N, M;
	T *data;
};

template<typename T> MatriceaBuclucasa<T>::MatriceaBuclucasa(const unsigned int N, const unsigned int M)
{
	this->N = N;
	this->M = M;

	data = new T[N*M];

}

template <typename T> T* MatriceaBuclucasa<T>::operator [] (const unsigned int i)
{
	assert(i<N);
	return data+i*M;
}

template<typename T> MatriceaBuclucasa<T>::~MatriceaBuclucasa()
{
	delete []data;
}

#endif /* _MATRICEABUCLUCASA_H */
main.cpp (doar esentialul)

Code: Select all

/*..........*/
	unsigned int N=2, M=3;
	MatriceaBuclucasa<int> A(N, M);
	for (unsigned int i=0; i<N; i++)
		for (unsigned int j=0; j<M; j++)
			A[i][j] = i+j;
	char *buf = A.GetAsCharBuf();
	unsigned int len = A.GetCharBufCount();
	for (unsigned int i=0; i<len; i++)
		printf("%d ", (int) buf[i]);
	printf("\n");
/*..........*/

Post Reply