Introducción a los Arreglos y Punteros

Anuncio
Introducción a los Arreglos y Punteros
Mag.,Esp.,Lic. Mariano Méndez
Correcciones: Ignacio Jordan
Facultad De Ingenierı́a - Universidad de Buenos Aires
1
Punteros: Un Cuco... pero no tanto
Como se ha comentado anteriormente una variable es un espacio de memoria
que se identifica mediante un nombre o identificador único por el cual se hace
referencia a ella. Ampliando un poco más este concepto, podemos decir que en
realidad la memoria está estructurada como un conjunto de celdas distribuidas
linealmente, cada una de estas celdas posee una dirección única dentro de este
conjunto, esta dirección se denomina dirección de memoria ver Figura 2.
El nombre de una variable es el equivalente humano de la dirección de memoria, ya que serı́a humanamente muy complejo escribir programas complejos y largos que referencien directamente a las direcciones de memoria (Cómo se hacı́a
con las primeras computadores), por ello, se utilizan nombres que posteriormente
el compilador reemplaza por direcciones de memoria.
En muchos lenguajes de programación existe un tipo de dato que almacena
exclusivamente direcciones de memoria, este tipo de dato se denomina puntero,
ver Figura 1. Cabe destacar que la utilización de punteros agrega un nivel de
complejidad al programa que se está desarrollando, ya que el programador, en
el caso de C, debe controlar su uso. Como con todos los tipos de datos en C se
puede declarar una variable tipo puntero.
En el caso especı́fico de los punteros, la declaración se realiza de la siguiente
forma:
tipoDeDatoAlQueApuntar ∗ NombreDelPuntero ;
Concretamente :
int
double
char
float
1.1
∗ ptrEntero ;
∗ prtDouble ;
∗ ptrChar ;
∗ ptrFloat ;
//un
//un
//un
//un
puntero
puntero
puntero
puntero
a
a
a
a
un
un
un
un
entero
double
caracter
float
Operador de Dirección
El operador de dirección es un operador unario en C que devuelve la dirección
del operando, este corresponde a “&”.
int
int
unEntero =2;
∗ ptrEntero ;
p t r E n t e r o= &unEntero ;
//un p u n t e r o a un e n t e r o
2
Algoritmos y Programacón I - 75.40 - Cat. Garcia
123
unaVariable
unPuntero
Fig. 1. Esquema del concepto de Puntero
p
...
c
...
Fig. 2. Esquema de distribución de la memoria
...
Introducción a los Arreglos y Punteros
3
En el código escrito anteriormente se definen dos variables, una entera y otra
que es un puntero a un entero. En la asignación, el operador de dirección le
asigna la dirección de memoria en la cual esta definida la variable unEntero a
ptrEntero.
2
unEntero / f2c4
f2c4
ptrEntero
Fig. 3. Diagrama del ejemplo
1.2
Operador de Indirección
El operador de indirección devuelve el valor del objeto hacia el cual su operando
apunta, dicho operando debe ser un puntero.
int
int
unEntero =2;
∗ ptrEntero ;
//un p u n t e r o a un e n t e r o
p t r E n t e r o= &unEntero ;
p r i n t f ( ”d” , ∗ p t r E n t e r o ) ;
Cuanto deberı́a mostrar el código anterior? La respuesta correcta es 2. Veamos
otro ejemplo
#i n c l u s e <s t d i o . h>
int main ( ) {
int unEntero ;
int ∗ ptrUnEntero ;
unEntero =7;
ptrUnEntero=&unEntero ;
p r i n t f ( ”La d i r e c c i o n de memoria de unEntero e s %p \n” ,&UnEntero ) ;
4
Algoritmos y Programacón I - 75.40 - Cat. Garcia
p r i n t f ( ” e l v a l o r de p t r U n e n t e r o e s %p\n” , ptrUnEntero ) ;
p r i n t f ( ” El v a l o r de unEntero e s %d \n” , UnEntero ) ;
p r i n t f ( ” e l v a l o r d e l a d i r e c c i o n de memoria apuntada por p t r U n e n t e r o e
return 0 ;
}
2
Pasaje de parámetros por referencia
Se ha explicado que en C sólo es posible pasar los parámetros por valor, y esta
afirmación sigue siendo verdadera, entonces cómo se hace cuando se necesita
pasar algún parámetro y que cualquier modificación hecha en la función que
recibe el parámetro se vea plasmada o reflejada en la función llamadora, es decir
pasar el parámetro por referencia. En C es posible utilizando el concepto de
puntero. Si implementamos la siguiente función de intercambio de dos enteros:
#i n c l u s e <s t d i o . h>
void i n t e r c a m b i o ( int v a l o r 1 , int v a l o r 2 ) {
int aux ;
aux = v a l o r 1 ;
v a l o r 1=v a l o r 2 ;
v a l o r 2=aux ;
}
int main ( ) {
int unNumero , otroNumero ;
unNumero=1;
otroNumero =2;
i n t e r c a m b i o ( unNumero , otroNumero ) ;
p r i n t f ( ”unNumero = %d \n otroNumero=%d” , unNumero , otroNumero ) ;
return 0 ;
}
tras compilar y ejecutar el programa propuesto, veremos sin asombro que el
los valores impreso es :
unNumero=1
otroNumero=2
Introducción a los Arreglos y Punteros
5
Ahora bien, ¿Cómo se plantea el programa si realmente se quiere intercambiar
los valores de las variables? En realidad para que el pasaje de parámetros resulte
por referencia, se debe implementar la función intercambio() de la siguiente
forma:
void i n t e r c a m b i o ( int ∗ v a l o r 1 , int ∗ v a l o r 2 ) {
int aux ;
aux = ∗ v a l o r 1 ;
∗ v a l o r 1 =∗ v a l o r 2 ;
∗ v a l o r 2=aux ;
}
y la llamada a la función debe realizarse :
i n t e r c a m b i o (&unNumero,& otroNumero ) ;
}
Es decir, los parámetros formales de la función son punteros a dos enteros,
y los parámetros actuales de la llamada son las direcciones de memoria de las
variables que se desea pasar por referencia. En la Figura
3
Constantes
Una constante no es nada más que una versión escrita o nombrada de un determinado valor que se utiliza en el programa. En ANSI C se pueden definir valores
constantes mediante la utilización de la palabra reservada const de la siguiente
forma:
int const Pi = 3 . 1 4 1 6 ;
const int Base =2;
¿Para qué sirve utilizar constantes si podemos escribir el valor por todo el
programa? De hecho no es necesario usar constantes, pues los valores escritos
directamente en el programa pueden ir tranquilamente. La utilización de constantes es una práctica de buena programación, por dos motivos:
1. Hacen más fácil la aplicación de cambios al programa.
2. Hacen más comprensible y auto-descriptivo el código fuente.
3. Ayudan al mantenimiento del código fuente.
Otra forma de definir valores constantes, es mediante el uso del preprocesador de C. Es posible utilizar la directiva #define, a diferencia de utilizar la
palabra reservada el preprocedador de C reemplazará el valor de la directiva por
el nombre asignado.
#define TRUE 1
#define FALSE 0
6
Algoritmos y Programacón I - 75.40 - Cat. Garcia
en el llamador: main
unNumero
otroNumero
valor2
valor1
en intercambio:
Fig. 4. Diagrama ejemplo de pasaje de parámetros por referencia
Introducción a los Arreglos y Punteros
7
....
....
i f ( esPrimo==TRUE) . . .
4
Vectores
ANSI C proporciona un tipo de dato estructurado capaz de almacenar una
colección secuencial y finita de de elementos del mismo tipo de dato. A este
tipo de dato se lo denomina arreglo o vector unidimensional.
La idea detrás de los vectores consiste en que en vez de declarar n variables,
por ejemplo, medicion1, medicion2,medicion3, hasta medicion99 se declare una
única variable llamada mediciones, que pueda almacenar todos los valores que
sean necesarios (cuando se refiere a todos los valores necesarios no hay que olvidar
que este valor DEBE ser finito), ver Figura 5.
Una vez declarada la variable de tipo vector, se podrán acceder a sus elementos mediante la utilización de un subı́ndice que corresponde a i-ésimo elemento
del vector.
Para declarar un vector en C, el programador debe especificar el tipo de
dato de los componente el vector (por definición, todos son del mismo tipo) y el
número de elementos del vector o tamaño:
t i p o NombreDelVector [ tama ñoDelVector ] ;
Algunos ejemplo de declaraciones de vectores :
int main ( ) {
int const CANTIDAD MAXIMA TEMP=50;
int const DIAS DEL MES=31;
int const MESE DEL ANIO=12;
int m e d i c i o n e s [ 6 ] ;
// v e c t o r de 6 e l e m e n t o s e n t e r o s
f l o a t t e m p e r a t u r a s [CANTIDAD MAXIMA TEMP ] ;
f l o a t t e m p e r a t u r a s D i a r i a s [ MESE DEL ANIO ] ;
char p a l a b r a [ 1 2 ] ; // v e c t o r de 12 c a r a c t e r e s
}
Nota:Las operaciones entre vectores deben hacerse elemento por elemento.
No es posible en C poder asignar un vector a otro, ni sumar un escalar a un
vector en forma automática.
Nota2: Los vectores se definen con una longitud fija y finita que NO PUEDE
SER CAMBIADA a lo largo del programa.
8
Algoritmos y Programacón I - 75.40 - Cat. Garcia
int mediciones[6];
mediciones[0]
elemento 1
mediciones[1]
mediciones[2]
mediciones[3]
mediciones[4]
mediciones[5]
elemento 2
elemento 3
elemento 4
elemento 5
elemento 6
Fig. 5. Vector de 6 elementos enteros
Nota3: Los vectores o arreglos de caracteres se denominan String y en C
tiene un tratamiento especial.
Nota4: Los vectores en C al igual que muchos tipos de variables pueden inicializarse en la misma linea en donde se declaran, para ello es necesario enumerar
uno a uno los elemento del vector:
int m e d i c i o n e s [ 6 ] = { 1 2 , 2 3 , 3 4 , 4 5 , 5 6 , 67 } ;
Caso especial 1, inicialización de todos los elementos de un vector con el
mismo valor:
int m e d i c i o n e s [ 6 ] = { 0 } ;
ado que en C, si la lista de inicializadores es menor a la cantidad total de elementos del vector, aquellos elementos que no tengan inicializador serán automáticamente inicializados en 0. Ojo!!, este tipo de reglas no es igual en todos
los lenguajes de programación, por lo tanto se desaconseja utilizarla.
Caso especial 2, inicialización de un arreglo al que no se le ha definido longitud:
int l i s t D e E n t e r o s [ ] = { 5 , 4 , 3 , 2 , 1 } ;
En este caso el arreglo tomará la longitud, fija, de la cantidad de elementos con
inicializadores, en este caso la longitud será 5.
4.1
Arreglos multidimensionales
La primera aproximación a un arreglo multidimensional la tenemos en el concepto algebraico de matriz, en la Figura 6 puede observarse el concepto matemático
dibujado a la izquierda y la representación computacional dibujada a la derecha.
La declaración de un arreglo bidimensional en este caso se realiza como se
describe a continuación:
int m a t r i z [ 3 ] [ 3 ] ;
Introducción a los Arreglos y Punteros

