10.1.
Es incorrecta sintácticamente la declaración i n t &y, ya que es una referencia y debe ser inicializada a una
variable. ( Una referencia es un alias de otra variable.) No tiene ningún sentido en C++, debería ser, por ejemplo, int
&y = x. Un carácter que está entre comillas simples es considerado como una constante de tipo char no como una
cadena, para lo cual debería estar rodeado de dobles comillas: char* c= "C". La declaración void* r = &x ; es correcta.
10.2. Por medio de un puntero a constante se puede acceder a la constante apuntada, pero no está permitido cambiar
o modificar su valor por medio del punter o. Un puntero declarado como constante no puede modificar el valor del
puntero, es decir, la dirección que contiene y a la que apunta; pero puede modificarse el contenido almacenado en la
posición de memoria a la que apunta.
10.3. El tipo del puntero que se utilice para recorrer un array unidimensional tiene que ser del mismo tipo que el de
los elementos que compongan el array, puesto que va a ir apuntando a cada uno de ellos sqgún los recorra. El acceso
y recorrido puede realizarse de la siguiente forma:
i nt *p , v [ 5 ] ;
P = v;
for ( 1 nt i = 0; i < 5; i++, p++) // p apunta a v[i]
El compilador de C++ considera que un array bidimensional es en realidad un array de punteros a los array s que
forman sus filas, por lo que para apuntar al inicio de un arr ay bidimensional es necesario un puntero doble o puntero
a puntero, que contiene la dirección del primer puntero del array de punteros a cada una de las filas del array
bidimensional o matriz. Como los arravs bidimensionales se almacenan en memoria linealmente f ila afila, para acceder
a un elemento concreto de una fila y columna determinadas hay que calcular primer o en que fila está y dentro de esa
fila en qué columna para poder calcular su posición dentro de la memoria. Rira realizar esta operación no es necesario
saber cuántas fias contiene la matriz bidimensional pero sí cuántas columnas, para saber cuántos bytes ocupa cada fia
(conocido el tipo de dato).
Por ejemplo dada la declaración:
int v[10][5] ; son expresiones equivalentes:
v[i][j];
* ( v [ i ] +j ); // puntero de filas
*((*(v + i)) + j) //puntero de columnas
( &v [ 0 ] [ 0 ] + Numero_de_col umnas * i + j)
10.4. Se define un puntero a puntero que apunte a la primera posición de la matriz y se calculan las posiciones de
memoria donde se encuentran cada uno de los elementos de la matriz, a base de sumar la longitud de las filas desde
el comienzo de la matriz y los elementos desde el comienzo de laf ila donde está situado el elemento al que se desea
acceder . Si un elemento está en la fila i, habrá que saltar i filas enteras de elementos del tipo de la matriz, para situarse
al comienzo de su fila en la memoria. Si el elemento que se b usca está en la columna j, hay que avanzar tres posiciones
desde el comienzo de su fila calculado anteriormente . Así, se accede a la dir ección donde se encuentr a el elemento
b uscado.
V[i][j] está *(&V[0][0] + i * ( numero_de_col umnas ) + j ) (Para realizar los cálculos es imprescindible conocer el número
de columnas de la matriz, que es igual al tamaño de cada fila). El elemento buscado también se encuentra en *(/[i ]+j
), o bien en *( (*(mt+f) )+c). Una de estas expresiones (normalmente la primera ) es la misma que sustituye el
compilador de C++, cuando compila la indirección que representan los operadores corchetes de los arrays. En la
codificación que se presenta, se incluyen cada una de las e xpresiones anteriores para visualizar la matriz.
Programa de ejmplo en dev c++
#include <cstdlib>
#include <iostream>
using namespace std;
#define N 2
#define M 3
doubl e mt[N] [M] ;
int maintint argc, char *argv[])
i
int f , c ;
for (f = 0; f < N; f++)
for (c = 0; c < M; c++)
ci n >> mt[f ] [c] ;
cout << " mt[f][c]\n";
for (f = 0; f < N; f++)
{
for (c = 0; c < M; c++)
cout << mt[f ] [c] << " " ;
cout << endl ;
}
cout <<"*((* (mt + f) ) + c)\n";
for (f = 0; f < N; f++)
{
for (c = 0; c < M; c++)
cout «(*((* (mt + f) ) + c)) << "
cout << endl ;
}
cout << " * (mt[f ]+c ) \n " ;
for (f = 0; f< N; f++)
{
for (c = 0; c < M; c++)
cout << ( * (mt[f] + c)) << ” ” ;
cout << endl ;
}
cout << " * ( &mt C 0 ] [ 0 ] + M * f + c)\n";
for (f = 0; f< N; f++)
I
for (c = 0; c < M; c++)
cout << (* (&mt[0][0] + M * f + c ) ) <<
cout << endl ;
}
System (" PAUSE" ) ;
return EXIT_SUCCESS;
10.5. Al hacer la llamada a la función se debe pasar el nombr e del array que se va a recorrer o un puntero con la
dirección del comienzo del array. El puntero que recibe la función doub 1 e *A puede ser tratado dentro de su código
como si fuer a un array, usando el operador corchete [], A[i ], o como un simple puntero que se va a mover por la
memoria. En este caso se codifica con el operador corchete. Para resolver el problema planteado se usa un algoritmo
voraz, que toma como mi ni mo el primer elemento A[0],y como dirección del mínimo di rmi n imo la dirección del
primer elemento del array &A[0]. Usando el segundo parámetro de la función int n, que es necesario para no moverse
fuera de la región de la memoria donde están los datos válidos del array original almacenados, se itera con un bucle
for, eligiendo como nuevo minimo el que ya se tenía o el que se está tratando en caso de que lo sea.
double *minimo_de_Array (double *A, int n)
int i ;
double minimo =ACO] ;
doubl e *dirminimo = & ACO]
for (i = 0; i < n; i ++)
if r ( A [ i ] < minimo)
dirminimo = &A [ i ] ;
minimo= A [ i ] ;
return dirminimo;
10.6. La función tiene, en primer lugar, un error de sintaxis en la sentencia return, ya que debe terminar
necesariamente en punto y coma ( ;) y no en coma ( , ) como así lo hace. Por otra parte, se observa que el b ucle for
itera pero siempre compara el mismo valor *v == k, y parece que hay otro error semántico y sintáctico, ya que es poco
probable que se programe un bucle para comparar un solo elemento. Tal vez, lo que el programador, haya querido
programar, sea una función que retorne la dirección de la primera ocurrencia de k en el vector v, por ello la codificación
debería ser la siguiente:
double* gorta (doubl e* v, int m, double k)
{
int j ;
for (j = 0; j < m; j++)
if (*v == k)
return v;
el se
V++ ;
return 0; // si no se encuentra retorna el valor de 0
• La primera llamada r = gorta (M , 10 , 12 . 3 ); es correcta ya que a un puntero voi d se le puede asignar cualquier oír
o tipo de punteros, y el valor de m es 12 que es menor o igual que 1 5 que es el tamaño declarado del array.
• La se gunda llamada cout « (*gorta(W, 15, 10. 5) es sintácticamente corr ecta. La ter cera llamada z = gorta (U, 15,
12. 3) es incorrecta ya que a una variable de tipo doubl e no puede asignársele un puntero a un tipo doub 1 e.
10.1. Se declara la estructura Persona con los atributos indicados, y se programa las dos funciones pedidas, ambas con
parámetros tipo puntero a Persona, con lo que el acceso a los miembros debe hacerse con -> Además, se programa
una llamada a la función mostrar_Persona usando un Array_de_Personas, previamente inicializado con la información
de dos personas, realizando las llamadas con un puntero p que toma antes de comenzar el bucle el valor de p =
Array_de_Personas.
La codificación de este problema se encuentra en la página Web del libro.
10.2. La función simetri ca decide si una matriz m cuadrada que recibe como parámetro es simétrica, por lo que es de
tipo boo 1. Esta función se codifica con tres parámetros bool simétrica (float **mat, int f, int c). El primero es un
puntero a puntero de reales, m en el que se recibe la matriz, el segundo, f, y el tercero, c, son respectivamente el
número de filas y de columnas, que en el caso de una matriz cuadrada debe coincidir. Es bien conocido que una matriz
es simétrica si cada uno de sus elementos es igual a su simétrico con r especio a la diagonal principal. Para resolver el
problema de decidir si una matriz es simétrica, se define una variable de tipo boo 1 s i me, inicializada a true. Esta
variable se pone a f al se cuando se está seguro de que la matriz no cumple la condición de simetría. El r ecorrido de
la matriz se hace mediante dos b ucles for anidados que avanzan por las posibles filas y columnas, siempre que la
condición de simetría siga cumpliéndose (se sale de cualquiera de los dos bucles si s i me toma el valor de fal se). Si en
una de las iteraciones se comprueba que no se cumple la condición “cada elemento es idéntico al que se obtiene
cambiando su fila por su columna” la variable, o interruptor s i me cambia de valor poniéndose a fal se.
Lajunción crearMatriz, genera aleatoriamente los datos de la matriz cuadr ada de ffilasy c columnas. Para hacerlo usa
las funciones randomi ze y random definidas en sendos macros, y que se encargan de generar la semilla y los sucesivos
números aleatorios en el rango de 1 y max =100.
El programa principal realiza las llamadas a las funciones e xplicadas anteriormente, para mostrar cómo debe realizarse
una invocación de las mismas. Se hace al propio tiempo una llamada a la función escribí r_matri z, cuyo prototipo es
incluido en el código, y cuya codificación, puede consultarse en el Ejemplo 10.11. A nivel global se referencian en
sentencias define el número de filas, el de columnas y el valor aleatorio máximo que se puede generar en los
correspondientes identificadores F, C, max.
La codificación de este problema se encuentra en la página Web del libro.
10.3. La función multiplicacolumna recibe como parámetro en forma de puntero a puntero de reales la matriz m, el
número de filas el de columnas, así como la columna neo 1 que se multiplica por la columna 0, un vector de punteros
vp como puntero a reales, donde se retorna el resultado. La codificación usa un bucle for que recorre las sucesivas jilas
de la matriz, para ir almacenando los resultados de los productos parciales de la columna 0 por la columna neo 1 en
las posiciones correspondientes del vector vp.
La función muestravector, se encarga de mostrar el vector v que recibe como parámetro (puntero a reales).
La función muestra_suma realiza la suma de las correspondientes componentes del vector que recibe como parámetro
visualizando el resultado.
El programa principal realiza las sucesivas llamadas a las funciones, usando, además, las funciones escribir_matriz y
crearMatriz cuyos prototipos son incluidos, y cuya codificación puede consultarse en el Problema 10.2.
La codificación de este problema se encuentra en la página Web del libro.
10.4. La función Intercambiafilas, recibe los números de las filas que debe intercambiar, nfl, nf2, y mediante un bucle
itera por cada una de las columnas ínter cambiando los elementos uno a uno. La función Suma f i las es la encargada
de sumar a la fila nfl, la fila nf2, realizándolo mediante su correspondiente bucle de columnas controlado por la variable
j. Para sumar a una fila nfl, una combinación lineal de filas, la función Sumacombi naci on, recibe los coeficientes de la
combinación en el vector vf (puntero a reales) y, posteriormente, por cada elemento j de la fila nfl, se la suma la
combinación lineal
f-1
m(nflj) = X m(i,j)*vf(i)
í=0
La codificación de este problema se encuentra en la página Web del libro.
10.5. La codificación de ambas funciones es casi trivial. Basta con recorrer todos los elementos de la matriz por filas y
columnas, efectuando los cálculos correspondientes
La codificación de este problema se encuentra en la página Web del libro.
10.6. Para almacenar el texto de entrada se declara un sinónimo de cha r* que es 1 inea, para que al declarar entrada
como un puntero a 1 i nea, se tenga un puntero que apunta a un puntero de caracteres. Esta es una forma de declarar
una matriz bidimensional de caracteres, de tal manera que cada una de las filas contenga una línea de la entr ada. Al
no declarar una matriz de caracteres como tal en el programa, es necesario disponer de memoria para la matriz,
reservando primeramente memoria para un vector de punteros a char con la orden entrada = new linea [20] y,
posteriormente, reservando memoria para cada una de las líneas mediante la or den entrada[i ] = new char[strl en(
cad)+l]. Esta variable cad, es una cadena de caracteres (puntero a carácter) a la que se le reserva memoria para
almacenar una línea completa de 80 caracteres. Ahora bien, cuando se reserva memoria a entrada [ i ], sólo se hace
con la longitud real que tenga la línea leída, sin desperdiciar espacio de memoria sin ser usada como ocurriría si hubiera
definido una matriz con todas las filas de la misma longitud. El programa que se presenta, lee las líneas del texto en
un bucle externo controlado por la variable i, almacenándolas en el arrav bidimensional entrada, para, posteriormente,
en otro bucle interno controlado por la variable j, ir tratando cada uno de los caracteres de la línea, para acumular las
vocales y poder visualizar el resultado del número de vocales leídas al final del bucle interno. Un vez terminada la
lectura de datos, se presenta el texto leído, así como el número total de vocales que tiene el texto.
La codificación de este problema se encuentra en la página Web del libro.
10.7. El primer paso consiste en definir una estructura t i empos para poder almacenar los minutos y segundos. El
segundo paso consiste en definir la estructura regnadador para almacenar los datos de cada nadador. Como la
estructura regnadador tiene miembros que son cadenas, se declaran punteros a carácter, para resen’ar sólo la
memoria que se necesite , una vez que se conozca la longitud de la cadena que se intr oduce en el campo. Al tener
que almacenar un máximo de 16 nadadores se define un array VectorNadadores que almacena la información de cada
uno de los nadadores, como punteros a estructuras de regnadador por lo que al principio del pr ograma se crea un
array de punteros sin inicializar, lo que ocupa poco espacio en memoria. Se gún se lea cada uno de los nadador es se
reservará espacio en memoria ajustado a la información que se almacena. El ahorr o en espacio de memoria es signif
i cativo cuando el número de registros, como en este so, es grande. Las función 1 eerregnadador se encarga de la
reserva de memoria para un registro de un nadador, y leer los datos introducidos por el usuario. Recibe como
parámetro por referencia un puntero reg a regnadador. Para visuali-
zar los datos de un nadador se emplea la función escribí rregnadador que recibe como parámetro un puntero a una
estructura regnadador. Por último, lafunción Desvi aci ónMedi a, calcula la desviación media en segundos del array de
nadadores, para lo que necesita una función Medí a Vector, encargada de calcular la media en se gundos de los
nadadores.
Las expresiones matemáticas de estas dos funciones son:
n-1
J^abs(a(i) - m)
m = f ^ a(i)j i n dm = —
La codificación de este problema se encuentra en la página Web del libro.
10.8. Se programan en primer lugar las funciones que calculan el ár ea de cada una de lasf ¡guras de acuerdo con las
correspondientes fórmulas:
Tri Rec = (c¡ * c 2 )/2
Cuacl = P Circ = p * r 2
El array areafi gura[] contiene los nombres de cada una de las funciones. Este array de nombres de las funciones es
llamado en el programa principal, dentro de un menú de opciones.
La codificación de este problema se encuentra en la página Web del libro.
10.9. El programa se ha estructurado de la siguiente forma: Lafunción 1 leer_registro, solicita al usuario todos los datos
de un registro, cuyos atributos han sido deciar ados en la estructura registro, retornando los resultados en el
parámetro por referencia reg. Esta función permite al usuario la posibilidad de no continuar con la entr ada de nuevos
registros de pacientes. La lectura de la información de todos los pacientes es realizada por lafunción 1 eervector. Esta
función retorna la información en vector, que es un parámetro recibido como puntero a registro. Lafunción mostrarl
as con su 1 tas, está encargada de visualizar los nombres de los pacientes que cumplan la condición de la fecha. Por
su parte el programa principal realiza las llamadas a las distintas funciones.
SEGUNDA PARTE
10.1 Escribir un programa en el que se lean 20 lineas de texto, cada linea con un máximo de 80 caracteres.
Mostrar por pantalla el número de vocales que tiene cada linea.
#include <stdio.h>
#include <stdlib.h>
# define L 20;
void datos(char *ln);
int main()
{
int rep;
char linea[80];
char *l;
l = &linea[0];
for(rep=0; rep < 20; rep++)
datos(l);
return 0;
}
void datos(char *ln){
int i;
int cont=0;
printf("Escriba las linea\n");
fgets(ln,80,stdin);
for(i=0; i<strlen(ln); i++){
if(*(ln+i)=='a' || *(ln+i)=='e' || *(ln+i)=='i' || *(ln+i)=='o' ||
*(ln+i)=='u')
cont++;
}
printf("numero de vocales en la frase: %d \n\n", cont);
}
10.2 Escribir un programa que encuentre una matriz de números reales simétrica. Para ello una función entera con
entrada a la matriz determinará si ésta es simétrica. En otra función se generará la matriz con números aleatorios de
1 a 19. Utilizar aritmética de apuntadores en la primera función; en la segunda, indexación.
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <time.h>
using namespace std;
void generarNumeros(int **matriz, int tam)
{
//Generando nçumeros aleatorios con indexación
/*for (int i =0; i < tam; i++)
{
for(int j=0; j < tam; j++)
{
matriz[i][j] = 1 + rand() % 19;
}
}*/
//Generando nçumeros aleatorios con aritmetica de punteros
for (int i=0; i < tam; i++ )
{
for(int j=0; j < tam; j++)
{
*(*(matriz+i)+j) = 1 + rand() % 19;
}
}
}
void imprimirMatriz(int **matriz, int tam)
{
// Imprimiendo por indexación
/*for (int i =0; i < tam; i++)
{
for(int j=0; j < tam; j++)
{
cout << matriz[i][j];
cout << " ";
}
cout << endl;
}*/
// Imprimiendo por aritmetica de punteros
for (int i=0; i < tam; i++ )
{
for(int j=0; j < tam; j++)
{
cout << *(*(matriz+i)+j);
cout << " ";
}
cout << endl;
}
}
void transpuesta(int **matriz, int tam)
{
int aux;
for (int i=0; i < tam; i++ )
{
for(int j=0; j < tam; j++)
{
if(i == j)
{
aux = *(*(matriz+i)+j);
*(*(matriz+i)+j) = *(*(matriz+j)+i);
*(*(matriz+j)+i) = aux;
}
}
}
}
int main()
{
srand(time(0));
int tamanyo;
int **matrizPrincipal; // puntero para dos dimensiones del arreglo
cout << "Problema 11.2 ----_____----" << endl << endl;
cout << "Ingrese el tamaño de la matriz: "; cin >> tamanyo;
matrizPrincipal = new int*[tamanyo]; /*asignacion de memoria de //n punteros a
//enteros*/
for (int i =0; i < tamanyo; i++)
matrizPrincipal[i] = new int[tamanyo]; /*asignacion de //memoria para cada
//entero*/
/*comprobar si fue creado */
if (matrizPrincipal == NULL)
{
cout << "No se pudo crear la matriz" << endl;
}
generarNumeros(matrizPrincipal, tamanyo);
imprimirMatriz(matrizPrincipal, tamanyo);
cout << endl << endl;
// matriz transpuesta
cout << endl << "***MATRIZ TRANSPUESTA***" << endl;
transpuesta(matrizPrincipal, tamanyo);
imprimirMatriz(matrizPrincipal, tamanyo);
return 0;
}