Sprawdzenie czy wprowadzony tekst jest palindromem

0

Witam,

Na wstępie chciałbym podziękować za pomoc w poprzedniej kwestii. Szansa na zaliczenie tego przedmiotu się dzięki wam zwiększyła. Niestety znów jestem zmuszony prosić was o pomoc.

Do napisania następująca rzecz. Użytkownik wprowadza teks, a program ma sprawdzić czy jest on palindromem. Etapy rozwiązania problemu:

  1. Usunięcie znaków interpunkcyjnych z wprowadzonego tekstu
  2. Zamiana wielkich na male litery (już z tekstu pozbawionego znaków interpunkcyjnych)
  3. Odwrócenie tekstu składającego się tylko z małych liter.
  4. Porównanie tekstów z punktu 2 i 3.

Uwaga jedna: nie wolno mi używać klasy string:/

Nawet nie wiem jak określić co działa a co nie działa w tym programie. Na pewno nie działa usuwanie znaków interpunkcyjnych. Wydaje się działać zamiana wielkich na małe litery. Pisanie tekstu od tyłu raz działa a raz nie:/

Oto kod:

#include <iostream>
#include <string>
#include <vector>

using namespace::std;

class Napis {

      private:
              char* Tablica;
              int Dlugosc;
              char* od_tylu;
              char* male;
              char* bez_inter;
              int Dlugosc_Bez_Inter;
      public:
             Napis(char* Tekst);
             ~Napis();
             void Zamien(int i, char c);
             void wyswietl();
             void przestaw(int i, int j);
             void napis_od_tylu();
             void napis_male();
             void napis_bez_inter();
             bool napis_jest_palindromem();
             bool char_in_set(char, string);
};

bool Napis::napis_jest_palindromem(){

     return (male == od_tylu);
}

/* string od_tylu(const string& s) {
int poczatek = 0;
int koniec = s.length( );
string pom(s);
while (poczatek < koniec)
{
koniec--;
przestaw(pom[poczatek], pom[koniec]);
poczatek++;
}
return pom;
}
*/

void Napis::napis_bez_inter(){

     delete [] bez_inter;
     int Tablica_size = sizeof(Tablica)/sizeof(char);
     bez_inter = new char[Tablica_size + 1];

     string znaki(",;:.?!'\" ");

     int i = 0;
     int j = 0;
     while (i < Tablica_size) {

      if (!char_in_set(Tablica[i], znaki)) {
        bez_inter[j] = Tablica[i];
        j++;
      }

      i++;
     }
}

bool Napis::char_in_set(char c, string set) {
  int size = set.length();
  for (int i = 0; i < size; i++) {
    if (c == set[i]) {
      return true;
    }
  }
  return false;
}

void Napis::napis_male(){

                  delete [] male;
                  male = new char[Dlugosc_Bez_Inter + 1];

                  for (int i = 0; i < Dlugosc_Bez_Inter; i++)
                  male[i] = tolower(bez_inter[i]);
}

/*
string na_male_litery(const string& s) {
string pom(s);
for (int i = 0; i < s.length( ); i++)
pom[i] = tolower(s[i]);
return pom;
}
*/

void Napis::napis_od_tylu(){

     delete [] od_tylu;
     od_tylu = new char[Dlugosc_Bez_Inter + 1];
     char temp;
     for (int i = 0; i < Dlugosc_Bez_Inter; i++)
     {
         od_tylu[i] = male[i];
     }

     for (int i = 0; i < Dlugosc_Bez_Inter/2; i++)
     {
         temp = od_tylu[i];
         od_tylu[i] = od_tylu[Dlugosc_Bez_Inter - i - 1];
         od_tylu[Dlugosc_Bez_Inter - i - 1] = temp;
     }
}

void Napis::przestaw(int i, int j) {
     char * temp = new char[2];
     temp[0] = Tablica[i];
     temp[1] = Tablica[j];
     Tablica[i] = temp[1];
     Tablica[j] = temp[0];
     delete [] temp;
}

