Asignación dinámica de memoria
Para cada función, el compilador de C/C++ reserva una cierta cantidad de memoria para almacenar las variables locales.
En algunas ocasiones será necesario utilizar un arreglo que requiera una mayor cantidad de memoria:int main() { int arreglote[1024 * 1024]; return 0;}
Asignación dinámica de memoria
La solución consiste en asignar memoria a un arreglo de manera dinámica mediante el operador new:
int main() {
int i, n = 1024 * 1024;
int *a = new int[n];
if (a != NULL) {
for (i = 0; i < n; i++) { a[i] = i; }
delete[] a;
}
return 0;
}
Es importante siempre liberar la memoria reservada mediante el operador delete[] una vez que ya no se utiliza.
El apuntador NULL
El lenguage C/C++ define una constante especial llamada NULL, el cual es un apuntador que no apunta a ningún lugar válido en la memoria y tiene valor numérico cero.
Se recomienda siempre inicializar los apuntadores con una dirección válida, o bien, con NULL, de manera que no sea posible sobreescribir información accidentalmente.
El operador new devuelve NULL si no es capaz de reservar la cantidad de memoria solicitada. Esto permite detectar la falta de memoria en un programa.
Práctica
Declare un arreglo bidimensional X de M x N elementos como un “arreglo de arreglos” y llénelo con números aleatorios entre 0 y 10.
Imprima las direcciones de memoria de cada uno de los elementos y verifique que éstos están organizados en orden lexicográfico.
Declare un apuntador p y asígnele la dirección del primer elemento de X. Ahora p actúa como un arreglo unidimensional que hace referencia a los mismos elementos que X, pero en orden lexicográfico. Utilice p para imprimir el contenido del arreglo.
Ejercicios
Escriba una función llamada promedio(x,n) que calcule y devuelva el promedio de un arreglo x de tamaño n. Escriba otra función llamada punto(x,y,n) que devuelva el producto punto de dos vectores x y y, ambos de tamaño n.
Considere el problema de regresión lineal simple, donde uno desea encontrar una función de la forma y(x) = mx + b, dado un conjunto de n datos (xi , yi). Se puede demostrar que los parámetros de la recta que mejor se ajusta a los datos están datos por:donde · representa el producto punto, y x denota el promedio de x.Escriba una función que tome x, y, n como argumentos y que calcule y devuelva m y b. Escriba un programa que genere un conjunto de 1,000,000 de datos de prueba con el modelo yi = 3xi – 5 + ei, donde xi ~ U(-100,100) y ei ~ U(-10,10), y luego utilice la función anterior para recuperar m y b a partir de los datos de prueba.
_
Ejercicios
Escriba una función llamada genera(F, m, n, p) que genere una matriz binaria aleatoria F de tamaño m x n donde cada elemento sea igual a 1 con probabilidad p.
Escriba una función llamada imprime(F, m, n) que borre la pantalla (usando system(“cls”)) y luego imprima la matriz binaria F de tamaño m x n, donde los ceros se imprimirán como espacios en blanco y los unos como asteriscos.
Escriba una función llamada evolucion(F, G, m, n) que tome como parámetros dos matrices de enteros, F y G, de tamaño m x n, donde cada elemento es binario (0 ó 1). Digamos que si un elemento vale 1, la celda correspondiente está “viva”. La función debe calcular Gi,j a partir de los “vecinos” de Fi,j, considerando las siguientes reglas:
Si una celda viva tiene menos de dos vecinos vivos, entonces morirá.
Si una celda viva tiene mas de tres vecinos vivos, entonces morirá.
Una celda viva continuará en ese estado solamente si tiene dos o tres vecinos vivos.
Una celda muerta cobrará vida si tiene tres vecinos vivos, de lo contrario continuará en ese estado.
Usando las tres funciones anteriores, escriba un programa que implemente el juego de la vida: el programa iniciará mostrando una matriz binaria aleatoria, y luego, de manera iterativa, encontrará una nueva matriz realizando una evolución, la mostrará en pantalla, y esperará a que el usuario presione la tecla Enter (usando la función getchar()). La iteración continuará hasta que el usuario presione la tecla ‘x’ (seguida de Enter).
Flujos de entrada y salida en C++
En C++, las operaciones de entrada y salida se manejan a través objetos llamados flujos.
Existen tres librerías estándar para el manejo de flujos:
para entrada desde y salida hacia consola
para entrada desde y salida hacia archivos
para entrada desde y salida hacia objetos tipo string (cadenas de caracteres).
Flujos de archivos
La librería define los elementos necesarias para el manejo de archivos. Los mas importantes son:
ofstream : clase de datos utilizada para escritura de archivos.
ifstream : clase de datos utilizada para lectura de archivos.
Apertura y cierre de archivos
Para acceder a un archivo (escritura o lectura) es necesario siempre abrir primero el archivo mediante la función open(), que recibe como parámetro el nombre del archivo.
De igual manera, una vez que finaliza el acceso al archivo, es necesario cerrarlo mediante la función close().
Ejemplo: creación de un archivo de salidaofstream of;of.open(“archivo.txt”);of << “Hola mundo!” << endl;of.close();
Escritura de archivos de texto
Como se observó en el ejemplo anterior, la escritura de datos en un archivo de texto se realiza mediante el operador de inserción <<, al igual que con la instrucción cout.
Ejemplo
Muchos programas como Excel o Matlab pueden leer archivos de datos en forma de matriz, los cuales son fáciles de exportar desde un programa en C++.
int main() {
float x, y, r;
int i, int n = 100;
ofstream of(“datos.txt”);
for (i = 0; i < n; i++) {
x = 10.0 * rand() / RAND_MAX – 5.0;
r = 1.0 * rand() / RAND_MAX – 0.5;
y = 0.5 * x – 3.0 + r;
of << x << “t” << y << endl;
}
of.close();
}
Ejemplo
Muchos programas como Excel o Matlab pueden leer archivos de datos en forma de matriz, los cuales son fáciles de exportar desde un programa en C++.
int main() {
float x, y, r;
int i, int n = 100;
ofstream of(“datos.txt”);
for (i = 0; i < n; i++) {
x = 10.0 * rand() / RAND_MAX – 5.0;
r = 1.0 * rand() / RAND_MAX – 0.5;
y = 0.5 * x – 3.0 + r;
of << x << “t” << y << endl;
}
of.close();
}
El archivo puede abrirse desde el momento de declararlo
Ejemplo
Muchos programas como Excel o Matlab pueden leer archivos de datos en forma de matriz, los cuales son fáciles de exportar desde un programa en C++.
int main() {
float x, y, r;
int i, int n = 100;
ofstream of(“datos.txt”);
for (i = 0; i < n; i++) {
x = 10.0 * rand() / RAND_MAX – 5.0;
r = 1.0 * rand() / RAND_MAX – 0.5;
y = 0.5 * x – 3.0 + r;
of << x << “t” << y << endl;
}
of.close();
}
El archivo puede abrirse desde el momento de declararlo
Los datos generados pueden graficarse en Excel fácilmente
Lectura de archivos de texto
De manera similar, podemos leer de un archivo de texto al igual que se hace con la instrucción cin:
int main() {
int n, k, N = 4096;
float x[N], X[N * 2];
ifstream in(“eeg.txt”);
ofstream out(“espectro.txt”);
for (n = 0; n < N; n++) { in >> x[n]; }
fft(x, X, N);
for (k = 0; k < N/2; k++) {
out << sqrt(X[k] * X[k] + X[k+N] * X[k+N]) << endl;
}
return 0;
}
Lectura de archivos de texto
Señal de EEG
Espectro de frecuencias de la señal
Algunas funciones adicionales
El operador ! puede utilizarse para saber si un archivo se abrió correctamente. En caso de haber algún problema, este operador devuelve verdadero.
Es posible leer una línea completa de un archivo de texto y almacenarla en una cadena, mediante la función getline(char *s, int n).
Para detectar si se ha llegado al final del archivo, se puede utilizar la función eof().
Ejemplo
// Esta función imprime el contenido de un archivo
void muestra_archivo(char *s) {
int n = 65536;
char temp[n];
ifstream in(s);
if (!in) return;
while (!in.eof()) {
in.getline(temp, n);
if (!in.eof()) { cout << temp << endl; }
}
in.close();
}
int main() {
muestra_archivo(“ejemplo.cpp”);
return 0;
}
Ejemplo
// Esta función imprime el contenido de un archivo
void muestra_archivo(char *s) {
int n = 65536;
char temp[n];
ifstream in(s);
if (!in) return;
while (!in.eof()) {
in.getline(temp, n);
if (!in.eof()) { cout << temp << endl; }
}
in.close();
}
int main() {
muestra_archivo(“ejemplo.cpp”);
return 0;
}
Verifica la apertura del archivo
Ejemplo
// Esta función imprime el contenido de un archivo
void muestra_archivo(char *s) {
int n = 65536;
char temp[n];
ifstream in(s);
if (!in) return;
while (!in.eof()) {
in.getline(temp, n);
if (!in.eof()) { cout << temp << endl; }
}
in.close();
}
int main() {
muestra_archivo(“ejemplo.cpp”);
return 0;
}
Iterar hasta llegar al final del archivo
Ejemplo
// Esta función imprime el contenido de un archivo
void muestra_archivo(char *s) {
int n = 65536;
char temp[n];
ifstream in(s);
if (!in) return;
while (!in.eof()) {
in.getline(temp, n);
if (!in.eof()) { cout << temp << endl; }
}
in.close();
}
int main() {
muestra_archivo(“ejemplo.cpp”);
return 0;
}
Leer la siguiente línea del archivoy almacenarla en la cadena temp
Página anterior | Volver al principio del trabajo | Página siguiente |