9

a11















a12
a13
a21
a22
a23
a31
a23
a33















a[0, 0] a[0, 1] a[0, 2]
a[1, 0] a[1, 1] a[1, 2]
a[2, 0] a[2, 1] a[2, 2]
Fig. 6. Una matriz de 3 filas y 3 columnas
Cabe destacar que para acceder al contenido de un elemento del arreglo
bidimensional, necesitamos dos coordenadas i,j. Por ejemplo, si se desea imprimir
el valor almacenado en la fina 2 columna 3 de la matriz, se deberá escribir:
p r i n t f ( ”%d” , m a t r i z [ 1 , 2 ] ) ;
Ası́ mismo también las matrices pueden ser inicializadas en su declaración :
int
{0 ,
{4 ,
{8 ,
};
matriz [ 3 ] [ 4 ]
1 , 2 , 3} ,
5 , 6 , 7} ,
9 , 1 0 , 11}
= {
/∗ i n i t i a l i z e r s f o r row i n d e x e d by 0 ∗/
/∗ i n i t i a l i z e r s f o r row i n d e x e d by 1 ∗/
/∗ i n i t i a l i z e r s f o r row i n d e x e d by 2 ∗/
En realidad no es necesario escribirlo de esta forma, también es posible inicializarla de la siguiente forma:
int a [ 3 ] [ 4 ] = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 1 0 , 1 1 } ;
En C es posible declarar un arreglo de más de dos dimensiones, por ejemplo
de tres dimensiones, ver Figura 7 esto se debe declarar de la siguiente forma:
4.2
Vectores, Punteros y Pasaje de Vectores como parámetros
En el lenguaje de Programación C existe una muy estrecha relación entre los
vectores y los punteros [2,1]. A continuación se muestra la relación entre los
vectores y los punteros en C:
int v e c t o r [ 1 0 ] = ” 1 2 , 2 3 , 3 4 , 4 5 , 5 6 , 6 7 , 7 8 , 8 9 , 9 0 , 100 ” ;
int ∗ p t r E n t e r o ;
int unValorEntero ;
Las siguiente expresiones son equivalentes:
ptrEntero= &vetor[0]
ip=vector
unValorEntero=*ptrEntero unValorEntero=*ptrEntero
*(ptrEntero+1)
v[1]
ptrEntero+i
&vector[i]
Algoritmos y Programacón I - 75.40 - Cat. Garcia
7
0,1
7
,0
,0
1,0
,0
9
0,2
,0
1,1
,0
2,0
,0
8
4
0,0
9
3
6
1
5
2
10
1
1,2
,0
2,1
,0
5
3
6
4
2,2
2
,0
8
Fig. 7. Una matriz de tres dimensiones
4.3
Pasaje de Vectores por Parámetros
En primer lugar, cuando se necesita definir un parámetro formal como un vector,
se lo define de la siguiente forma:
int SumarElementosDeVector ( int unVector [ ] ) {
}
No es necesario poner la longitud del vector que se espera como parámetro. Como
se ha visto en las igualdades anteriores la llamada a la función sumar puede ser
escrita como :
int suma=SumarElementosDeVector(& v e t o r [ 0 ] ) ;
int suma=SumarElementosDeVector ( v e t o r ) ;
esta última es la más utilizada. Como se puede apreciar los vectores o arreglos
(cualquiera sea su dimensión) SIEMPRE se pasan por referencia.
5
Un Ejemplo Completo del uso de Vectores
Dados dos arreglos cuyos elementos contienen valores enteros, realizar un programa en C que solucione los siguientes apartados:
1.
2.
3.
4.
5.
Cargue ambos vectores con valores ingresados por el usuario
Calcule el vector suma
Calcule el vector resta
Calcule el producto escala entre ambos vectores
Calcule el módulo
Introducción a los Arreglos y Punteros
11
#include<s t d i o . h>
#include<math . h>
#define LONGITUD
10
void sumar ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int vectorSuma [ ]
void r e s t a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int v e c t o r R e s t a
long p r o d u c t o E s c a l a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] ) ;
void l e e r V e c t o r ( int unVector [ ] ) ;
double modulo ( int vectorOperandoUno [ ] ) ;
void m o s t r a r V e c t o r ( int unVector [ ] ) ;
int main ( ) {
int unVector [LONGITUD ] ;
int o t r o V e c t o r [LONGITUD ] ;
int r e s u l t a d o [LONGITUD] = { 0 } ;
p r i n t f ( ” I n g r e s a r l o s d a t o s d e l p r i m e r v e c t o r \n” ) ;
l e e r V e c t o r ( unVector ) ;
p r i n t f ( ” I n g r e s a r l o s d a t o s d e l segundo v e c t o r \n” ) ;
leerVector ( otroVector ) ;
sumar ( unVector , o t r o V e c t o r , r e s u l t a d o ) ;
mostrarVector ( r e s u l t a d o ) ;
r e s t a r ( unVector , o t r o V e c t o r , r e s u l t a d o ) ;
mostrarVector ( r e s u l t a d o ) ;
p r i n t f ( ” e l p r o d u c t o e s c a l a r de l o s dos V e c t o r e s e s : %l d \n” , p r o d u c t o E s c a
p r i n t f ( ” e l modulo d e l p r i m e r v e c t o r e s : %f \n” , modulo ( unVector ) ) ;
p r i n t f ( ” e l modulo d e l segundo v e c t o r e s : %f \n” , modulo ( o t r o V e c t o r ) ) ;
}
void sumar ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int vectorSuma [
int i ;
f o r ( i =0; i <LONGITUD; i ++)
vectorSuma [ i ]= vectorOperandoUno [ i ]+ vectorOperandoDos [ i ] ;
}
void r e s t a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int vectorSuma
int i ;
f o r ( i =0; i <LONGITUD; i ++)
vectorSuma [ i ]= vectorOperandoUno [ i ]− vectorOperandoDos [ i ] ;
}
12
Algoritmos y Programacón I - 75.40 - Cat. Garcia
long p r o d u c t o E s c a l a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] ) {
int i ;
long s u m a t o r i a =0;
f o r ( i =0; i <LONGITUD; i ++)
s u m a t o r i a+=vectorOperandoUno [ i ] ∗ vectorOperandoDos [ i ] ;
return s u m a t o r i a ;
}
void l e e r V e c t o r ( int unVector [ ] ) {
int i ;
f o r ( i =0; i <LONGITUD; i ++){
p r i n t f ( ” Vector [%d ] = ” , i ) ;
s c a n f ( ”%d” ,& unVector [ i ] ) ;
}
}
double modulo ( int OperandoUno [ ] )
{
int i ;
double suma=0;
f o r ( i =0; i <LONGITUD; i ++){
suma+=OperandoUno [ i ] ∗ OperandoUno [ i ] ;
}
return s q r t ( suma ) ;
}
void m o s t r a r V e c t o r ( int unVector [ ] ) {
int i ;
f o r ( i =0; i <LONGITUD; i ++)
p r i n t f ( ”%d” , unVector [ i ] ) ;
}
este ejemplo puede ser descargado, compilado y ejecutado desde https://
www.dropbox.com/s/2e28zc64wbyf580/ejemplo.c?dl=0
6
Simulación de Vectores de Longitud Variable
En C como en muchos otros lenguajes de programación no es posible declarar
vectores que puedan variar la cantidad de elementos que almacenan. Por ello se
dice que los vectores son tipos de datos estáticos, pues no se puede alterar su
tamaño (en bytes) en tiempo de ejecución del programa.
Introducción a los Arreglos y Punteros
13
De todas formas es muy común que sea necesario, dadas las caracterı́sticas
del problema que se necesite, variar la cantidad de elementos que contiene un
vector en tiempos de ejecución ... Entonces, ¿Cómo lo hacemos si el lenguaje no lo
permite? La respuesta es sencilla, se define un vector de una longitud conocida, a
priori, que dentro del dominio del problema nunca podrá ser superada. En otras
palabras, se define un vector muy grande. Y además, se utiliza una variable para
almacenar la información del tamaño o tope utilizados del vector, ver Figura 8.
Tope del Vector
Vector
Fig. 8. Uso acotado del tamaño de un vector
El par vector tope siempre van juntos durante la ejecución del programa.
Teniendo en cuenta ahora esta forma de simular vectores de longitud variable o
de tamaño variable, podemos modificar el ejemplo anterior para que el usuario
seleccione la longitud de los dos vectores:
Dados dos arreglos cuyos elementos contienen valores enteros, y cuya dimensión se ingresa por teclado, realizar un programa en C que solucione los
siguientes apartados:
1.
2.
3.
4.
5.
Cargue ambos vectores con valores ingresados por el usuario
Calcule el vector suma
Calcule el vector resta
Calcule el producto escala entre ambos vectores
Calcule el modulo
#include<s t d i o . h>
#include<math . h>
#define LONGITUD
10
void sumar ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int vectorSuma [ ]
void r e s t a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int v e c t o r R e s t a
14
Algoritmos y Programacón I - 75.40 - Cat. Garcia
long p r o d u c t o E s c a l a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int t o
void l e e r T o p e ( int ∗ t o p e ) ;
void l e e r V e c t o r ( int unVector [ ] , int t o p e ) ;
double modulo ( int vectorOperandoUno [ ] , int t o p e ) ;
void m o s t r a r V e c t o r ( int unVector [ ] , int t o p e ) ;
int main ( ) {
int unVector [LONGITUD ] ;
int t o p e =0;
int o t r o V e c t o r [LONGITUD ] ;
int r e s u l t a d o [LONGITUD] = { 0 } ;
l e e r T o p e (& t o p e ) ;
printf (” Ingresar los
l e e r V e c t o r ( unVector ,
printf (” Ingresar los
leerVector ( otroVector
d a t o s d e l p r i m e r v e c t o r \n” ) ;
tope ) ;
d a t o s d e l segundo v e c t o r \n” ) ;
, tope ) ;
sumar ( unVector , o t r o V e c t o r , r e s u l t a d o , t o p e ) ;
mostrarVector ( resultado , tope ) ;
r e s t a r ( unVector , o t r o V e c t o r , r e s u l t a d o , t o p e ) ;
mostrarVector ( resultado , tope ) ;
p r i n t f ( ” e l p r o d u c t o e s c a l a r de l o s dos V e c t o r e s e s : %l d \n” , p r o d u c t o E s c a
p r i n t f ( ” e l modulo d e l p r i m e r v e c t o r e s : %f \n” , modulo ( unVector , t o p e ) ) ;
p r i n t f ( ” e l modulo d e l segundo v e c t o r e s : %f \n” , modulo ( o t r o V e c t o r , t o p e )
}
void sumar ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int vectorSuma [
int i ;
f o r ( i =0; i <t o p e ; i ++)
vectorSuma [ i ]= vectorOperandoUno [ i ]+ vectorOperandoDos [ i ] ;
}
void r e s t a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int vectorSuma
int i ;
f o r ( i =0; i <t o p e ; i ++)
vectorSuma [ i ]= vectorOperandoUno [ i ]− vectorOperandoDos [ i ] ;
}
long p r o d u c t o E s c a l a r ( int vectorOperandoUno [ ] , int vectorOperandoDos [ ] , int t o
int i ;
long s u m a t o r i a =0;
f o r ( i =0; i <t o p e ; i ++)
Introducción a los Arreglos y Punteros
15
s u m a t o r i a+=vectorOperandoUno [ i ] ∗ vectorOperandoDos [ i ] ;
return s u m a t o r i a ;
}
void l e e r T o p e ( int ∗ t o p e ) {
p r i n t f ( ” I n g r e s e l a d i m e n s i o n de l o s v e c t o r e s \n” ) ;
s c a n f ( ”%d” , t o p e ) ;
}
void l e e r V e c t o r ( int unVector [ ] , int t o p e ) {
int i ;
f o r ( i =0; i <t o p e ; i ++){
p r i n t f ( ” Vector [%d ] = ” , i ) ;
s c a n f ( ”%d” ,& unVector [ i ] ) ;
}
}
double modulo ( int OperandoUno [ ] , int t o p e )
{
int i ;
double suma=0;
f o r ( i =0; i <t o p e ; i ++){
suma+=OperandoUno [ i ] ∗ OperandoUno [ i ] ;
}
return s q r t ( suma ) ;
}
void m o s t r a r V e c t o r ( int unVector [ ] , int t o p e ) {
int i ;
f o r ( i =0; i <t o p e ; i ++)
p r i n t f ( ”%d” , unVector [ i ] ) ;
}
El mismo concepto es aplicable para las matrices y los arreglos multidimensionales, por cada dimensión es necesario almacenar el tope. El ejemplo puede
ser descrgado, compilado y ejecutado desde : aquı́
7
Registros
Un registro o struct en C es un tipo de dato estructurado, que define a una
lista de variables agrupadas fı́sicamente bajo un mismo nombre en un bloque
de memoria, permitiendo de esta forma que estas sean accedidas mediante la
utilización de un único nombre (que como ya sabemos en C equivale a la variable
puntero que referencia a dicha estructura).
16
Algoritmos y Programacón I - 75.40 - Cat. Garcia
Un struct o registro puede contener ya sea a otros tipos de datos estructurados como a tipos de datos simples. Se debe tener en cuenta que los struct
o registros permiten, al contrario de los vectores, agrupar variables de tipos de
datos disı́miles que guardan alguna relación entre sı́.
struct unNombre {
t i p o campo1 ;
t i p o campo2 ;
t i p o campo3 ;
t i p o campo4 ;
};
También es posible utilizar y declarar estructuras utilizando la palabra reservada de C typdef. Su función es asignar un nombre alternativo a tipos existentes,
a menudo cuando su declaración normal es aparatosa o potencialmente confusa,
por ejemplo:
typedef struct f e c h a {
unsigned short d i a ;
unsigned short mes ;
unsigned int a n i o ;
} Tfecha ;
typedef char [ 9 ] Tdocumento ;
struct p e r s o n a {
char nombre [ 4 0 ] ;
char a p e l l i d o [ 4 0 ]
Tdocumento documento
Tfecha fechaDeNacimiento ;
} Tpersona ;
Tpersona unaPersona ;
Cada una de las variables que componen a un struct o registro se denomina
campo o miembro. Al igual que los arreglos estas variables pueden ser inicializadas:
/∗ D e c l a r a c i ó n a n t i c i p a d a d e l t i p o de d a t o ” punto ” . ∗/
typedef struct punto Tpunto ;
/∗ D e c l a r a c i o n d e l s t r u c t o r e g i s t r o con l o s campos o miemobros x , y ∗/
struct punto {
int
x;
int
y;
};
Introducción a los Arreglos y Punteros
17
Inicialización al estilo C-89, solo puede ser hecha cuando los valores de los
campos son ingresados en orden y en forma contigua:
/∗ d e f i n e una v a r i a b l e de t i p o Tpunto e i n i c i a l i z a s u s miembros en e l mismo l u
point p = {1 ,2};
Si la inicialización no es en orden, entonces:
/∗ D e f i n e una v a r i a b l e de t i p o Tpunto e i n i c i a l i z a s u s miembros ∗/
point p = {. y = 2 , . x = 1};
7.1
Registros: Asignación
Como se puede suponer la asignación de una variable de tipo struct a otra
puede hacerse en un único paso, con lo cual se asigna una variable a otra. O
puede hacerse miembro a miembro:
#include<s t d i o . h>
/∗ D e c l a r a c i o n d e l s t r u c t o r e g i s t r o con l o s campos o miemobros x , y ∗/
struct punto {
int
x;
int
y;
} Tpunto ;
int main ( ) {
Tpunto unPunto ={1 ,2};
Tpunto otroPunto ;
Tpunto otroPuntoMas ;
/∗ s e a s i g n a l o s v a l o r e s de t o d o s l o s miembros de una v a r i a b l e a o t r a ∗/
otroPunto = unPunto ;
/∗ s e c o p i a campo a campo l o s v a l o r e s de una v a r i a b l e a o t r a ∗/
otroPuntoMas . x=unPunto . x ;
otroPuntoMas . y=unPunto . y ;
otroPunto . x+=1;
i f ( otroPunto . x != otroPuntoMas . x )
return 0 ;
}
p r i n t f ( ” El campo x:%d
e l Campo y :%d
18
7.2
Algoritmos y Programacón I - 75.40 - Cat. Garcia
Registros: Punteros
Al igual que en cualquier otro tipo de dato , en C uno puede definir un puntero
a un struct, se verá la operatoria en el ejemplo:
struct punto {
int x ;
int y ;
};
struct punto MiPunto = { 1 , 3 } ;
struct punto ∗ ptrPunto = &miPunto ;
( ∗ ptrPunto ) . x = 8 ;
ptrPunto−>x = 8 ;
/∗ a c c e d e r a l primer miembro d e l r e g i s t r o ∗/
/∗ o t r a forma de h a c e r l o mismo ∗/
References
1. Harvey M Deitel, Paul J Deitel, and TR Nieto. C++ how to program, volume 4.
Prentice Hall Englewood cliffs, 1994.
2. B. W. Kernighan and D. M. Ritchie. The C Programming Language. Prentice-Hall,
Englewood Cliffs, New Jersey, 1978.
Descargar