1
votes

Erreurs avec tableau dynamique créé avec nouveau après avoir été passé à la fonction de redimensionnement

J'essaie d'implémenter un tableau créé dynamiquement en utilisant new que je veux redimensionner mais l'action de redimensionnement ne fonctionne pas correctement.

Ceci est un exercice sur les tableaux dynamiques, j'ai donc besoin de tableaux dynamiques utilisant new et non std::vector .

Voici mon code:

int main ()
{
    // Build an application here
    int length = 0;
    int size = 0;
    int input;
    bool endAdding = false;

    cout << "Please enter the length of the new array : ";
    cin >> length;

    int* oPtrDynamicArray = CreateDynamicArray (length, size);

    do
    {
        cout << "Add an element (0 to quit) : " << endl;
        cin >> input;
        cout << endl << endl;

        if (input == 0){
            endAdding = true;
        }
        else
        {
            InsertElement(oPtrDynamicArray, input, size, length);
        }
        cout << "The array contains : " << endl;
        for (int i = 0; i < size; i++)
        {
            cout << i << ": [" << oPtrDynamicArray[i] << "]" << endl;
        }
    } while (!endAdding);

    DeleteDynamicArray (oPtrDynamicArray, size);
}

int *CreateDynamicArray (int capacity, int &size)
{
    size = 0;
    return new int[capacity];
}

void DeleteDynamicArray (int *dynamicArray, int &size)
{
    delete[] dynamicArray;
    dynamicArray = nullptr;
    size = 0;
}

void InsertElement (int *dynamicArray, int element, int &size, int capacity)
{
    if (capacity <= size)
    {
        ResizeDynamicArray (&dynamicArray, size+1);
    }

    dynamicArray[size] = element;
    size++;

}

void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
    int ** newArray = new int*[newCapacity];
    for (int i = 0; i < newCapacity; i++) 
    {
        newArray[i] = dynamicArray[i];
    }

    *dynamicArray = *newArray;

    delete[] newArray;
    newArray = nullptr;
}

Le problème est que le tableau est passé à ma fonction InsertElement() puis à ResizeDynamicArray() uniquement si la capacity <= size , mais le tableau passé à la première fonction, est passé avec de bonnes valeurs, mais avec des pointeurs anormaux dans le tableau.

Exemple :

Pour un tableau de 3, j'ai:

tableau [0] = 1 -> adresse 0x0004e300 contenant la valeur 1

tableau [1] = 2 -> adresse 0x00000003 contenant ???

array [2] = 3 -> adresse 0x008ffb24 contenant la valeur 2

Je ne comprends vraiment pas, ce serait vraiment génial si quelqu'un pouvait expliquer mon erreur: /.


4 commentaires

Un std :: vector est un tableau dynamique.


Ce que vous décrivez est impossible. Votre "tableau dynamique" est un tableau simple de style C - qui se désintègre en int * que vous tenez. Ses éléments sont des entiers , pas des pointeurs , et ont des adresses consécutives (en multiples de sizeof(int) bien sûr) - ils ne peuvent pas avoir les adresses que vous avez répertoriées dans votre exemple.


Je sais que c'est bien, mais pour mon exercice, je ne dois pas utiliser de vecteur: /


Et je ne comprends vraiment pas trop ces adresses, c'est mon débogueur qui me montre celles-ci: / Ce sont les références du "dynamicArray" dans "InsertElement ()" Mais cela crée un problème après, j'obtiens une exception à chaque fois au hasard sur resizedArray


3 Réponses :


1
votes

Le problème est là

void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
    int * newArray = new int[newCapacity];
    for (int i = 0; i < newCapacity; i++) 
    {
        newArray[i] = (*dynamicArray)[i];
    }

    delete[] *dynamicArray;
    *dynamicArray = newArray;
}

lorsque vous appelez ResizeDynamicArray vous modifiez le pointeur dynamicArray déclaré en tant que paramètre à InsertElement . Vous ne modifiez pas le pointeur oPtrDynamicArray dans main.

Si vous voulez que cela fonctionne, vous devez modifier InsertElement pour prendre un double pointeur (tout comme ResizeDynamicArray )

void InsertElement (int **dynamicArray, int element, int &size, int capacity)
{
    if (capacity <= size)
    {
        ResizeDynamicArray (dynamicArray, size+1);
    }
    (*dynamicArray)[size] = element;
    size++;
}

Ou vous pouvez faire la chose facile et utiliser simplement std::vector<int> .

