dodwanie nowej liczby do dynamicznie powiekszanej tablicy w klasie

0

Witam. Potrzebuje zrobić swoją klasę duże liczby i mam problem z operatorem wejścia. Próbuję stworzyć najprostszą wersje, gdzie jedna cyfra przechowywana jest w jednym charze (przez przeciążenie operatora+).

W klasie mam :

 
#ifndef DUZA_H
#define DUZA_H
//////////////////////////////////////////////////////////////////////
class DUZA
{
    char* wartosc;
    char znak;
    unsigned int rozmiar;
    
public:
    friend istream& operator>>(istream& s, DUZA& liczba);
    friend ostream& operator<<(ostream& s, DUZA& liczba);
    void operator+(char& cyfra);
    DUZA();
    ~DUZA();
};
//////////////////////////////////////////////////////////////////////
DUZA::DUZA()
{
    znak = ' ';
    rozmiar = 0;
    wartosc = 0;
}
//////////////////////////////////////////////////////////////////////
DUZA::~DUZA()
{
    znak = ' ';
    rozmiar = 0;
    delete [] wartosc;
}
//////////////////////////////////////////////////////////////////////
void DUZA::operator+(char& cyfra)
{
    if(rozmiar == 0)
    {
        wartosc = new char;
        wartosc[0] = cyfra;
        rozmiar = 1;
    }
    else
    {
        char* temp = new char[rozmiar+1];
        int i;
        for(i=0; i<rozmiar; i++)
            temp[i] = wartosc[i];        //kopiowanie już zapisanych wartości
        temp[i+1] = cyfra;                //dodawanie nowej cyfry na koniec
        delete wartosc;
        wartosc = new char[rozmiar+1];   
        for(int j=0; j<rozmiar+1; j++)             //przepisywanie powiększonej 
            wartosc[i] = temp[i];                   //liczby do właściwej zmiennej w klasie
        delete temp;
        rozmiar++;
    }
    
}        
//////////////////////////////////////////////////////////////////////
#endif

Natomiast cyfry wczutyję z maina:

