• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Palindromy/matura

VPS Starter Arubacloud
0 głosów
3,443 wizyt
pytanie zadane 6 marca 2018 w C i C++ przez Scypyon Gaduła (3,450 p.)
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    fstream plik;
    plik.open( "dane.txt",ios::in |ios::out );

    string a;

    while(!plik.eof()){

        plik>>a;

        for(int i=0; i<(a.length()-1)/2;i++){

            if(a[i]!=a[a.length()-1-i]){
                break;
            }
            else {
                cout<<a<<endl;
            }
        }
    }

    return 0;
}

Nie rozumiem dlaczego program nie działa, while(!plik.eof()) po kolei wczytuje każdy wyraz z osobna, chyba nie dokońca rozumiem jak działa break..

komentarz 6 marca 2018 przez Radfler VIP (101,030 p.)
A co ten program ma konkretnie robić? Liczyć palindromy, wyświetlać je?
komentarz 6 marca 2018 przez mokrowski Mędrzec (155,460 p.)

@Scypyon, To zależy co chcesz uzyskać. Jeśli chcesz kontynuacji wczytywania w pętli, to raczej continue będzie bardziej odpowiednie. 

plik.eof() także jest złym pomysłem. Wystarczy badać stan strumienia (czyli plik).

Pomogło by bardzo jak napisał byś co chcesz uzyskać. Trudno coś radzić zgadując.

komentarz 6 marca 2018 przez Scypyon Gaduła (3,450 p.)
Zadanie 4. Palindromy (10 pkt) Palindromem nazywamy słowo, które czytane od lewej i od prawej strony jest takie samo. Na przykład palindromami są słowa: JABFDFBAJ HAJAHAJAH ABBA Słowo JANA nie jest palindromem.
 W pliku dane.txt umieszczono w kolejnych wierszach 1000 słów o długościach od 2 do 25 znaków, składających się z wielkich liter A, B, C, D, E, F, G, H, I, J. Napisz program, który przegląda słowa zapisane w pliku dane.txt i wypisuje te z nich, które są palindromami, po jednym w wierszu. Kolejność wypisywania palindromów powinna być taka sama jak w pliku z danymi. Wyniki zapisz w pliku zadanie4.txt.
komentarz 6 marca 2018 przez Scypyon Gaduła (3,450 p.)
dlaczego plik.eof jest złym pomysłem?

6 odpowiedzi

0 głosów
odpowiedź 10 marca 2018 przez Beginer Pasjonat (22,110 p.)
wybrane 10 marca 2018 przez Scypyon
 
Najlepsza
#include <string.h>
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    ifstream mojPlik("dane.txt");  //otwarcie pliku do odczytu
    ofstream jejPlik ("zadanie4.txt");  //otwarcie pliku do zapisu

    if (mojPlik)  //true (dobre otwarcie)
    {
      string slowo;
      int palindrom;                              //zmienna kontrolna

      while (!mojPlik.eof())
      {
       mojPlik >> slowo;                          //pobranie wyrazu z pliku

       int len = strlen(slowo.c_str());           //podaje dlugość słowa (ile jest znaków)

       palindrom = 1;
       for (int i = 0; i < len/2; i += 1)         //w pętli for pobieramy i porównujemy kolejne litery słowa
       {
        string litera_X (slowo, i, 1);            //pojedyncza litera brana z początku słowa
        string litera_Y (slowo, len - i - 1, 1);  //pojedyncza litera brane z końca słowa
        if (litera_X != litera_Y)                 //sprawdzenie czy litery się różnią
        {
         palindrom = 0;
         break;                                    //przerywa dalsze sprawdzanie i wykonywanie funkcji
        }
       }
        if(palindrom != 0)
        {
         cout << slowo << endl;                    //wyświetla PALINDROM
         jejPlik << slowo << endl;                 //zapisuje PALINDROM do pliku
        }
      }
    }
    else
    {
     cout << "\n ERROR: nie mozna otworzyc pliku do odczytu \n";
    }

    mojPlik.close();
    jejPlik.close();
    return 0;
}

Powyżej masz pełną wersję programu do wyszukiwania palindromów, łącznie z zapisem do pliku - tak, jak było w zadaniu. Palindromy są zapisywane w pliku: zadanie4.txt

P.S. W tej wersji nie ma zewnętrznej funkcji.

komentarz 10 marca 2018 przez Scypyon Gaduła (3,450 p.)

Dokładnie o takie coś mi chodziło :) Idealnie, powiedz mi tylko dlaczego 

for (int i = 0; i < len/2; i += 1) 

i+=1? czyli to samo co ++ w tym przykładzie

strlen?

