Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Khronos14 en 31 Diciembre 2010, 16:40 pm



Título: Problema con arrays dinámicos
Publicado por: Khronos14 en 31 Diciembre 2010, 16:40 pm
Hola, practicando un poco con punteros me surgió un problema. Estoy creando una clase llamada TStringList (como la que existe en Delphi) y creé una función Add(). Funciona bastante bien, el problema ocurre cuando introduces más de 5 o 6 cadenas, que la primera cadena se pierde y salen caracteres raros.

Código main.

Código
  1. #include <iostream>
  2. #include "stringlist.h"
  3.  
  4. using namespace std;
  5.  
  6. const int CHAR_MAX_LENGTH = 20;
  7.  
  8. int showmenu()
  9. {
  10. int option = 0;
  11.    do
  12.    {
  13.        cout << "1.- Añadir string" << endl;
  14.        cout << "2.- Mostrar strings" << endl;
  15.        cout << "3.- Salir" << endl;
  16.        cout << "Introduce una opcion: ";
  17.        cin >> option;
  18.    }while(option < 1 && option > 3);
  19. return option;
  20. }
  21.  
  22. int main()
  23. {
  24. char buff[CHAR_MAX_LENGTH];
  25. int option = 0;
  26. TStringList *List = new TStringList();
  27.        do
  28.        {
  29.            option = showmenu();
  30.            switch(option)
  31.            {
  32.                case 1: cout << "Introduce una cadena: ";
  33.                        cout.flush();
  34.                        cin >> buff;
  35.                        List->Add(buff);
  36.                        break;
  37.                case 2: for (int i = 0; i < List->GetCount(); i++)
  38.                            cout << "Item " << i + 1 << ": " << List->GetItem(i) << endl;
  39.  
  40.                        break;
  41.            }
  42.  
  43.        }while(option != 3);
  44. delete(List);
  45. return 0;
  46. }
  47.  
  48.  

Código stringlist.h
Código
  1. #ifndef _H_STRINGLIST
  2. #define _H_STRINGLIST
  3.  
  4. struct SL_ITEM{
  5.    char *string;
  6. };
  7.  
  8. class TStringList{
  9.    private:
  10.        SL_ITEM *Items;
  11.        long numItems;
  12.    public:
  13.        TStringList();
  14.        ~TStringList();
  15.        void Add(char *cadena);
  16.        long GetCount();
  17.        char * GetItem(long Index);
  18. };
  19.  
  20. #endif
  21.  
  22.  

Código stringlist.cpp
Código
  1. #include "stringlist.h"
  2. #include <memory>
  3. #include <malloc.h>
  4. #include <string.h>
  5.  
  6. TStringList::TStringList()
  7. {
  8.    numItems = 0;
  9. }
  10.  
  11. TStringList::~TStringList()
  12. {
  13.    if (numItems > 0)
  14.    {
  15.            for (int i = 0; i < numItems; i++)
  16.                Items[i].string = NULL;
  17.            Items = NULL;
  18.         /*
  19.               Aquí también tengo alguna duda.
  20.               Probé con delete [] Items; pero compilado en Linux me suelta un stack error, en Windows, simplemente se cierra la aplicación  :huh:
  21.          */
  22.    }
  23.  
  24. }
  25.  
  26. void TStringList::Add(char *cadena)
  27. {
  28.    if (numItems > 0){
  29.        SL_ITEM * NewItems = (SL_ITEM*) malloc((numItems + 1) * sizeof(SL_ITEM));
  30.        /*for (int i = 0; i < numItems; i++)
  31.             {
  32.                 NewItems[i].string = (char *) malloc(strlen(Items[i].string) + 1);
  33.                 strcpy(NewItems[i].string, Items[i].string);
  34.             }*/
  35.        memcpy(NewItems, Items, sizeof(*Items));
  36.        memcpy(Items, NewItems, sizeof(*NewItems));
  37.        NewItems = NULL; //Creo que no hace falta
  38.    }
  39.    else Items = (SL_ITEM*) malloc(sizeof(SL_ITEM));
  40.        Items[numItems].string = (char *) malloc(strlen(cadena) + 1);
  41.        strcpy(Items[numItems].string, cadena);
  42.        numItems++;
  43. }
  44.  
  45. long TStringList::GetCount()
  46. {
  47.    return numItems;
  48. }
  49.  
  50. char * TStringList::GetItem(long Index)
  51. {
  52.    if (Index < numItems && Index >= 0)
  53.        return Items[Index].string;
  54.    else return NULL;
  55. }
  56.  
  57.  