Napis::Napis(char* Tekst) {
                   Dlugosc = std::strlen(Tekst);
                   Tablica = new char[Dlugosc + 1];
                   if (Tablica)
                      memcpy (Tablica, Tekst, Dlugosc+1);
                   else
                       Dlugosc = 0;

                   od_tylu = new char[Dlugosc+1];
                   male = new char[Dlugosc+1];
                   bez_inter = new char[Dlugosc+1];

                  napis_bez_inter();
                  napis_male();
                  napis_od_tylu();

}

Napis::~Napis() {
        if(Dlugosc) delete[] Tablica;
        delete[] od_tylu;
        delete[] bez_inter;
        delete[] male;
}

void Napis::wyswietl(){

    cout << Tablica << endl;
    cout << "Bez interpunkcji: " << bez_inter << endl;
    cout << "Zamieniony na male litery: " << male << endl;
    cout << "Na koniec napis od tylu: " << od_tylu << endl;
}

int main() {

    char * tekst = new char;
    string znaki(",;:.?!'\" ");

    cout << "Wpisz jakis napis" << endl;
    cin >> tekst;
    Napis Napis(tekst);
    if (Napis.napis_jest_palindromem())
       cout << "Wprowadzony napis jest palindromem" << endl;
       else
       cout << "Wprowadzony napis nie jest palindromem" << endl;
    delete [] tekst;

    Napis.wyswietl();

cin.get();
return 0;
}

Z góry dziękuję za pomoc.

Pozdrawiam,

0

Przepraszam za double post, ale nie mogę edytować:/

Mała zmiana w funkcji usuwającej interpunkcje.

void Napis::napis_bez_inter(){

     delete [] bez_inter;
     int Tablica_size = sizeof(Tablica)/sizeof(char);
     bez_inter = new char[Tablica_size + 1];

     string znaki(",;:.?!'\" ");

     int i = 0;
     int j = 0;
     Dlugosc_Bez_Inter = 0;
     while (i < Tablica_size) {

      if (!char_in_set(Tablica[i], znaki)) {
        bez_inter[j] = Tablica[i];
        j++;
        Dlugosc_Bez_Inter++;
      }

      i++;
     }
}
0
  1. porównywanie char* robimy za pomocą strcmp a nie ==
  2. Piszesz koszmarny kod i tym samym utrudniasz sobie życie.
  3. Używanie debuggera nie boli
    Nie rozumiem czemu chcesz to wszystko robić w osobnych obiegach i trzymać w osobnej pamięci. Przecież zamienić duże literki na małe możesz w miejscu
for(int i=0;i<tekst.length();i++){
  tekst[i] = tolower(tekst[i]);
}

Co więcej mozesz to zrobić od razu usuwając interpunkcję...
Usuwanie interpunkcji wygląda ok, przy czym musisz dodać na końcu \0 (zarezerwowałeś na nie miejsce, ale nie dodałeś)

0

Dzięki za odpowiedź.

Usuwanie interpunkcji wygląda ok, przy czym musisz dodać na końcu \0 (zarezerwowałeś na nie miejsce, ale nie dodałeś)

Możesz mi wskazać w którym miejscu mam to dodać i w jaki sposób? Bo niestety nie do końca to rozumiem:(

Pozdrwaiam,

EDIT:

Udało się zrobić usuwanie interpunkcji. Działa bez zarzutu, pod warunkiem, że wprowadzony tekst ma długość mniejszą od 15 znaków. Działa również zamiana na małe litery.

Nie działa teraz pisanie tekstu od tyłu.

EDIT 2:

Dobra, pisanie od tyłu działa w 90%.

Jak wpiszę ala;ma;kota - jest poprawnie
Jak wpiszę ala;ma;kota; - program się wywala
Jak wpiszę ala;ma;kota;a - jest poprawnie

Nie mam zielonego pojęcia o co chodzi.

I niestety pomyliłem się co do długości wpisanego tekstu:/

Jak wpiszę np. abcdefghi - program działa poprawnie.
Jak wpiszę abcdefghij - program już się wykrzacza.

To teraz się muszę zastanowić czemu nawet po wpisaniu potop, dostaję informację że nie jest palindromem:/

EDIT 3:

Bardzo dziękuję za wskazanie mi funkcji strcmp. Dzięki temu potop już jest palindromem:)