komentarz 10 marca 2018 przez Beginer Pasjonat (22,110 p.)
Tak!  i += 1, to to samo, co i++

"len / 2" (czyli długość słowa / 2)  dlatego, że przeszukujemy słowo z obu stron jednocześnie (i porównujemy litery), ale z każdej strony wystarczy tylko do połowy - np. wyraz: AB BA .

W tej konkretnej sytuacji sama komenda "break" nie mogła wystarczyć, dlatego konieczne było wprowadzenie dodatkowej zmiennej kontrolnej "palindrom". Poza tym Twoja wersja była bardzo zbliżona.

Podrzucam kilka swoich palindromów: MANAM, KAJAK, MADAM, ARA (gatunek papugi)
komentarz 10 marca 2018 przez Scypyon Gaduła (3,450 p.)
Akurat wczoraj byłem w papugarni ^^ Dzięki jeszcze raz
+3 głosów
odpowiedź 6 marca 2018 przez Radfler VIP (101,030 p.)

1. Nie wczytuj danych z wykorzystaniem funkcji eof (może sprawiać problemy). Jeżeli chcesz wczytać wszystkie dane dostępne w pliku, to zrób to tak:

string a;
while(plik >> a) {
  // ...
}

Albo nawet tak:

for(string a; plik >> a; ) {
  // ...
}

2. Odnośnie tego kodu:

for(int i=0; i<(a.length()-1)/2;i++){
 
    if(a[i]!=a[a.length()-1-i]){
        break;
    }
    else {
        cout<<a<<endl;
    }
}

Dlaczego za każdym razem, kiedy zostanie znaleziona pasująca litera, wyświetlasz cały wyraz? Trochę to sprzeczne z treścią zadania.

3. Według mnie to zrobiłeś w tym kodzie małe zamieszanie. Spróbuj napisać osobną funkcję, która sprawdza czy wyraz jest palindromem:

bool IsPalindrome(const string& text);

A następnie użyj jej w taki sposób:

if(IsPalindrome(a)) {
  cout << a << '\n';
}

EDIT (może Ci się to przydać na maturze):

W C++ sprawdzanie palindromu można załatwić jedną ładną instrukcją i wg mnie warto się jej nauczyć (nie będziesz tracić czasu na pisanie dodatkowych funkcji):

#include <algorithm>

bool IsPalindrome(const string& word) {
    return equal(word.begin(), word.begin() + (word.size()/2), word.rbegin());
}
komentarz 9 marca 2018 przez Radfler VIP (101,030 p.)

Funkcja, którą napisałem zwraca typ bool (logiczny), czyli sprawdza czy wyraz podany w argumencie jest palindromem. Jeżeli używasz mojej funkcji w taki sposób:

if (IsPalindrome)
cout << wyraz << '\n';

To nie dziw się, że to nie działa. Wyrażenie IsPalindrome jest zawsze prawdą bo jest adres funkcji. Używaj tego tak:

if (IsPalindrome(wyraz))
cout << wyraz << '\n';

A jeżeli to też nie działa to pokaż kod.

komentarz 9 marca 2018 przez Scypyon Gaduła (3,450 p.)
Bym był bardzo wdzięczny za jakiś prosty(maturalny )sposób rozwiązania tego zadania :)
komentarz 9 marca 2018 przez Beginer Pasjonat (22,110 p.)

@Radfler,

Nie działa, nic nie wypisuje.

Kod zamieściłem powyżej.

komentarz 9 marca 2018 przez Radfler VIP (101,030 p.)

@Scypyon

To może tak:

bool IsPalindrome(const string &word) {
    
    int p = 0;
    int q = word.size()-1;
    
    while(p < q) {
        if(word[p] != word[q]) {
            return false;
        }
        ++p;
        --q;
    }
    
    return true;
    
}

A jeżeli chodzi o maturę to polecam Ci uczyć się idiomów (taki jak ten co Ci pokazałem). Oszczędzisz sobie pisania.

komentarz 9 marca 2018 przez Radfler VIP (101,030 p.)

@Beginer

while(mojPlik >> wyraz) // (1)
{
mojPlik >> wyraz;
if(IsPalidrome(wyraz))
cout << wyraz << endl;
}

Liczba, którą wczytujesz w (1) jest całkowicie pomijana. Poza tym ten kod nie powinien się nawet skompilować.

+1 głos
odpowiedź 6 marca 2018 przez mokrowski Mędrzec (155,460 p.)
edycja 6 marca 2018 przez mokrowski

No dobrze... po publikacji treści zadania, IMHO masz następujące wyzwania ;)

1. Otworzyć poprawnie pliki i w przypadku niepowodzenia otwarcia, załamać program.

