2008-10-24 16 views
5

Po prostu zaczynam uczyć się języka C++, więc przepraszam za to proste pytanie. Co robię, to czytanie liczb z pliku, a następnie próby dodania ich do tablicy. Mój problem polega na tym, jak zwiększyć rozmiar tablicy? Na przykład ja, że ​​może być w stanie po prostu zrobić:Dynamic Arrays

#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; 
} 

Ale to oczywiście tylko nadpisuje wartość, 5, że początkowo ustawione na X [0], a więc generuje 0,6. Jak mam to zrobić, aby uzyskać wynik 5,6?

Proszę zdać sobie sprawę, że na przykład, który zamieściłem, nie chciałem zaśmiecać go odczytem kodu z pliku lub kodu, aby uzyskać liczby od użytkownika. W aktualnym zgłoszeniu nie będę wiedział, jak dużą część tablicy potrzebuję w czasie kompilacji, więc proszę, nie mów mi, żebym po prostu tworzył tablicę z dwoma elementami i ustawiał je odpowiednio na 5 i 6.

Dzięki za pomoc.

Odpowiedz

17

Nie chcesz pracować bezpośrednio z tablicami. Zamiast tego należy rozważyć użycie vector. Następnie możesz wywołać funkcję push_back, aby dodać rzeczy do końca, a ona automatycznie zmieni rozmiar wektora.

#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

Musisz być ostrożny z wektorami, ale są one dość powolne w użyciu. – Huppie

+0

Powolne jest względne. tzn. profiluj swój program i zobacz, czy ma to wpływ na rzeczy. Jeśli tak, napisz niestandardowy alokator, zoptymalizowany do alokowania dubletów (i obiektów o rozmiarze 'sizeof (double)'). –

+0

To nie będzie wolniejsze niż zmiana rozmiaru za pomocą nowych, usuwania i kopiowania. –

4

Powinieneś użyć klasy kolekcji, aby zrobić to za ciebie, zamiast zarządzać nią samodzielnie. Zobacz klasę "vector". Jest to w istocie dynamiczna tablica, która zmienia się automatycznie w razie potrzeby.

W twojej sytuacji używałbyś "wektora" z "podwójnym" typem. Może zajść potrzeba przeczytania szablonów w C++.

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

4

Lub, jeśli nie chcesz używać STL lub inny dynamiczny rzecz, można po prostu stworzyć tablicę z odpowiednim rozmiarze od początku: x = new double [2];

Oczywiście problem jest taki, jak duży. Jeśli nie wiesz, to musisz po prostu stworzyć "wystarczająco duży" (np. Sto lub tysiąc) ... który w pewnym momencie nie będzie wystarczająco duży, aw niektórych losowo wyglądający sposób. Więc musisz zmienić jego rozmiar. A kiedy dojdziesz do tego punktu, będziesz żałował, że nie używałeś STL od samego początku, tak jak inne odpowiedzi każą ci to zrobić.

#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

Jeśli z jakiegoś powodu nie mają dostępu do STL - albo chcesz dowiedzieć się, jak to zrobić samemu - można użyć algorytmu takiego:

Przeznaczyć swoją tablicę, jak niektóre arbitralne rozmiar i pamiętam ile elementy są w niej i jak duże jest:

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

za każdym razem dodać nowy element, zwiększyć „rozmiar”. Jeśli rozmiar jest równy ARBITRARY_SIZE, pomnóż "przydzielony" przez 2 i ponownie przyłóż tablicę. Tak czy inaczej, przypisz nową wartość do [rozmiaru].

void addElement(int value) { 
    ++size; 

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

    a[size] = value; 
} 

Należy zauważyć, że powyższy kod zawiera co najmniej jeden błąd - w obu przypadkach nie przydzielono wystarczającej ilości miejsca dla x [1].

Oczywiście w prawdziwym kodzie sprawdzasz, czy zwrot z malloc & nie jest zerowy.

+0

To także tradycyjne sprawdzanie wartości zwracanej z malloc dla wartości null. W przeciwieństwie do nowych nie rzuca std :: bad_alloc na niepowodzenie, a zrzuty pamięci są trudniejsze do debugowania niż nieudane potwierdzenia ;-) –

+0

Dokonano zmian. Chociaż podstawowe zrzuty są znacznie łatwiejsze do debugowania niż większość innych błędów :) –

3

Oto przykład chociaż środek na dobre, więc można zobaczyć wzór:

#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

Tablica zawsze potrzebuje ciągłego bloku pamięci. W sytuacji, gdy może zajść potrzeba późniejszej zmiany rozmiaru tablicy, realokacja jest prawdopodobnie jedynym rozwiązaniem. To właśnie robią Moishe i Shadow2531 powyżej.

Problem z realokacją polega na tym, że może to być kosztowna operacja. Więc jeśli potrzebujesz dodać 5 dodatkowych elementów do tablicy 5000 elementów, możesz skończyć kopiowanie wszystkich 5000 elementów w pamięci.

Zamiast tego można rozważyć użycie takiej listy dla takiego scenariusza.