EDIT maintenant que je regarde votre fonction ResizeDynamicArray , je vois que cette fonction est également complètement fausse. Il est clair que vous avez appris à faire avec les pointeurs

Voici comment ResizeDynamicArray devrait être

void InsertElement (int *dynamicArray, int element, int &size, int capacity)
{
    if (capacity <= size)
    {
        ResizeDynamicArray (&dynamicArray, size+1);
    }
    dynamicArray[size] = element;
    size++;
}

Vous n'êtes pas le premier débutant à ne pas comprendre les pointeurs. Jetez un œil au code ci-dessus et comparez-le avec votre code. La principale différence est que mon code utilise un pointeur pour changer ce qui est pointé . Votre code a essayé de modifier le pointeur lui-même, ce qui est incorrect. C'est déroutant car ce qui est pointé est un autre pointeur (le tableau dynamique).


3 commentaires

Mmmmh J'ai essayé cela avant, mais cela ne fonctionnait pas parce que je ne savais pas que je pouvais attribuer une valeur comme celle-ci pour dynamicArray Merci, cela fonctionne maintenant, mais le problème est maintenant la fonction deleteArray, avec une exception "Heap Corruption Detected". J'ai vu que je devais faire de même, en passant par référence, alors je l'ai fait, mais ça ne marche pas du tout ...


C'est pourquoi je m'exerce spécifiquement sur les tableaux, je viens du développement web donc c'est super dur pour moi pointer ^^. Merci de votre aide ! :RÉ


Aaaaaaaaaaa et ça marche !! Merci pour votre aide, donc le gros problème était que je mélangeais entre les tableaux d'int, les tableaux de pointeur et le pointeur sur int -_-. J'ai encore besoin de beaucoup de pratique pour bien le comprendre.



0
votes

Il y a plusieurs problèmes dans votre code:

Tout d'abord, dans ResizeDynamicArray , vous ResizeDynamicArray un tableau de pointeurs aux entiers, pas un tableau d'entiers. int ** newArray = new int*[newCapacity] doit être int *newArray = new int[newCapacity] .

Deuxièmement, une fois que vous avez corrigé cela, vous devez écrire *dynamicArray = newArray; ; mais vous devez libérer l'ancien tableau avant d'affecter le pointeur au nouveau bloc de mémoire.

void InsertElement (int **dynamicArray, int element, int &size, int capacity)

Troisièmement, puisque InsertElement peut appeler ResizeDynamicArray (qui vous rendra un nouveau bloc de mémoire), vous devez modifier le pointeur passé à l'origine. Vous devez donc passer un pointeur vers un pointeur dans la fonction, comme vous l'avez fait avec ResizeDynamicArray :

void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
    int *newArray = new int[newCapacity];
    for (int i = 0; i < newCapacity; i++) 
    {
        newArray[i] = (*dynamicArray)[i];
    }

    delete[] *dynamicArray;
    *dynamicArray = newArray;
}

adapter le corps en conséquence alors.


1 commentaires

Mais comment fonctionne votre mission ?? Il me dit "La valeur de type int * ne peut pas être attribuée à une entité de type int" ?? J'allais comme ça, mais parce que je ne l'ai pas compris, j'ai changé la stratégie pour celle-ci (c'est évidemment faux grâce à votre explication: O)



0
votes

Je sais que la question est déjà répondue mais pas le pourquoi.

Vous devez garder à l'esprit que les pointeurs sont passés aux fonctions par valeur . La valeur du pointeur, l'adresse vers laquelle il pointe , est perdue lorsque la fonction se termine. Mais vous pouvez toujours modifier la valeur stockée à l'adresse vers laquelle elle pointe en déréférençant le pointeur.

Pour réussir à changer la valeur du pointeur, l'adresse vers laquelle il pointe , à l'intérieur d'une fonction, vous devez passer un pointeur vers un pointeur. Dans ce cas, le passage d'un double pointeur est synonyme de passage d'un pointeur vers une fonction par référence .

void Foo(int **ptr) 
{
    // Don't use ptr, changes are lost after function end as ptr is a local copy
    // Use *ptr to change the value of the pointer you passed to the function.
    // Use **ptr to change the value at the address the pointer you passed to the funcion points to
}

Dans ce cas, vous pouvez modifier la valeur du pointeur, l'adresse vers laquelle il pointe , en déréférençant une fois le double pointeur. Ce qui s'applique aux réponses ci-dessus.


0 commentaires