13 / 13
Nov 2019

http://pl.spoj.com/problems/FR_02_M4/15
Nie wiem co jest nie tak z moim programem. Wiem, że algorytm jest dobry, sprawdzałem go. Jednak zapewne nie biorę pod uwagę jakiegoś głupiego wejścia albo nie formatuję odpowiednio wyjścia jak np brak nowej lini w ostatnim zestawie. Proszę pomoc.

#include <iostream>
#include <string>
using namespace std;
int main() {
    int z;
    cin>>z;
    getchar();
    while (z--) {
        string wzor;
        string zdanie,test;
        cin>>wzor;
        getline(cin, test);
        getline(cin,zdanie);
        int dla=zdanie.length(),dlb=wzor.length();
        int j=0;
        for (int i=0; i<dla; i++) {
            while(zdanie[i]==' ') {
                cout<<' ';
                i++;
            }
            if (j==dlb) {
                j=0;
            }
             cout<<char (((int (zdanie[i]) + int (wzor[j]) - 130) % 26) + 65);
             j++;
        }
        if (z!=0) cout<<endl;
    }
    return 0;
}
  • created

    Oct '15
  • last reply

    Nov '19
  • 12

    replies

  • 1.3k

    views

  • 7

    users

  • 3

    likes

  • 4

    links

Nie znam się to się wypowiem:P Nie programowałam w C++ ale po wstawieniu int przed getchar(); w linii 7 może Ci pomoże. Debugowanie tego kodu u mnie wykazało, że po zwróceniu uwagi na ten element zbudował się odpowiednio.

Przyjrzyj się trochę tutaj, jak dalej nie będzie działać:
http://www.cplusplus.com/reference/cstdio/getchar/6

O ile mi wiadomo getchar() potrzebuje nagłówka stdio.h, a tu go nie widzę.
Z resztą moim skromnym, zatrzymanie programu w tym miejscu nic nie daje, wywaliłbym tę linijkę.

while(zdanie[i]==' ') {
                cout&lt;&lt;' ';
                i++;
            }

Czy nikt Ci nie mówił, że to nieładnie robić i++ w środku pętli for (int i = 0; .....; i++) ?
Jak to zmienisz, [wiesz jak?], to masz gwarantowane AC wink

Dodatkowe pytanie, czemu tu, w tym zadaniu, to co w/w, powodowało WA [dla jakiego testu], bo oczywiście chociaż to nieładnie, można od czasu do czasu robić nieładne rzeczy, ale należy mieć tego świadomość, że to nieładnie wink a dodatkow często jest powodem błędów.

Przy okazji pozdrawiam serdecznie Jagodę 1992. Jagoda bardzo stara się aktywnie pomagać, dzięki i masz moje jedno malutkie serduszko wink

Jak czytałam to, aż mi się gorąco zrobiło:D W każdym razie dzięki

getchar miał wczytać znak końca linii za intem, zamieniłem go na getline'a ostatecznie.
Pamiętam że nauczyciel od programowania mówił że przy pascalu wywali nam błąd kompilator (co było prawdą) przy próbie zwiększenia licznika pętli ale w c++ chyba mówił że śmiało można tak robić i obędzie się bez błędów składniowych (co w zasadzie też jest prawdą). W tym kodzie musiałem przerobić trochę więcej rzeczy niż ta pętla for na while ale w końcu przeszło.
Te i++ w pętli mogło powodować wyjście poza zakres tablicy co powodowało odwołanie się do jakiejś tam wartości która powodowała krzaki.
Kod usunę, dla wyjaśniania błędów potomnych obędzie się bez niego smiley
Dzięki za pomoc.

jAK NAJBARDZIEJ [sorry włączył się capslock] wszystko prawda, ale ....

  1. Mogłeś śmiało postawić kreskę na getchar [dokładnie dwie '//'] i pozbyć się getchar(), był tam zupełnie niepotrzebny. Możesz zrobić teraz taki test. Dodać dwie kreski //, czyli zakomentować istrukcję getline, którą wstawiłeś zamiast getchar.
  2. Nie pisałem, że się nie skompiluje. Pisałem, że to brzydko i w tym zadaniu, gdy na końcu zdania była/y spacja, powodowało to błąd.
    " musiałem przerobić ... pętla for na while..."
    Ja raczej proponowałem pozbyć się pętli while, a nie for wink
    Np:.
    if (zdanie[i] == ' '){
    cout << ' ';
    continue;
    }
  1. Dostałem WA. Nie rozumiem dlaczego nie powinno być tam tego getline'a. Aktualnie po wczytaniu inta zostają zostają w tej samej linijce zostaje znak nowej linii + ileś tam spacji które wczyta ten getline. Bez niego w pierwszym obrocie pętli do stringa wzor zostaną wczytane spacji i znak końca linii.
  2. Wiem że tak nie napisałeś. Rozumiem że to brzydko po podbieram funkcjonalność pętli a tak nie powinno się robić. O czymś takim jak continue nie miałem pojęcia, ale już wiem co to i na przyszłość będę stosował smiley

