Niepoprawny kod banalnego programu obiektowego

0

Witam, mam problem, poniewaz moj program zaraz po uruchomieniu przestaje dzialac poprawnie. Nie mam pojecia gdzie lezy blad. Mogłby ktos rzucic okiem na kod i powiedziec co jest nie tak ?

#include <iostream>
#include <cstdlib>
#include <string.h>

using namespace std;

class language
{
  char* English;
  char* Polish;
  char* German;

  public:
    char menu();
    void show(language* myLanguage2);
    void fill(language* myLanguage2);
};
//******************************************************************************************//
char language::menu()
{
    char letter;
    cout << "Wybierz jezyk" <<endl;
    cout << "[1]... Angielski" <<endl;
    cout << "[2]... Polski" <<endl;
    cout << "[3]... Niemiecki" <<endl;
    cout << "[0]... KONIEC" <<endl;
    cout << " ";
    cin >>letter;
        if(letter==48)
          exit(1);
        else if(letter<48 || letter>57)
            cout << "Nie podano cyfry!! Wybierz odpowiednia opjce" <<endl<<endl;
        else if(letter>=52 && letter<=57)
            cout <<"Podano nie wlasciwa cyfre" <<endl<<endl;
        else
            return letter;
}
//******************************************************************************************//
void language::fill(language* myLanguage2)
{
    myLanguage2->English = "Hello World !";
    myLanguage2->Polish = "Witaj Swiecie !";
    myLanguage2->German = "Hallo Welt !";
}
//******************************************************************************************//
void language::show(language* myLanguage2)
{
    char a = 0;
    char letter=1;
    while(a!=letter)
    {
    letter = menu();
     switch(letter)
    {
        case '1':
            cout << myLanguage2->English <<endl <<endl;
                break;
        case '2':
            cout << myLanguage2->Polish <<endl <<endl;
                break;
        case '3':
            cout << myLanguage2->German <<endl <<endl;
                break;
    }
    }
}
//******************************************************************************************//
//******************************************************************************************//
int main(void)
{
    language* myLanguage; //tworze moj obiekt!
    myLanguage->fill(myLanguage);
    myLanguage->show(myLanguage);
    return 0;
}

 
0
language* myLanguage;

Nie tworzysz obiektu tylko wskaźnik do obiektu. Ten wskaźnik pokazuje Bóg-wie-gdzie a ty następnie każesz mu zinterpretować ten losowy obszar pamięci jako obiekt language. W efekcie program od razu rzuca segfaultem.

0

O faktycznie, bardzo dziekuje za odpowiedz, bo nie mialem pomyslu co jest nie tak...
Czyli:

language* myLanguage = new language; Powinno zalatwic sprawe :)

Pozdrawiam :)

0

Niekoniecznie. W kodzie masz też coś takiego:

myLanguage2->English = "Hello World !";

Gdzie English jest wskaźnikiem na typ char. Takie przypisanie nie powinno zadziałać (może kompilator da ostrzeżenie). Dla wskaźników na char powinno się alokować odpowiednią ilość pamięci i potem użyć strcpy.

0

No i jak ktoś wywoła show() przed fill() to też może być słabo. Nie mówiąc o tym że zamiast magicznych liczb typu 48 można napisać 'a'...

0

Ok dzieki za wskazowki, postanowilem caly kod zmienic :)

myLanguage2->English = "Hello World !"; 

Piszac takie cos bylem pewny ze "Hello World !" potraktuje mi jako string i zapisze mi adres tego stringa w odpowiednie miejsce w pamieci. Owszem kompilator wyrzuca ostrzezenia, ale ignorowalem to.
char* English, traktowlalem po prostu jako tablice charow. I teraz widze ze to jest blad. Przeciez musze zaalokwac odpowiedzina ilosc pamieci na te moją "tablice charow".

Uwzglednie te wszytie informacje podczas poprawiania kodu :)

Pozdrawiam!

0

nie będzie warninga jeśli dodasz const:

const char *English;
...
myLanguage2->English = "Hello World !";
0

Faktycznie, teraz nie ma warninga :)

 #include <iostream>
#include <cstdlib>
#include <string.h>

using namespace std;

class language
{
  const char* English;
  const char* Polish;
  const char* German;

  public:
    char menu();
    void show(language* myLanguage2);
    void fill(language* myLanguage2);
};
//******************************************************************************************//
char language::menu()
{
    char letter;
    cout << "Wybierz jezyk" <<endl;
    cout << "[1]... Angielski" <<endl;
    cout << "[2]... Polski" <<endl;
    cout << "[3]... Niemiecki" <<endl;
    cout << "[0]... KONIEC" <<endl;
    cout << " ";
    cin >>letter;
        if(letter==48)
          exit(1);
        else if(letter<48 || letter>57)
            cout << "Nie podano cyfry!! Wybierz odpowiednia opjce" <<endl<<endl;
        else if(letter>=52 && letter<=57)
            cout <<"Podano nie wlasciwa cyfre" <<endl<<endl;
        else
            return letter;
}
//******************************************************************************************//
void language::fill(language* myLanguage2)
{
    myLanguage2->English = "Hello World !";
    myLanguage2->Polish = "Witaj Swiecie !";
    myLanguage2->German = "Hallo Welt !";
}
//******************************************************************************************//
void language::show(language* myLanguage2)
{
    char a = 0;
    char letter=1;
    while(a!=letter)
    {
    letter = menu();
     switch(letter)
    {
        case '1':
            cout << myLanguage2->English <<endl <<endl;
                break;
        case '2':
            cout << myLanguage2->Polish <<endl <<endl;
                break;
        case '3':
            cout << myLanguage2->German <<endl <<endl;
                break;
    }
    }
}
//******************************************************************************************//
//******************************************************************************************//
int main(void)
{
    language* myLanguage = new language; //tworze moj obiekt!
    myLanguage->fill(myLanguage);
    myLanguage->show(myLanguage);
    return 0;
}

Ok to jeszcze chciałbym sie upewnic. Const char* English jest wskaznikiem do przechowywania adresu elementu typu char. Czyli myLanguage2->English = "Hello World !"; zapisuje adres stringa "Hello World !" wlasnie w Const char* English. Czy takie dzialanie jest poprawne?

Bo jezeli zrobie tak jak poprzednio czyli "char*English" to (jezeli dobrze zrozumialem wskazowki) to moja funkcja fill musi wygladac tak:

void language::fill()
{
    English = new char[20];  
    Polish = new char[20];
    German = new char[20];
    strcpy(English,"Hello World !");
    strcpy(Polish,"Witaj Swiecie !");
    strcpy(German,"Hallo Welt !");
} 

I teraz ostatnie pytanie. Stosujac przedrostek const, sprawiam iż moj wskanik teraz moze przechowywac caly string czyli tablice charow... A nie uzywajac tego przedrostka, koniecznie musze alkowac pamiec na tablice. Bo samo char* English jest tylko wskaznikiem na 1 element typu char ???

Z gory dziekuje za odpowiedz. Chciałbym dobrze to zrozumiec, bo wskazniki to potężna broń w c++ :)

0

Poczytaj co robi const. Const pozwala na pokazywanie na stały ciąg znaków i nie pozwala na jego zmianę. To czy możesz tak korzystać z c-stringów, czy musisz oddzielnie alokować pamięć i kopiować do niej literał to zależy od tego co będziesz później robił z tymi stringami. Jeżeli przechowujesz tylko adres do literału to nie możesz go zmieniać. Nie masz gwarancji, że dwa takie same literały będą w różnych miejscach pamięci, więc zmiana jednego pociągnie za sobą zmianę drugiego.

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