2. Iterować po danych w pliku wczytując kolejno słowa i w przypadku gdy słowo jest palindromem, wyświetlić je.

3. Po dojściu do końca danych wczytywanych, zamknąć poprawnie plik.

Pkt. 1 kwalifikuje się albo do wyjątku albo do brutalnego zakończenia programu przez exit().

Pkt. 2 Zgadzam się z @Radfler'em że powinna to być funkcja sprawdzająca czy słowo jest palindromem.

Pkt. 3 Tak się składa że destruktor obiektów ifstream/ofstream/fstream, poprawnie zamyka plik.

Nazwę pliku przekazujesz przez stałą referencję na std::string aby nie kopiować potencjalnie długich nazw. Jeśli z plikiem będzie coś .. "nie tak", nastąpi załamanie programu z wcześniejszym komunikatem na strumień błędów.

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>

std::ifstream openFile(const std::string& fileName) {
    std::ifstream file(fileName);
    if(!file) {
        std::cerr << "Błąd otwarcia pliku: " << fileName << '\n';
        exit(EXIT_FAILURE);
    }
    return file;
}

int main() {
    std::ifstream file = openFile("dane.txt");
}

Żeby zaproponować może coś innego niż koledzy... Zauważ że wystarczą 2 indeksy. Jeden na początku napisu, drugi na jego końcu. Porównywać można do momentu gdy pierwszy (początkowy) jest mniejszy niż drugi (końcowy). W zadaniu każde słowo ma 2 lub więcej znaków więc jesteś pewien że nie ma mniej. Normalnie byś to sprawdzał, tu się możesz powstrzymać.

#include <string>
#include <iostream>
#include <ios>

bool isPalindrome(const std::string& message) {
    size_t first = 0;
    size_t last = message.size() - 1;
    bool answer = true;
    while(first < last) {
        if(message[first] != message[last]) {
            answer = false;
            break;
        }
        ++first;
        --last;
    }
    return answer;
}

int main() {
    std::string msg = "ABBA";
    std::cout << std::boolalpha << isPalindrome(msg) << '\n';
}

Główna część programu to otwarcie pliku z przypisaniem do obiektu file oraz iterowanie przez while(!file) { ... } z wyświetlaniem palindromu. Tu już połącz funkcje w działający program :-)

 

PS. Przy użyciu iteratorów i algorytmów, kod staje się prosty :-)

#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <algorithm>

std::ifstream openFile(const std::string& fileName) {
    std::ifstream file(fileName);
    if(!file) {
        std::cerr << "Błąd otwarcia pliku: " << fileName << '\n';
        exit(EXIT_FAILURE);
    }
    return file;
}

bool isPalindrome(const std::string& message) {
    auto mid = message.cbegin() + (message.size() / 2);
    return std::equal(message.cbegin(), mid, message.crbegin());
}

int main() {
    auto file = openFile("dane.txt");
    std::istream_iterator<std::string> iBeg(file), iEnd;
    std::ostream_iterator<std::string> iOut(std::cout, "\n");
    std::copy_if(iBeg, iEnd, iOut, isPalindrome);
}

 

komentarz 7 marca 2018 przez Scypyon Gaduła (3,450 p.)
wygląda świetnie, jednak nie rozumiem 70% kodu ,a mianowicie:

auto file(tak domyślam się jednak pewności nie mam)

auto mid(analogicznie jak wyżej)

iBeg,iEnd,iOut,copy_if, w sumie nie wiem na jakiej zasadzie to działa :/
komentarz 7 marca 2018 przez Scypyon Gaduła (3,450 p.)
+ algorytm nawet się nie kompiluje
komentarz 7 marca 2018 przez mokrowski Mędrzec (155,460 p.)

@Scypion. U Ciebie się nie kompiluje bo czas zainstalować nowy kompilator albo użyć (w końcu) przełączników nowych wersji standardu. Kod jest jak najbardziej poprawny: https://godbolt.org/g/dqzPgZ      Na górze w okienku widzisz przełącznik -std=.... 

Typ auto to dedukcja typu dla C++11 (już 6 lat). W tym przypadku oszczędza klepania długiej nazwy typu. Algorytmy są zoptymalizowaną (i pozbawioną błędów) wersją wszelkiego rodzaju pętli które lepiej działają i wyglądają.

mid to iterator na środkowy element kontenera. Iterujemy od początku do środka porównując z elementami od końca (message.cebegin()). Errr w nazwie oznacza reverse. Cee w nazwie oznacza const. W efekcie Const Reverse Iterator.

komentarz 7 marca 2018 przez Scypyon Gaduła (3,450 p.)