AD 1
string wzór nie jest wczytywany funkcją getline, ale "normalnie" cin >> wzór.
Taki sposób wczytywania sam się "broni" przed wczytaniem wszelkich białych znaków, także '\n', więc nie potrzeba wcześniej wczytywać czy to pozostawionego znaku końca linii ['\n'] czy dowolnych dodatkowych spacji - jeżeli by się tam jakieś przypadkowo pojawiły.

AD 2
To był tylko przykład - jedna możliwość, wykorzystanie instrukcji continue.
Inna to NP.:

if (zdanie[i] == ' ')  
   cout << ' ';
else {
  ......

PS
Natomiast poniższa linia jest już niezbędna:
getline(cin, test);
ale powinieneś napisać [dla siebie] komentarz, po co ona jest.
np //usuwam '\n' znak końca linii
Zamiast tych dwóch linii, możesz też użyć dwa razy:
getline(cin,zdanie); // tu tylko usuwam-wczytuje '\n'
getline(cin,zdanie);
Moim zdaniem, jeszcze lepiej:

do 
   getline(cin, zdanie);
while (zdanie.length() < 1); // zadziała gdy nie będzie dodatkowych spacji+ '\n'

Dlaczego to jest [moim zdaniem] lepiej? Bo ta wersja też wczytuje dwa razy zdanie, ale dodatkowo ten fragment jest samodokumentujący się - wiadomo o co tu chodzi, bez dodatkowych komentarzy, prawda?

PS 2
Nie rozumiem, czemu po zakomentowaniu=usunięciu getchar() nie dostałeś AC, może pozmieniałeś coś więcej, ale to nie ważne, ważne, że masz AC wink

Przepraszam ale chyba usunąłem tamtego getline z kodu z którego miałem ac a nie z tej wersji w tym poście, zamotałem i szczerze mówiąc nie chce mi się bawić nad tym kodem dalej kiedy czekają inne zadania. Zostawmy ten temat w spokoju już. Tak jak powiedziałeś, ważne że jest AC a ja wiem co jest do poprawienia w moim programowaniu.
Tak czy tak dzięki za pomoc i rady.

2 months later

Witam, mógłby mi ktoś podpowiedzieć co w moim kodzie jest nie tak? U mnie na komputerze wszystko dobrze szyfruje tak jak jest w testach, natomiast na ideone.com pokazuje tylko pierwszy rezultat dobrze i wyskakuje błąd "Błąd wykonania". Cudowałem już z tym na różne sposoby i nie idzie mi tego poprawić.

#include <iostream>
#include <stdio.h>
using namespace std;
int tab[27][27];
string wyraz,klucz;
int d,e,ile;
int main()
{
   for(int i=1; i<=26; i++)
   {
      for(int j=1; j<=26; j++)
      {
         if(j+64+i-1>90)
         {
            tab[i][j]=(j+64+i-1-26);
         }
         else
         {
            tab[i][j]=(j+64+i-1);
         }
      }
   }
   cin>>ile;
   //
   while(ile--)
   {
       //
       cin>>klucz;
       getline(cin, wyraz);//
       getline(cin, wyraz);
       d=wyraz.length();
       e=klucz.length();
       int i=0;
       int j=0;
       while(i<d)
       {
          for(int j=0; j<e; j++)
          {
             if(wyraz[i]==' ')
             {
                wyraz[i]=' ';
                i++;       
             }
             wyraz[i]=(char)tab[(int)wyraz[i]-64][(int)klucz[j]-64];
             i++;
          }
          j=0;
       }
       cout<<wyraz;
       if (ile!=0) cout<<endl;
    }
    return 0;
}

link do ideone https://ideone.com/bWz2Eu3

Nie zważając na "bałagan", który zrobiłeś w kodzie odpowiem jedynie na Twoje pytanie. Twój kod działa tylko dla przypadków, dla których (długość wiadomości) % (długość klucza) == 0. W pozostałym przypadku, próbuje on wykorzystać pozostałą cześć klucza do zaszyfrowania znaków za wiadomością. Niektóre kompilatory pozwalają wyjść nieco poza zakres tablicy(stringa) w takiej sytuacji, a inne nie i wyrzucają błąd. Spróbuj więc sprawdzić czy nie próbujesz ustawić znaku w zmiennej wyraz, mając zmienną i, większą niż długość przechowywanego łańcucha.

3 years later