19 / 46
Dec 2019

Test:

in:
register 2
jan HAslo12!@
kowalski
login 3
jan 123
jan HAslo12!@
kowalski HA12@wes

twój out:
Zarejestrowano
Blad

mój (AC) out:
Zarejestrowano
Blad
Zle haslo
Zalogowano
Konto nie istnieje

Udało mi się rozwiązać test powyżej jednak nadal wyskakuje błędna odpowiedź.
Kod:hide
Będę bardzo wdzięczny za inne ciekawe dane wejściowe :pray:

edit: usuniecie kodu.

Login musi zawierać od 3 do 12 znaków:

if (lo.length() <= 3 && lo.length() >= 12) { // błędny warunek

Musisz dostosować się do kolejności podanej w zadaniu. W przypadku rejestracji gdy podany zostanie zajęty login i błędne hasło musisz wypisać “Blad”, a nie “Login zajety”.

PS. Spróbuj skrócić trochę kod i rozdziel warstwę logiki od operacji IO.

20 days later

Dziękuje wszystkim za pomoc. Dopiero dzisiaj udało mi się usiąść do tego zadania i je zrobić. Udało się, jeszcze raz dziękuje za pomoc.
Dokładnie jak pisze hipcia - trzeba dostosować się do kolejności w zadaniu.

BTW. W próbach sędziego nie ma pustego hasła :wink:

2 months later

Proszę o podpowiedź dotyczącą tego zadania, już naprawdę mam mam dosyć a jestem zbyt uparty żeby sobie odpuścić. Mój kod https://pastebin.com/hEccTrmB20 oraz jeszcze zapytam czy tu może być problem z podawaniem wartości przez cin?

cout << "register ";
cin >> registerAttemps;

Na wejściu pojawi się nieokreślona liczba zestawów zawierająca słowa register/login - dlatego powinieneś wczytać stringa i wykonać podaną operację:

int attempts;
std::string command;
while (std::cin >> command >> attempts) {
    if (command == "register") {/*register*/}
    else if (command == "login") {/*login*/}
}

W funkcji main masz zdublowany fragment kodu. To wszystko :wink:

Nie rozumiem pytania - cin służy do wczytywania.

Problem polega między innymi na tym, że twoje rozwiązanie nie jest poprawne nawet dla testów przykładowych z zadania, więc będzie WA.

I tu pytanie, czy Ty testujesz swoje rozwiązanie i jeżeli tak to jak?

Można testować u siebie, albo na ideone.com6 - po wklejeniu przykładowego wejścia z zadania lub swojego/innego testu do okienka stdin : https://ideone.com/LE9LpC7 [podałeś błędny - nie kompilujący się kod, poprawiłem go, tylko tak aby się kompilował].

W twoim programie, wszystkie cout << "login...., cout << "register .... są zbędne i są błędem. Wczytywanie danych też masz błędne.
Poprawnie możesz tak jak zaproponował @hipcia:

int main () {
  // deklaracja potrzebnych zmiennych - 
while (cin >> command >> attemps) {//powtarzaj, dopóki są jeszcze dane do wczytania
     if (command == "register") {
           //twój kod obsługujący rejestrację powtórony attemps razy
          }
      else { 
          // twój kod obsługujący logowanie powtórzony attemps razy
          }
}

PS
Jeżeli wzorujesz się na stylu Stańczyka, to jego książka nie jest do nauki języka C++, a dodatkowo jest już nieco przestarzała.

Makra w C++ to spadek po języku C, i w C++14 np.: zamiast makra FOREACH:

 FOREACH(it, account){
        cout << it->first << " " << it->second << "\n";
    }

można i jest to dużo lepiej:

for (auto i : account)
        cout << i.first << ' ' << i.second << '\n';

itd.

@narbej Range-based for pojawił się w C++11. Dodałbym również referencję do deklaracji typu, ponieważ std::pair nie można trywialnie kopiować.

Ty to wiesz, ja to wiem, ale chodziło mi tylko i wyłącznie o to, że na spoju jest już dostępny właśnie C++14, a nie C++11, 17 czy 20.

Testuje swoje rozwiązania w cmd w visual studio code przy użyciu komendy a.exe, natomiast nie wiem jak dokładnie działa sędzia na spoju. Ten link który mi podałeś https://ideone.com/LE9LpC8 to w stdout sędzia otrzymuje takie wyjście?

Tak - przynajmniej starać się rezygnować.
Nie - makra, a szczególnie przedstawione w książce Algorytmika praktyczna … miały zwiększyć szybkość i wygodę kodowania, a nie szybkość samego wynikowego programu jako takiego. Oczywiście ktoś może twierdzić, że wstawienie kodu do programu [rozwijanie makr] daje szybszy kod, niż kod z wywołaniami funkcji - ale przecież są też funkcje inline…

Może nie dokładnie - w końcu, oprócz najprostszego sędziego [programu] są także czasami specjalne programy pisane przez autora zadania.
Ogólnie twój program “potraktowany” zostaje testem - przekierowanie pliku i produkuje odpowiedzi - też przekierowane zostaje do pliku. Potem już tylko porównanie pliku przygotowanego przez autora z twoim.

Czyli jeżeli testujesz u siebie w cmd - używając klawiatury, to jest to dobry sposób tylko dla prostych zadań. Dla trudniejszych, możesz przygotować plik/i testowe in.txt, oraz wynikowy out.txt [np kopijąc z zadania]
Potem:

C:\....> twój_program.exe < in.txt >twoj_out.txt [ENTER]

Poczytaj, o przekierowaniach.

Teraz pozostaje już tylko porównać [najlepiej programowo]:

c:\...> jakis_diff.exe  twoj_out.txt   out.txt  [ENTER]

Dodatkowo możesz “opakować” [samo] testowanie w automatyczny pomiar czasu, ale wtedy musisz przygotowywać swoje większe testy, bo dla małych nie ma to sensu.

Ja używam linuxa i czasami robię/robiłem podobnie …, teraz częściej korzystam z ideone.

Teraz zacząłem testować swój kod na stronie ideone.com1 i teraz spotkałem się z takim problemem, że nie wiem dlaczego na tym serwisie niepoprawnie porównuje mi tablice znaków tzn.

  • mam funkcje is_login_contain_illegal_char w której porównuje mi znaki z loginu do tablicy znaków AsciiSpecialCharacter z tymi specjalnymi znakami, które nie powinny znajdować się w loginie.
  • następnie funkcja ta dla każdego znaku zwraca informacje, że każda litera jest znakiem specjalnym.


Tutaj jest wynik programu
tablica AsciiSpecialChar znajduje się w 28 linicie,
a funkcja is_login_contain_special_character w 128 linijce.

Dodam jeszcze, że u mnie działa na komputerze tylko mam problem na tej stronie.

Krótko:
Linia 134 wtwoim kodzie jest błędna i powinna Cię dodatkowo skłonić do przemyślenia plusów i minusów używania makr.

Pochwała:
Skupiłem się tylko na tej jednej funkcji - w linii 128 i brawo, że sam potrafiłeś to zdiagnozować.

Maleńka krytyka:

  1. Twój program jest zdecydowanie za długi i twój sposób sprawdzania - pętla zagnieźdźona w pętli może okazać się za wolny.
  2. Masz dużo inkludów - wszystkichg potrzebujesz? - ogranicz ich liczbę tylko do potrzebnych, lub zastosuj:
    #include <bits/stdc++.h> <— lista wszystkich bibliotek w STL, ale czy działa pod windows? To też nie jest to dobre ale …
  3. To jak z tymi makrami? Rezygnujesz? :wink: Masz makra na first i last, a w programie ich nie wykorzystujesz:
    cout << it.first << " " << it.second << "\n";
    zamiast:
    cout << it.ST << " " << it.ND << "\n";
    Możliwe, że jest więcej - ale nie przęglądałem dokładnie twojego kodu.
  4. tablica: static char AsciiSpecialCharacters[32] = {'!', '"', '#', '$', '%', '&', '*', ..... jest globalna, więc nie musisz zaznaczać, static.
  5. można: char AsciiSpecjal[] = "!#$%&*@..........";
  6. Lepiej string AsciiSpecjal = "!#$%&*@..........";
  7. lub: string AsciiSpecjal {"!#$%&*@.........."};
  8. Można to sprawdzić łątwiej i krócej, ale miało być krótko :wink:
  9. No i jeszcze te śmieci [komentarze na końcu]
  10. Ale się nie przejmuj, walcz, a jak coś pytaj śmiało.

Dzięki za wszystkie rady @narbej oraz @hipcia w końcu dostałem AC.
Rezygnuje z makr, ponieważ gdybym z nich nie korzystał to bym program skończył około 2 tygodnie temu.

Gratuluję!!

Brawo, cieszy mnie to.

PS
Ale zdajesz sobie sprawę, że spoj nie potrafi ocenić jakości kodu? Mógłbym ewentualnie podać Ci trochę wskazówek i trochę krytyki twojego kodu, gdybyś chciał.

Ok
Potraktuj to jako swego rodzaju prezent pod choinkę :wink:

Dotyczy to twojego starego kodu, w nowym, może część rzeczy pozmieniałeś/usunąłeś.

  1. // https://p…content-available-to-author-only…j.com/problems/FR_07_03/ <-- ten link jest błędny :wink:
  2. Nadmiar importowanych bibliotek, na zapas nie jest dobry, ale jeżeli jednak chcesz to robić, to możesz wypróbować:
    #include <bits/stdc++.h> <— włączasz wszystkie/większość bibliotek.
  3. Używanie using namespace std; + pkt.1 ułatwia pisanie prostych - krótkich kodów, ale może spowodować konflikt/y nazw. Spróbuj na przykład użyć do swojej zmiennej nazwy time.
  4. Jeżeli dołączasz jawnie [nie bits/stdc++.h] wiele bibliotek, to czasami warto wiedzieć, jakie są tam ukryte skarby :wink: Np. <cctype> zawiera miedzy innymi isdigit(), isupper(), islower(), toupper()… itd.
  5. Pisałem już wcześniej o tablicy, ale jeszcze do samej nazwy: AsciiSpecialCharacters znaki i char to prawie zamienniki, albo to samo ale w różnych językach a dodatkowo natychmiast kojarzą się z tablicą kodów ASCII. W takim razie nazwa tablicy mogłaby brzmieć np: charSpecial, ale gdy dodamy typ zmiennej, to: char charSpecjal, wydaje się nadmiarowa i że nazwa char specjal[] wystarczy. Przecież, z załaczonego linku do zadania a i z samego kodu wynika, że nie chodzi tu przecież o piwo.
  6. map<string, string> account; <-- [wyjątkowo] można zrobić globalną, w przeciwieństwie do tablicy specjal, która potrzebna jest tylko funkcji register. Można też utworzyć i zamknąć to wszystko w klasie, ale to już inna bajka.
  7. …zostało jeszcze sporo, a może i tak to nie aktualne?

Łatwiej może będzie jak po prostu wyślę Ci mój pierwszy kod na PM i sam sobie spróbujesz porównać i się czegoś nauczyć?

        if(numberOccurence == false) FOR(n, 48, 57){
            if((char)(n) == password[i]){
                numberOccurence = true;
            }
        }

Powyższy blok, jeżeli chciałbym to robić w tym samym duchu, ja zapisałbym:

FOR (n, '0', '9')
   

a naprawdę należy inaczej przeprogramować pętlę np:

dla kolejnego znaku c w haśle:
      jeżeli jest to cyfra <np isdigit(c)> to zaznacz
      else jeżeli to wielka litera .... to zaznacz
      else jeżeli mała zaznacz
      w przeciwnym wypadku, jeżeli to nie cyfra, mała ani duża litera to jest znakiem specjalnym  zaznacz to

funkcje isdigit(), isupper(), islower() są bardzo proste, można skorzystać z biblioteki <cctype> lub napisać własne, np:

bool isdigit (char c) {
   return (c >= '0' and c <= '9')
}
char tolower (char c) {
       if (isupper (c)) c += 'a' - 'A';
       return c;
}