@mokrowski niestety ale w takim razie ta wiedza jest mi zbędna :/ na maturze codeblocks jest, ja cpp potrzebuję tylko do matury ,a tak to uczę się frontendu i backendu :/ Mimo wszystko dzięki za poświęcony czas :) Bardzo doceniam :)

komentarz 7 marca 2018 przez mokrowski Mędrzec (155,460 p.)
Ok. C::B to tylko IDE. Możesz ustawić tryb pracy kompilatora przez 1 kliknięcie w ustawieniach.
komentarz 7 marca 2018 przez Scypyon Gaduła (3,450 p.)
Wiem, jednak egzaminator ma to wiadomo gdzie :/ na maturze mamy tak związane ręce... Nie można korzystać ze wszystkich bibliotek, tak samo zadanie ,które bez problemu pyknąłbym w JS - muszę robić w Cpp albo lepiej zadane,które zrobił bym w MySQL to muszę w acces
0 głosów
odpowiedź 6 marca 2018 przez Erfik878 Początkujący (310 p.)
musisz dopracować ten kod. kilka uwag

1. nie zamykasz pliku.

2. czemu otwierasz plik jednocześnie do odczytu i zapisu?

3. trochę źle napisałeś warunki w pętli for. za każdym razem, kiedy jakieś dwa znaki są te same, wyświetlasz całe słowo, natomiast kiedy są różne, łamiesz pętle całkowicie

4. zauważ, że dla słowa o parzystej liczbie pętla nie porówna środkowych liter (słowo panika ma 6 liter. ze wzoru (6-1)/2 = 2 (intiger ucina liczby po przecinku, nie zaokrągla) pętla i tak pominie porównanie 2, ponieważ dałeś znak mniejszości, zamiast mniejszy lub równy)

Myślę że dasz radę z poprawą kodu
0 głosów
odpowiedź 9 marca 2018 przez Beginer Pasjonat (22,110 p.)
edycja 9 marca 2018 przez Beginer
#include <string.h>
#include <iostream>
#include <fstream>

using namespace std;

void Palindrom(string slowo)                   //funkcja do wyszukiwania palindromów
    {
    int len = strlen(slowo.c_str());           //podaje dlugość słowa (ile jest znaków)

    for (int i = 0; i < len/2; i += 1)         //w pętli for pobieramy i porównujemy kolejne litery słowa
    {
     string litera_X (slowo, i, 1);            //pojedyncza litera brana z początku słowa
     string litera_Y (slowo, len - i - 1, 1);  //pojedyncza litera brane z końca słowa

     if (litera_X != litera_Y)                 //sprawdzenie czy litery się roznia
     return;                                   //przerywa dalsze sprawdzanie i wykonywanie funkcji
    }
     cout << slowo << endl;                    //wyświetla PALINDROM
    }

int main()
{
    ifstream mojPlik("dane.txt");  //otwarcie pliku do odczytu

    if (mojPlik)  //true (dobre otwarcie)
    {
      string wyraz;
      while (!mojPlik.eof())
      {
       mojPlik >> wyraz;  //pobranie wyrazu z pliku
       Palindrom(wyraz);  //wywołanie funkcji Palindrom
      }
    }
    else
    {
     cout << "\n ERROR: nie mozna otworzyc pliku do odczytu \n";
    }

    mojPlik.close();
    return 0;
}

Jeśli możesz poczekać do wieczora, to rozwiążemy kwestię PALINDROMY po szkolnemu (jak na maturze), w prosty sposób.

9.03.2018 godz.20.00

Powyżej zamieściłem kompletny kod do wyszukiwania palindromów. Jest prosty, logiczny, z dość dokładnym opisem. Jeśli masz jakieś pytania lub reklamacje daj znać.

komentarz 10 marca 2018 przez Kamil Krzysztof Użytkownik (660 p.)
Nie podobają mi się te minusy to generuje zła energię.
–1 głos
odpowiedź 9 marca 2018 przez Kamil Krzysztof Użytkownik (660 p.)

http://www.programmr.com/zone/cpp

http://www.programmr.com/zone/java

W drugim masz zadanko z polidrome
Pierwsze przeszukaj, polecam warto :)

 

Podobne pytania

0 głosów
1 odpowiedź 363 wizyt
pytanie zadane 22 marca 2021 w C i C++ przez fsfxvcxv Obywatel (1,160 p.)
0 głosów
1 odpowiedź 586 wizyt
pytanie zadane 22 marca 2021 w C i C++ przez fsfxvcxv Obywatel (1,160 p.)
0 głosów
1 odpowiedź 513 wizyt
pytanie zadane 3 listopada 2020 w C i C++ przez Niepokonana7999 Bywalec (2,250 p.)

92,454 zapytań

141,263 odpowiedzi

319,099 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...