🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: es.comp.os.linux.programacion
Article #15341

Re: Uniones

#15341
From: Xavier Montero
Date: Mon, 10 Jul 2000 00:00
234 lines
8630 bytes
kuantiko escribi�:
> 
> Hola a todos.
> 
>         �Podr�a alguien darme una breve explicaci�n de lo que es una uni�n
> en C? Nunca las he usado, y lo �nico que he le�do es que son como una
> estrcutura en la que todos los elementos comparten direcci�n de
> memoria. �Qu� utilidad tienen?

Sup�n que quieres gestionar un museo que contiene 3 tipos de obras
de arte: Pinturas, esculturas y literatura escrita.

Hay una parte com�n a cada obra de arte: T�tulo, autor, lugar de
creaci�n,
fecha de inicio, fecha de acabado, estado de conservaci�n, etc.
Pero hay una serie de datos que son pertenecientes a cada tipo de
obra, por ejemlo, de las pinturas podemos almacenar el tipo de
pintura usado, la tonalidad general del cuadro, el tipo de tela,
si est� barnizado o no y las dimensiones X * Y. Para las esculturas
podemos almacenar
la materia prima (madera, yeso, m�rmol, etc) y las dimensiones X * Y *
Z.
Para las obras literarias podr�amos almacenar el n�mero de p�ginas,
el tipo de papel usado y si las tapas son de cart�n, cartulina o
cart�n reforzado.

Para gestionar el muso, vamos a asumir que hay que carga un n�mero
grande de obras en memoria para almacenarlas, clasificarlas, ordenarlas,
etc. Por ello no queremos desperdiciar demasiados bytes no usados.

[Nota: Cuando declare tipos siempre les preceder� con t para
evitar posteriores confuciones, por ejemplo un tipo "d�a de
semana" le llamar�a tdia. Es costumbre personal, cada uno que programe
a su gusto, evidentemente.]

Usaremos algunos enums:

tobra ------> {pintura, escultura, literatura}
testado ----> {muy_bueno, bueno, regular, malo, muy_malo}
tpintura ---> {acuarela, �leo, carb�n}
ttela ------> {tela_a, tela_b, etc} (No tengo ni p**a idea de nombres de
telas)
tbool ------> {true = -1, false}
tescultura -> {madera, yeso, marmol}
tpapel -----> {normal, satinado/*, etc*/}
ttapas -----> {carton_reforzado, carton, cartulina}

y as� construyes todos los tipos necesarios para luego escribir
lo que piensas.

Por ejemplo, si el tipo de obra se almacena en una variable
llamada t, la declaraci�n debe ser del tipo:

tobra t;

al estilo "int t;", pero es m�s l�gico escribir "tobra t;" puesto
que �se es su tipo de dato y no otro.

Repasemos: para clasificar una obra necesito:
T�tulo, autor, lugar de creaci�n, fecha de inicio, fecha de acabado,
estado de conservaci�n, etc.

Para el t�tulo, autor, lugar de creaci�n usaremos cadenas. Asumo que hay
un typedef que define el tipo "tcadena" para que sea un char[100] o un
char*
o lo que m�s te guste. Para el ejemplo da igual. Lo mismo para las
fechas.
Ahora me es igual si est� en formato dd/mm/yyyy en un string o es una
estructura o lo que sea. Asumo que hay un tipo tfecha.

Adem�s necesitar� almacenar con los datos de la obra el propio tipo de
obra y sus datos adicionales. Ah� viene el union. Como una obra
no puede ser literatura y estatua a la vez, reutilizo sus datos
extras.

El tipo de obra es del tipo tobra. Los datos adicionales todav�a
no los he analizado, pero les llamar� textra.

/*Aqu� rellenar� el c�digo necesario para textra*/

struct tobra_con_todo
{
	tobra	tipo;		/* Importante saber de qu� tipo es */
	tcadena	titulo;
	tcadena	autor;
	tcadena	lugar
	tfecha	inicio;
	tfecha	fin;
	testado	estado;
	textra	infoadicional;	/* Hasta que definamos textra infoadicional
				   contiene algo que no sabemos qu� es pero que
				   va a representar todo lo "raro" que no
				   es com�n a los tipos de obras */
};

Si nos fijamos, la info adicional de las pinturas podr�a ser as�:

struct tinfoextrapintura
{
	tpintura	pintura;
	ttonalidad	tonalidad;	/* no he definido ttonalidad
					pero ser�a un tipo capaz de contener
					los datos que representen una tonalidad
					determinada */
	ttela		tela;
	tbool		barnizado;
	int		x;
	int		y;
}

Para las esculturas:

struct tinfoextraescultura
{
	tescultura	material;
	int		x;
	int		y;
	int		z;
}

Para las obras literarias:

struct tinfoextraliteratura
{
	int	numeropaginas;
	tpapel	papel;
	ttapas	tapas;
}

