2008-10-24 20 views
5

Estoy empezando a aprender C++ así que discúlpeme por esta simple pregunta. Lo que estoy haciendo es leer en números de un archivo y luego tratar de agregarlos a una matriz. Mi problema es ¿cómo se aumenta el tamaño de la matriz? Por ejemplo pensé que podría ser capaz de simplemente hacer:Arrays dinámicos

#include <iostream> 
using namespace std; 

int main() { 
    double *x; 
    x = new double[1]; 
    x[0]=5; 
    x = new double[1]; 
    x[1]=6; 
    cout << x[0] << "," << x[1] << endl; 
    return 0; 
} 

Pero esto, obviamente, sólo sobrescribe el valor, 5, que en un principio me puse a x [0] y así da salida a 0,6. ¿Cómo lo haría para que salga 5,6?

Por favor, tenga en cuenta que para el ejemplo que he incluido no quise saturarlo con el código que se lee de un archivo o código para obtener números de un usuario. En la aplicación real, no sabré cuán grande es el arreglo que necesito en el momento de la compilación, así que no me digan que haga una matriz con dos elementos y configúrelos igual a 5 y 6 respectivamente.

Gracias por su ayuda.

Respuesta

17

No desea trabajar con matrices directamente. Considere usar un vector, en su lugar. Luego, puede llamar a la función push_back para agregar cosas al final y automáticamente cambiará el tamaño del vector.

#include <iostream> 
#include <vector> 

int 
main() { 
    double value; 
    std::vector<double> values; 

    // Read in values 
    while (std::cin >> value) { 
     values.push_back(value); 
    } 

    // Print them back out 
    for (std::size_t i(0), len(values.size()); i != len; ++i) { 
     std::cout << values[i]; 
    } 
} 
+0

Sin embargo, debes tener cuidado con los vectores, ya que tienden a ser bastante lentos en el uso. – Huppie

+0

Lento es relativo. es decir, perfila tu programa y ve si impacta las cosas. Si lo hace, escriba un asignador personalizado, optimizado para asignar dobles (y objetos de tamaño 'sizeof (double)'). –

+0

No será más lento que hacer el cambio de tamaño con nuevo, eliminar y copiar. –

4

Debe utilizar una clase de colección para hacer esto por usted en lugar de hacerlo usted mismo. Eche un vistazo a la clase "vector". Es esencialmente una matriz dinámica que cambia el tamaño automáticamente según sea necesario.

En su situación usaría "vector" con el tipo "doble". Es posible que también necesite leer plantillas en C++.

http://www.cplusplus.com/reference/stl/vector/

4

O, si usted no desea utilizar STL u otra cosa dinámica, sólo puede crear la matriz con el tamaño correcto desde el principio: x = new double [2];

Por supuesto, el problema es qué tan grande es para hacerlo. Si no lo sabe, tendrá que crearlo "lo suficientemente grande" (como cien o mil) ... que, en algún momento, no será lo suficientemente grande y fallará en algunos de forma aleatoria. Entonces necesitarás redimensionarlo. Y una vez que llegas a ese punto, desearás haber usado el STL desde el principio, como las otras respuestas te dicen que hagas.

#include <iostream> 
using namespace std; 
int main() { 
    double *x = new double[2]; 
    x[0]=5; 
    x[1]=6; 
    cout << x[0] << "," << x[1] << endl; 
    return 0; 
} 
2

Si por alguna razón usted no tiene acceso a STL - o quiere aprender a hacer esto por sí mismo - se puede utilizar un algoritmo de esta manera:

Asignar la matriz como algunos arbitraria tamaño, y recordar cuántos elementos hay en él y lo grande que es:

int *a = malloc(int * ARBITRARY_SIZE); 
int size = 0; 
int allocated = ARBITRARY_SIZE; 

cada vez que se agrega un nuevo elemento, aumentar el "tamaño". Si el tamaño es igual a ARBITRARY_SIZE, multiplica "allocation" por 2 y reasigna la matriz. De cualquier manera, asigne el nuevo valor a un [tamaño].

void addElement(int value) { 
    ++size; 

    if (size == allocated) { 
    allocated *= 2; 
    a = realloc(sizeof(int) * allocated); 
    a = new_a; 
    } 

    a[size] = value; 
} 

Tenga en cuenta que el código anterior tiene al menos un error - no se están asignando espacio suficiente para x [1] en cualquiera de los casos.

También, obviamente, en el código real se comprobaría que el retorno de malloc & realloc no es nulo.

+0

También es tradicional verificar el valor de retorno de malloc para null. A diferencia de lo nuevo, no arroja std :: bad_alloc en el fallo, y los volcados del núcleo son más difíciles de depurar que los falsos ;-) –

+0

Se realizaron cambios. Aunque los volcados del núcleo son mucho más fáciles de depurar que la mayoría de los otros errores :) –

3

He aquí un ejemplo, aunque en buena medida, por lo que puede ver el patrón:

#include <iostream> 
using namespace std; 

int main() { 
    // Allocate some memory for a double array of size 1 and store 
    // an address to the beginning of the memory in mem_address. 
    double* mem_address = new double[1]; 

    // Assign 5 to the first element in the array. 
    mem_address[0] = 5; 

    // Save the address of the memory mem_address is currently 
    // referencing. 
    double* saved_address = mem_address; 

    // Allocate some memory for a double array of size 2 and store 
    // an address to the beginning of the memory in mem_address. 
    mem_address = new double[2]; 

    // Copy over the 1 element from the first memory block 
    // to the new one. 
    mem_address[0] = saved_address[0]; 

    // Done with the old memory, so clean it up. 
    delete [] saved_address; 

    // Assign 6 to the second element in the new array. 
    mem_address[1] = 6; 

    // Print out the 2 elements in the new array. 
    cout << mem_address[0] << "\n"; 
    cout << mem_address[1] << "\n"; 

    // Done with the new array memory now, so clean it up. 
    delete [] mem_address; 
} 
0

Una matriz siempre tiene un bloque contiguo de memoria. En una situación en la que es posible que necesite cambiar el tamaño de la matriz más adelante, la reasignación es probablemente la única solución. Esto es lo que Moishe y Shadow2531 hacen arriba.

El problema con la reasignación es que puede ser una operación costosa. Entonces, si necesita agregar 5 elementos más a una matriz de 5000 elementos, puede terminar copiando todos los 5000 elementos en la memoria.

El uso de una lista vinculada en su lugar se puede considerar para ese escenario.