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

[C++] Matura 2016 zadanie 6.2 - Ocena kodu oraz uwagi

VPS Starter Arubacloud
0 głosów
578 wizyt
pytanie zadane 28 marca 2019 w C i C++ przez Kacper Sas Dyskutant (8,460 p.)

Witam, widziałem iż istnieją już tematy o zadaniu 6.2, jednakże nie chciałem ich odkopywać (kwiecień 2018). Rozwiązałem zadanie i widząc jak diametralnie różni się mój kod od innych chciałbym poprosić bardziej doświadczonych ode mnie o ocenę oraz uwagi (przyda się na przyszłość), co można by było zrobić inaczej :)

 

Treść:

W pliku dane_6_2.txt zapisano 3 000 szyfrogramów i odpowiadające im klucze
szyfrujące. W każdym wierszu znajduje się jeden szyfrogram (zaszyfrowane słowo)
i po pojedynczym znaku odstępu odpowiadający mu klucz (maksymalnie czterocyfrowa
liczba).
 
Fragment pliku dane_6_2.txt:
 
BCYKUNCM 1718
YFOGNSKGYW 7580
WARDA 9334 
 
Napisz program, który odszyfruje słowa zaszyfrowane podanymi kluczami. Wynik zapisz
w pliku wyniki_6_2.txt: każde odszyfrowane słowo w osobnym wierszu, w porządku
odpowiadającym kolejności szyfrogramów z pliku z danymi.
 
Uwaga:
Dla pierwszego szyfrogramu z pliku dane_6_2.txt (BCYKUNCM) wynikiem jest słowo
ZAWISLAK.

Kod:

#include <iostream>
#include <fstream>

int main(void) {

    std::ifstream fData("dane_6_2.txt");
    std::ofstream fOutput("wynik_6_2.txt");

    std::string sHashed;
    int iKey;

    auto aDecode = [](std::string sHashed, int iKey){
        iKey %= 26;
        for(auto & aLetter : sHashed)
            aLetter = (!((int)aLetter - iKey < 65) ? (int)aLetter - iKey : 91 + ((int)aLetter - 65 - iKey));
        return sHashed;
    };

    while(fData >> sHashed >> iKey)
        fOutput << aDecode(sHashed, iKey) << std::endl;

    return 0;
}

Pozdrawiam.

2 odpowiedzi

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

Jedynie drobne poprawki. Jeszcze można się czepiać wartości magicznych w kodzie ale dla tak krótkiego kodu i znając jego przeznaczenie/kontekst użycia, można je zostawić.

#include <iostream>
#include <fstream>

int main(void) {

    std::ifstream fData("dane_6_2.txt");
    std::ofstream fOutput("wynik_6_2.txt");

    std::string sHashed;
    int iKey;

    auto aDecode = [](std::string& hashed, int key) {
        key %= 26;
        for(auto & aLetter : hashed) {
            aLetter = (!(static_cast<int>(aLetter) - key < 65) ?  static_cast<char>(aLetter - key) : static_cast<char>(91 + aLetter - 65 - key));
        }
        return hashed;
    };

    while(fData >> sHashed >> iKey) {
        fOutput << aDecode(sHashed, iKey) << std::endl;
    }
}

PS. Proponuję stosować dla clang++, opcje ostrzeżeń takie lub zbliżone:

-Weverything -Wno-c++98-compat

 

komentarz 28 marca 2019 przez Kacper Sas Dyskutant (8,460 p.)
Czy jest potrzeba przekazywać ten łańcuch przez referencję? Nie użyłem jej, ponieważ modyfikowałem łańcuch tylko wewnątrz ciała, a potem zwracałem go. Zwątpiłem w tej chwili :x Dzięki za zwrócenie uwagi na rzutowanie. Miałem gdzieś z tyłu w głowie, że rzutowanie w pierwotny sposób jest nieco niepoprawne. Mocne postanowienie poprawy i do przodu :)
1
komentarz 28 marca 2019 przez mokrowski Mędrzec (155,460 p.)