Jeśli ktoś by miał jakiś pomysł odnośnie tego co napisałem pod EDIT 2 to proszę dać znać. Jak nie, to trudno. Program działa w ponad 90% i jestem gotów go oddać.

Z racji tego że nie mogę edytować pierwszego postu, wklejam tutaj najświeższy kod.

#include <iostream>
#include <string>


using namespace::std;

class Napis {

      private:
              char* Tablica;
              int Dlugosc;
              char* od_tylu;
              char* male;
              char* bez_inter;
              int Dlugosc_Bez_Inter;
      public:
             Napis(char* Tekst);
             ~Napis();
             void Zamien(int i, char c);
             void wyswietl();
             void przestaw(int i, int j);
             void napis_od_tylu();
             void napis_male();
             void napis_bez_inter();
             bool napis_jest_palindromem();
             bool char_in_set(char, string);
};

bool Napis::napis_jest_palindromem(){

     return (strcmp(male, od_tylu) == 0);
}

void Napis::napis_od_tylu(){

     delete [] od_tylu;

     char temp;
     
     od_tylu = new char[Dlugosc_Bez_Inter + 1];

     for (int i = 0; i < Dlugosc_Bez_Inter; i++)
     {
         od_tylu[i] = male[i];
     }

     for (int i = 0; i < Dlugosc_Bez_Inter/2; i++)
     {
         temp = od_tylu[i];
         od_tylu[i] = od_tylu[Dlugosc_Bez_Inter - i - 1];
         od_tylu[Dlugosc_Bez_Inter - i - 1] = temp;
     }
     
     od_tylu[Dlugosc_Bez_Inter] = '\0';
}

void Napis::napis_bez_inter(){
 
     delete [] bez_inter;
     int Tablica_size = strlen(Tablica)/sizeof(char);
     char * temp = new char[Tablica_size + 1];
 
     string znaki(",;:.?!'\" ");
 
     int i = 0;
     int j = 0;
     Dlugosc_Bez_Inter = 0;
     while (i < Tablica_size) {
 
      if (!char_in_set(Tablica[i], znaki)) {
        temp[j] = Tablica[i];
        j++;
        Dlugosc_Bez_Inter++;
      }
      i++;
     }
     
     bez_inter = new char[Dlugosc_Bez_Inter + 1];
     for (int i = 0; i < Dlugosc_Bez_Inter; i++)
     bez_inter[i] = temp[i];
     
     bez_inter[Dlugosc_Bez_Inter] = '\0';
}

bool Napis::char_in_set(char c, string set) {
  int size = set.length();
  for (int i = 0; i < size; i++) {
    if (c == set[i]) {
      return true;
    }
  }
  return false;
}

void Napis::napis_male(){

                  delete [] male;
                  male = new char[Dlugosc_Bez_Inter + 1];

                  for (int i = 0; i < Dlugosc_Bez_Inter; i++)
                  male[i] = tolower(bez_inter[i]);
                  
                  male[Dlugosc_Bez_Inter] = '\0';
}

void Napis::przestaw(int i, int j) {
     char * temp = new char[2];
     temp[0] = Tablica[i];
     temp[1] = Tablica[j];
     Tablica[i] = temp[1];
     Tablica[j] = temp[0];
     delete [] temp;
}