int main(int argc, char *argv[])
{
    DUZA l;
    cin >> l;
    cout << l;
    
    system("PAUSE");
    return EXIT_SUCCESS;
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
ostream& operator<<(ostream& s, DUZA& liczba)
{
    for(int i=0; i<liczba.rozmiar; i++)
        s << liczba.wartosc[i];
}
//////////////////////////////////////////////////////////////////////
istream& operator>>(istream& s, DUZA& liczba)
{
    char odp = 'y';
    while(odp != 'e')
    {
        s >> odp;
        if(odp != 'e') liczba.operator+(odp);
    }
}
//////////////////////////////////////////////////////////////////////
 

Przy wypisywaniu rozmiar tablicy jest dobry ale zamiast cyfr są krzaki. A do tego po jakiejś 10 cyfrze program się zamyka. Prosiłbym o pomoc.

0

w c++ tablice dynamiczna deklarujemy w ten sposob wartosc = new char[1]

0

poprawiłem to, i zmieniłem na delete [] wartosc; ,ale niestety dalej nic to nie zmieniło.

0

hmmm a musi to koniecznie być tablica Bracie?Bo w Twoim wypadku lepiej byłoby użyć listy

0

no niestety właśnie musi. to projekt na studia .. z listą by było dużo fajniej.

1

Odwołujesz się do temp[i+1] po skończeniu pętli for (czyli jak i==rozmiar). Ogólnie trochę ten program jest średni, po pierwsze to, że Stroustrup przeładował operatory << i >> w strumieniach nie znaczy, że ty też możesz. Po drugie twoje powiększanie tablicy jest bardzo wolne, spróbuj napisać swój program tak, żeby powiększał tablicę np. co kolejne potęgi dwójki (czyli jak dodajesz 2.,3.,5.,9.,17. itd. element). Dzięki temu dodanie elementu będzie wykonywane w zamortyzowanym czasie O(1). Kolejną rzeczą jest jedna niepotrzebna alokacja, możesz zamiast przekopiowywać elementy ze zmiennej temp najpierw podmienić wskaźnik, a potem go zwolnić.

0

odwołanie jest dobre, bo temp ma rozmiar o jeden większy niż zmienna rozmiar i jest tak zrobione by cyfra dodawała się na ostatnie dodatkowe miejsce w tablicy. nie wiem o co Ci chodzi z przeładowaniem operatorów, ale po to to jest żebym właśnie mógł to zrobić (a po drugie takie jest polecenie). teraz nie zależy mi na szybkości ani na niczym innym tylko żeby cyfry były dodawane poprawnie, a niestety tak nie jest. jeśli najpierw podmienię wskaźnik, a potem go zwolnię to usunę to miejsce gdzie jest zapisana moja liczba więc tym bardziej się nie będzie wyświetlać..

0

zaraz.. chyba właśnie tak nie robię.
char* temp = new char[rozmiar+1]; //tu jest temp i ma zalóżmy 9 elementów. (zmienna rozmiar == 8)

for(i=0; i<rozmiar; i++)
temp[i] = wartosc[i]; // wtedy tu "i" idzie od 0 do 7 czyli na końcu ma wartość 7.
temp[i+1] = cyfra; // a tu dodaje na miejscu 8 czyli właśnie ostatnim wolnym. indeksy od 0 do 8 (czyli razem 9 elementow, tyle co rozmiar+1)
??

1

Jeżeli rozmiar ma 8 to nowa tablica ma 9 elementów. Wtedy odwołujesz tak temp[9], a ostatnim jest temp[8].
Dodatkowo przeładowanie operatorów jest błędne. Operatory << i >> powinny zwracać referencję do strumienia. Na końcu daj return s;
Operator + powinien zwracać obiekt klasy DUZA -> dodatkowo wypadałoby, a wręcz trzeba przeładować operator= i napisać konstruktor kopiujący.

//@up: nie, po wyjściu z pętli w tym wypadku zmienna i ma wartość 8(użyjesz debuggera to się przekonasz na własne oczy) - wychodzi z pętli dopiero wtedy, kiedy i nie jest mniejsze od rozmiar, czyli kiedy jest równe

0

a to wiele wyjaśnia. dzięki! ze zwracaniem fakt przeoczyłem. a czemu operator+ powinien zwracać obiekt? nie może być void skoro działa od razu na tym zmiennej w tym obiekcie? operatory bd właśnie zaczynał.

1

Można, ale jest to trochę mylące. Standardowo operator+ działa tak, że nie zmienia jego argumentów. Nie możesz go użyć dla stałego obiektu. no i nie możesz zrobić np. tak: jedna_duza = druga_duza + '1' + '2'; Dodatkowo gdybyś miał jeszcze operator+ przyjmujący z prawej strony też obiekt klasy DUZA to mógłbyś robić np. tak: jakas_duza = inna_duza + jeszcze_inna + 'x'

0

dzięki, postaram się to jakoś ogarnąć :)

0

Poprawiłem tą funkcję

void DUZA::operator+(char& cyfra)
{

    if(rozmiar == 0)
    {
        wartosc = new char[1];
        wartosc[0] = cyfra;
        rozmiar = 1;
    }
    else
    {
        char* temp = new char[rozmiar+1];
        int i;
        for(i=0; i<rozmiar; i++)
            temp[i] = wartosc[i];
        temp[i] = cyfra;
        delete [] wartosc;
        wartosc = new char[rozmiar+1];
        for(int j=0; j<rozmiar+1; j++)
            wartosc[i] = temp[i];
        delete [] temp;
        rozmiar++;
    }  
}   
 

i dodałem zwracanie s w operatorach. Teraz sytuacja jest taka, że prawidłowo dodaje się i wyświetla ostatnia cyfra a wszystkie poprzednie to krzaki :/

1

Ale nakombinowałeś ?!
Wystarczy to:

void DUZA::operator+(char& cyfra)
  {
   char *temp=new char[rozmiar+1];
   if(rozmiar)
     {
      memcpy(temp,wartosc,rozmiar);
      delete[] wartosc;
     }
   wartosc=temp;
   wartosc[rozmiar++]=cyfra;
  }
0

gdybym znał memcpy to bym nie kombinował ;)
teraz wszystko jest okej, poczytam dokładniej o tej funkcji, dzięki!

1 użytkowników online, w tym zalogowanych: 0, gości: 1