Tablica słów, dynamiczne tworzenie/usuwanie

0

Witam, mam następujące zadanie:

  1. Utworzenie tablicy słów na 1 słowo o długości mniejszej niż 50
  2. Wyświetlenie "Enter a word"
  3. Użytkownik wprowadza słowo
  4. Wstawienie słowa do tablicy
  5. Jeżeli wstawione słowo inne niż "quit" to:
  • zwiększenie rozmiaru tablicy słów o 1
  • ponowne wyświetlenie napisu, wprowadzenie słowa i tak dalej
  1. Wyświetlenie wszystkich wprowadzonych napisów

Wszystko za pomocą charów, a nie stringów. Mam coś takiego:

#include <iostream>

using namespace std;

int main()
{
    char **tab; 
    char **tab2; 
    tab = new char*[1];
    tab[0]= new char[50]; 
    int i=0; 
    do
    {
        cout << "Enter a word: ";
        cin >> tab[i]; 
        cout << tab[i];
        if (tab[i]!="quit")
        {
            i++;
            tab2 = new char*[i+1]; 
            for (int y=0;y<=i;y++)
                tab2[i]=new char[50];
            for (int x=0;x<i;x++)
                tab2[x]=tab[x];
            for (int h=0;h<i;h++)
                delete []tab[h];
            delete []tab;
            tab=tab2;
        }
    } while (tab[i]!="quit");

    for (int j=0;j<=i;j++)
        cout << tab[j];

    return 0;
}

No ale program nie działa. Jak to naprawić by działało? Uczyłem się, że zmienia się rozmiar dynamicznej tablicy poprzez utworzenie nowej, przekopiowanie starej do nowej, usunięcie starej, przypisanie wskaźnikowi starej tablicy wskaźnika nowej tablicy

1

Pierw inkrementujesz i, a potem działasz na i elementach tablicy poprzedniej, czyli masz off-by-one.

A prowadzącemu wklej https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/ i powiedz, że nie należy uczyć od .... strony.

0

@kq:

Hmm, w którym miejscu działam na i elementach tablicy poprzedniej? Po zwiększeniu wartości i działam na poprzedniej tablicy tutaj:

for (int x=0;x<i;x++)
                tab2[x]=tab[x];
for (int h=0;h<i;h++)
                delete []tab[h];

Ale nigdy przecież nie wyjadę poza zakres komórek pierwszej tablicy - jej ostatnia komórka to w tym momencie i-1, a pętle nie wchodzą na i - będą się wykonywać właśnie do momentu i-1.

@daniel1302

Mam działać w oparciu o materiał z zajęć, a niestety nie mieliśmy takiej funkcji omawianej

0
            i++;
            //...
            for (int h=0;h<i;h++)
                delete []tab[h];
0

@kq:
Wciąż nie do końca rozumiem dlaczego jest to źle, poniżej pokażę moje rozumowanie dla i początkowego i=0, które potem się zwiększa do i=1, przepraszam jeżeli jest to jakiś błahy błąd, ale jestem mocno początkujący, i wciąż mam problem z zauważaniem wielu błędow.

        cin >> tab[i]; //podajemy słowo i - początkowo i=0
        cout << tab[i]; 
        if (tab[i]!="quit")
        {
            i++; //zwiększamy i, i=1
            tab2 = new char*[i+1]; //tworczymy tablicę wskaźników i+1 elemntów, czyli dwóch
            for (int y=0;y<=i;y++) //tworzenie tablic tab2[0] oraz tab2[1]
                tab2[i]=new char[50];
            for (int x=0;x<i;x++) //przypisanie tab2[0] wartości tab[0] - mieścimy się w zakresie tab
                tab2[x]=tab[x];
            for (int h=0;h<i;h++) //usuwamy tab[0] - mieścimy się w zakresie tab[], bo, gdy i=1, to pętla skończy się wykonywać przy h=0;
                delete []tab[h];
            delete []tab;
            tab=tab2;
        }
1

Przepraszam za zamotanie, ale jednocześnie mam dla Ciebie przydatny link: https://dsp.krzaq.cc/post/445/jak-zadawac-pytania-na-forum/

"Nie działa" nic nie mówi, założyłem, że chodzi o crash, szczególnie, że dość podejrzanie te pętle wyglądały.

if(tab[i]!="quit")

Porównujesz wskaźniki, aby porównać treść użyj strcmp.

if (strcmp(tab[i], "quit") == 0)

Jednocześnie, przesunięcie i i tak sprawi problemy, ponieważ w warunku pętli masz porównanie tab[i] z quit, ale i jest inne niż w ifie wyżej. Zmień pętlę na nieskończoną i w ifie wychodź za pomocą break

    do
    {
        cout << "Enter a word: ";
        cin >> tab[i];
        cout << tab[i];
        if (strcmp(tab[i], "quit") == 0)
        {
            i++;
            tab2 = new char*[i+1];
            for (int y=0;y<=i;y++)
                tab2[i]=new char[50];
            for (int x=0;x<i;x++)
                tab2[x]=tab[x];
            for (int h=0;h<i;h++)
                delete []tab[h];
            delete []tab;
            tab=tab2;
            break;
        }
    } while (true);

Przy okazji:

            for (int x=0;x<i;x++)
                tab2[x]=tab[x];

Tak nadpisujesz wskaźniki, a nie kopiujesz stringi, do tego masz strcpy i jej bezpieczniejsze odpowiedniki.

0

Dzięki! W tej chwili mam więc takie coś:

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
    char **tab;
    char **tab2;
    tab = new char*[1];
    tab[0]= new char[50];
    int i=0;
    do
    {
        cout << "Enter a word: ";
        cin >> tab[i];
        if (strcmp(tab[i], "quit") == 0)
        {
            i++;
            tab2 = new char*[i+1];
            for (int y=0;y<=i;y++)
                tab2[i]=new char[50];
            for (int x=0;x<i;x++)
                strcpy(tab2[x],tab[x]);
            for (int h=0;h<i;h++)
                delete []tab[h];
            delete []tab;
            tab=tab2;
            break;
        }
    } while (true);

    for (int j=0;j<=i;j++)
        cout << tab[j];

    return 0;
}

Program jednak wciąż nie działa - wczytuje kolejne słowa, lecz po wpisaniu "quit" - konsola się crashuje.

1

Nie wiem co dziś ze mną jest :​/

W if wchodzisz tylko gdy słowo jest różne od quit:

if (strcmp(tab[i], "quit") != 0)

Dodatkowo tu masz błąd: powinno być tab2[y]:

            for (int y=0;y<=i;y++)
                tab2[i]=new char[50];

Finalnie:

int main()
{
    char **tab;
    char **tab2;
    tab = new char*[1];
    tab[0]= new char[50];
    int i=0;
    do
    {
        cout << "Enter a word: ";
        cin >> tab[i];
        if (strcmp(tab[i], "quit") != 0)
        {
            i++;
            tab2 = new char*[i+1];
            for (int y=0;y<=i;y++)
                tab2[y]=new char[50];
            for (int x=0;x<i;x++)
                strcpy(tab2[x],tab[x]);
            for (int h=0;h<i;h++)
                delete []tab[h];
            delete []tab;
            tab=tab2;
        } else {
            break;
        }
    } while (true);

    for (int j=0;j<=i;j++)
        cout << tab[j] << endl;

    return 0;
}
0

Dzięki wielkie, teraz działa jak powinno!

Faktycznie głupi błąd się tam pojawił z tym i zamiast y.

A na przyszłość będę się starał zakładać tematy według linka, który podałeś, i mocniej opisać problem ; )

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