Espero que puedan echarle un ojo y comentar.

Saludos.


Título: Re: Problema con arrays dinámicos
Publicado por: leogtz en 31 Diciembre 2010, 18:23 pm
@Khronos14, creo que aquí debes trabajar con listas enlazadas, no con arreglos, sería la mejor opción al ir cambiando la longitud de la lista.


Título: Re: Problema con arrays dinámicos
Publicado por: Khronos14 en 31 Diciembre 2010, 19:29 pm
Hola Leo Gutiérrez, gracias por responder. También pensé en utilizar listas enlazadas, pero son más lentas, ya que son de acceso secuencial.

Saludos.


Título: Re: Problema con arrays dinámicos
Publicado por: leogtz en 31 Diciembre 2010, 20:45 pm
Los beneficios serían mayores, para agregar elementos solo tendrías que mover un apuntador, algo sencillo, no sería tanto rollo. Sin contar que estarías trabajando en verdad con listas, no simulando listas con arreglos.


Título: Re: Problema con arrays dinámicos
Publicado por: Khronos14 en 31 Diciembre 2010, 23:04 pm
Bueno, al final lo conseguí. Sustituí malloc() por new y se arregló todo. Además añadí un método para borrar elementos del array dinámico.

Código
  1. #include "stringlist.h"
  2. #include <string.h>
  3.  
  4. TStringList::TStringList()
  5. {
  6.    numItems = 0;
  7. }
  8.  
  9. TStringList::~TStringList()
  10. {
  11.    if (numItems > 0)
  12.            delete [] Items;
  13. }
  14.  
  15. void TStringList::Add(char *cadena)
  16. {
  17.    if (numItems > 0){
  18.        SL_ITEM * NewItems = new SL_ITEM[numItems + 1];
  19.        for (int i = 0; i < numItems; i++)
  20.            {
  21.                NewItems[i].string = new char[strlen(Items[i].string) + 1];
  22.                strcpy(NewItems[i].string, Items[i].string);
  23.            }
  24.        delete [] Items;
  25.        Items = NewItems;
  26.    }
  27.    else Items = new SL_ITEM[1];
  28.        Items[numItems].string = new char[strlen(cadena) + 1];
  29.        strcpy(Items[numItems].string, cadena);
  30.        numItems++;
  31. }
  32.  
  33. bool TStringList::DeleteItem(long Index)
  34. {
  35.    if (Index >= 0 && Index < numItems)
  36.    {
  37.        SL_ITEM * NewItems = new SL_ITEM[numItems - 1];
  38.        int Pos = 0;
  39.        for (int i = 0; i < numItems; i++)
  40.            if (i != Index)
  41.                {
  42.                    NewItems[Pos].string = new char[strlen(Items[i].string) + 1];
  43.                    strcpy(NewItems[Pos].string, Items[i].string);
  44.                    Pos++;
  45.                }
  46.  
  47.        delete [] Items;
  48.        Items = NewItems;
  49.        numItems--;
  50.        return true;
  51.    }
  52.    else return false;
  53. }
  54.  
  55. long TStringList::GetCount()
  56. {
  57.    return numItems;
  58. }
  59.  
  60. char * TStringList::GetItem(long Index)
  61. {
  62.    if (Index < numItems && Index >= 0)
  63.        return Items[Index].string;
  64.    else return NULL;
  65. }
  66.  

Saludos.