Entonces, a diferencia de una estructura donde, por ejemplo almacenamos
numero de p�ginas _Y_ papel _Y_ tapas, ahora necesitamos una estructura
especial tinfoextra donde almacenamos inofpintura _O_ infoescultura
_O_ infoliteratura

y se hace con la union:

union tinfoextra
{
	struct tinfoextrapintura	infopintura;
	struct tinfoextraescultura	infoescultura;
	struct tinfoextraliteratura	infoliteratura;
}

con alg�n typedef puedes convertir "struct tinfoextra" a "textra", o en
el momento de definirla, as�:

typedef union tinfoextra
{
	struct tinfoextrapintura	infopintura;
	struct tinfoextraescultura	infoescultura;
	struct tinfoextraliteratura	infoliteratura;
} textra;

As�, la declaraci�n

textra i;

declara una variable llamada "i" de tipo "textra", pero "textra", seg�n
el typedef, no es m�s que un alias de "union tinfoextra".

De tal forma, i tiene tres miembros:

i.infopintura, i.infoescultura e i.infoliteratura, y cada uno, los
suyos pertiunentes. As�, si i es informaci�n extra relativa a una
novela, podemos saber su n�mero de p�ginas as�:

npag = i.infoliteratura.numeropaginas;

Lo �nico que sucede es que si escribo en i.infopintura.pintura, siendo
i infomaci�n de literatura, destrozo la info de la literatura porque
est�n en las mismas posiciones de memoria. Por eso, durante todo el
ejemplo, he supuesto que es informaci�n disjunta. Si almaceno datos
de pintura en una obra de literatura, es porque el programa funciona
mal. Por ello una union suele usarse dentro de una estructura m�s
grande que mantiene, entre otras cosas, el tipo de datos mantenidos
en la uni�n. Por ejemplo en nuestra estructura tobra_con_todo se
mantiene un dato tobra, para saber si es pintura, escultura o literatura
y poder tratar la infoemraci�n extra adecuadamente.

Hay numerosos ejemplos donde poder usar uniones:

Si almaceno un n�mero complejo puede hacerlo guardando "parte real +
parte
imaginaria" _O_ "m�dulo y �ngulo"

Si almaceno componentes de ordenador puede almacenar n�meros de serie
y en funci�n del tipo de compoennete unas u otras cosas: Monitores y
targetas
gr�ficas: Resoluci�n, _O_ cpu's y placas base: velocidad de proceso _O_
memoria y discos duros: Capacidad en bytes

Si almaceno fichas de "personas" en una empresa puedo poner en el
denominador
com�n el nombre, cif, poblaci�n, etc, y si es cliente almaceno unas
cosas _O_
si es proveedor otras _O_ si es trabajador otras (Este ejemplo no est�
muy
acertado porque un trabajador puede ser un cliente, o un cliente puede a
la
vex proveer materiales o servicios, pero si una persona pudiera ser S�LO
proveedor
o cliente o trabajador ser�a acertado).

Si almaceno fichas de alumnos que han terminado el curso, en la uni�n
puedo
almacenar la nota sacada para los aprobados y la fecha de repetici�n del
examen para los suspendidos.

Si un sat�lite almacena fotos de la tierra puede almacenar en una parte
com�n
si la foto es de infrarrojos o de luz normal y en cada caso almacenar
datos
distintos en una uni�n, por ejemplo, para infrarrojos, almacenar la
longitud
de onda captada y otras cosas que afecten a la captaci�n mediante
infrarrojos y
en caso de ser luz solar, almacenar si es de dia o de nocha (o lo que
sea
necesario) para fichar correctamente un foto sacada con luz natural.

Y asi, podr�amos poner un sinf�n de ejemplos m�s.

[Nota: Para los puristas:
	Donde pongo "tobra" deber�a poner "ttipoobra"
	Donde pongo "tobra_con_todo" deber�a poner "tobra"
pero no deseaba usar m�s de lo necesario las letras "*tipo*" para no
liar]

-- 
--------------------------------------------------------------
Chao!
Xavi
http://www.dsitelecom.com/ (Digital Sound Items)
--------------------------------------------------------------
Technical Details
Message-ID: <3969265B.884389C2@dsitelecom.com>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail
References: <39683D85.4A4E4957@teleline.es>

Show Full Headers
Complete Article Headers
X-Google-Language: SPANISH,ASCII
X-Google-Thread: f86c8,d9e2de11a81b412f
X-Google-Attributes: gidf86c8,public
From: Xavier Montero <xmontero@dsitelecom.com>
Subject: Re: Uniones
Date: 2000/07/10
Message-ID: <3969265B.884389C2@dsitelecom.com>
X-Deja-AN: 644401302
Content-Transfer-Encoding: 8bit
References: <39683D85.4A4E4957@teleline.es>
X-Accept-Language: en
Content-Type: text/plain; charset=iso-8859-1
Organization: Digital Sound Items
Mime-Version: 1.0
Newsgroups: es.comp.os.linux.programacion