Co do referencji na std::string..

1. Przyjąłeś konwencję przesyłania łańcucha "przez funkcję" aDecode, więc czemu nie.

2. Co do wydajności, współczesne kompilatory oczywiście optymalizują przesyłanie łańcuchów. Jeśli uda się im "w jednym strzale" (czyli pojedynczej operacji w asemblerze), przesłać całość łańcucha bo wiedzą że jest krótki, to obojętne czy będzie tam referencja czy nie. Tu nie wiedzą.

3. Jeśli łańcuch jest długi, wykonujesz zbędne kopiowania.

3. Podając referencję wyraźnie sugerujesz że to jest przejście "przez funkcję". IMHO to ważne dla czytania kodu.

4. Zużywasz z referencją zawsze mniej pamięci niż przez kopiowanie.

5. Takie działanie będzie szybsze.

Sam rozważ. Moim zdaniem ogólnie warto, tu oczywiście to wprawka ale prosiłeś o "czepianie się" :)

komentarz 28 marca 2019 przez Kacper Sas Dyskutant (8,460 p.)
Właśnie super :) Przecież to jest logiczne, a jednak się zagubiłem, dzięki za uwagę :) Zginąłem od własnej broni, nienawidzę, gdy nauczyciel od informatyki mówi "komputer i tak ma dużo pamięci". Od teraz będę miał stringa na uwadze! :)
komentarz 28 marca 2019 przez mokrowski Mędrzec (155,460 p.)

Co do języków C i C++, same zastosowania i sektor w jakim operują, powodują że powinieneś mieć "hopla" na punkcie wydajności i konsumpcji zasobów. Wybiera się je z tego powodu że mają duże możliwości optymalizacji. Jeśli optymalizacja to użycie jednego & to wydaje mi się że raczej warto.

PS. Kolega zaproponował std::transform. To bardzo dobry wybór jak już opanujesz pojęcie iteratorów i możliwości z <algorithm>. Jeśli masz możliwość ich użycia, zdecydowanie warto.

+1 głos
odpowiedź 28 marca 2019 przez RafalS VIP (122,820 p.)

Z czystej ciekawości czemu lambda a nie zwykła funkcja?

Rozumiem, że chcesz pisać nowoczesny kod, ale ja nie za bardzo widzę tutaj sens takiego rozwiązania.

Twoja lambda ani nie jest nigdzie przekazywana ani nie jest króciutką nienazwaną funkcją wstawioną inline jako argument innej funkcji.

Nie mówię, że rozwiązanie jest złe, po prostu nie rozumiem wyboru.

Osobiście wykorzystałbym z std::transform:

	while (fData >> sHashed >> iKey) {
		iKey %= 26;
		std::transform(sHashed.begin(), sHashed.end(), 
			std::ostreambuf_iterator<char>(fOutput), [iKey](char c) {
            return (static_cast<int>(c) - iKey >= 65 ? static_cast<int>(c) - iKey : 
                91 + (static_cast<int>(c) - 65 - iKey));
		});
		fOutput << std::endl;
	}

 

komentarz 28 marca 2019 przez Kacper Sas Dyskutant (8,460 p.)
Otóż zastosowałem lambdę, ponieważ nie tak dawno zacząłem poznawać uroki C++11 :) Uznałem, iż będzie to w miarę praktyczne zastosowanie, ponieważ jest to jedyna funkcja jaką wywołuje, więc fajnie by było mieć wszystko w "main'ie". Poza tym pomimo uroczego wyglądu, utrwalam sobie jak nie w inny to w taki sposób nowości. Dzięki za uwagę, może faktycznie to trochę jak armata na muchę. Twój przykład ma dla mnie trochę smaczków, wezmę go na warsztat i od "bebechów" przeanalizuje, dzięki! :)

Podobne pytania

0 głosów
1 odpowiedź 2,867 wizyt
0 głosów
0 odpowiedzi 5,313 wizyt

92,454 zapytań

141,262 odpowiedzi

319,089 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!

...