Napis::Napis(char* Tekst) {
                   Dlugosc = std::strlen(Tekst);
                   Tablica = new char[Dlugosc + 1];
                   if (Tablica)
                      memcpy (Tablica, Tekst, Dlugosc+1);
                   else
                       Dlugosc = 0;

                   od_tylu = new char[Dlugosc+1];
                   male = new char[Dlugosc+1];
                   bez_inter = new char[Dlugosc+1];

                  napis_bez_inter();
                  napis_male();
                  napis_od_tylu();

}

Napis::~Napis() {
        if(Dlugosc) delete[] Tablica;
        delete[] od_tylu;
        delete[] bez_inter;
        delete[] male;
}

void Napis::wyswietl(){

    cout << "Bez interpunkcji: " << bez_inter << endl;
    cout << "Zamieniony na male litery: " << male << endl;
    cout << "Na koniec napis od tylu: " << od_tylu << endl;
}

int main() {

    char * tekst = new char;
    string znaki(",;:.?!'\" ");

    cout << "Wpisz jakis napis" << endl;
    cin >> tekst;
    Napis Napis(tekst);
    if (Napis.napis_jest_palindromem())
       cout << "Wprowadzony napis jest palindromem" << endl;
       else
       cout << "Wprowadzony napis nie jest palindromem" << endl;
    delete [] tekst;

    Napis.wyswietl();

system("PAUSE");
return 0;
}

EDIT 5 (ostatni).

Działa wszystko:) Musiałem usunąć

 delete [] tekst; 

. I wszystko zaczęło śmigać:). Dziękuję za pomoc.

Pozdrawiam,

0

Witam,

Tak właściwie to jest jeszcze jedna rzecz która nie działa. Program nie radzi sobie ze spacjami. Gdy wpiszę tekst "A to idiota", to weźmie pod uwagę tylko literkę A.

Nie jest to krytyczny błąd, niemniej jednak przyjemnie by było jakby zadziałał. Czy ma ktoś jakieś pomysły? Myślałem nad zmianą zmiennej trzymającej wszystkie znaki, ale chyba nie tędy droga.

Pozdrawiam,

0

cin>> czyta do pierwszego białego znaku. Zamień to na http://www.cplusplus.com/reference/string/getline/ i będzie ok.

0

Bo używasz cin.
Użyj getline albo scanfa

http://ideone.com/syZP2
http://crasseux.com/books/ctutorial/getline.html

0

Tak, pisząc cin miałem na myśli operator>>.

0

Próbowałem następujące sposoby:

char * tekst = new char;
cout << "Wpisz jakis napis" << endl;
    //cin.getline(tekst,100);
    //scanf("%s", tekst);
    //cin >> tekst

Getline - nie dość że nie działało tak jak powinno, to jeszcze zepsuło mi cały program.
scanf - nie było żadnej różnicy między tym a cin

Boje się że edycja tego tak, by działało oznaczałaby konieczność modyfikacji całego programu, na co niestety nie będę miał czasu.

Pozdrawiam,

0

Spróbowałem tak:

cin.getline(tekst,sizeof(tekst));

Problem w tym, że zaraz po tej linii program się zamyka. Z tego co wyczytałem to tak się zdarza przy getline, ale żaden ze sposobów obejścia tego nie pomógł mi:/

0

Dopiero teraz rzuciłem okiem na ten twój kod i jest totalnie źle.

    char * tekst = new char;
    cin >> tekst;

oznacza ze alokujesz pamięć na 1 (!) znak a potem coś do tego wczytujesz. Głowe dam że juz dla kilku liter się wysypie (piszesz po pamięci której nie zaalokowałeś!)
Skoro to C++ to dlatego nie używasz string?

string tekst;
getline(cin,tekst);
cout<<tekst; //magic ;]
0

W treści zadania mam, że nie mogę używać klasy string.

Program się nie wysypał po wpisaniu 100 znaków. Poza spacjami wszystko w tym programie działa bez problemu.

0

Musisz zaalokować pewną ilość pamięci na ten tekst, tzn musisz mieć na przykład

new char[1000];

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