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

jak umozliwic 2 klasom korzystanie z 1 funkcji w 1 pliku.cpp

VPS Starter Arubacloud
0 głosów
284 wizyt
pytanie zadane 15 sierpnia 2020 w C i C++ przez lujasjeden Użytkownik (860 p.)
edycja 15 sierpnia 2020 przez lujasjeden

Mam takie kody:

polynomials.h

#include <iostream>

using namespace std;

class Polynomial
{
public:
    virtual void gather()=0;
    virtual void show()=0;
};

class Wx :public Polynomial
{
protected:
    string userStringNum;
    int degree;
    int helper;
    float *coefficients;

public:
    virtual void gather();
    virtual void show();
    void isInteger(int &d);

    Wx(string="0", int=0, int=0);
    ~Wx();

};

class Px :public Wx
{
public:
    virtual void gather();
    virtual void show();
    Px(string="0", int=0, int=0);
    ~Px();
};

isInteger.cpp:

#include <iostream>
#include "polynomials.h"
#include <ctype.h> // isdigit()
#include <sstream> // stringstream
using namespace std;

void Wx::isInteger(int &d)
{
    int isInt=0;
    int decimalCount=0;

    bool isIntBool=false;
    bool containsSpaces = false;

    do
    {
        getline(cin, userStringNum);
        for (int i=0; i<userStringNum.size(); i++)
        {
            if (isspace(userStringNum[i]))
                containsSpaces=true;
        }

        if (userStringNum[0] == '-')
        {
            isInt++;

            if (userStringNum[1]=='0')
                isInt=0;
        }

        if ((userStringNum[0]=='0' && isdigit(userStringNum[1])))
            isInt = 0;
        else
        {
            for (int i=0; i<userStringNum.size(); i++)
            {
                if (isdigit(userStringNum[i]))
                    isInt++;
                if (userStringNum[i]=='.')
                    decimalCount++;
            }
        }

        if (decimalCount==1)
            isInt=0;

        if (isInt==userStringNum.size() && containsSpaces==false)
        {
            stringstream str_stream_object(userStringNum);
            str_stream_object>>d;

            isIntBool=1;
        }

        else
        {
            cout<<endl;
            cout<<"Degree of polynomial has to be an integer greater than 0, try again: ";

            isIntBool=0;
            isInt=0;
            decimalCount=0;
            containsSpaces=false;
        }

    }
    while (isIntBool==0);
}

gatherWx:

#include <iostream>
#include "polynomials.h"
using namespace std;

void Wx::gather()
{
    cout<<"Input degree of polynomial W(x): ";
    isInteger(degree);
    cout<<endl;
}

gatherPx:

#include <iostream>
#include "polynomials.h"
using namespace std;

void Px::gather()
{
    cout<<"Input degree of polynomial P(x): ";
    isInteger(degree);
    cout<<endl;
}

jakim cudem isInteger dziala w pliku gatherPx skoro w pliku isInteger jest tylko taki zapis:

void Wx::isInteger(int &d)

nie ma w ogole Px::isInteger

komentarz 15 sierpnia 2020 przez ScriptyChris Mędrzec (190,190 p.)
Proszę poprawić tytuł tematu, żeby zwięźle i dokładnie opisywał problem.

1 odpowiedź

0 głosów
odpowiedź 15 sierpnia 2020 przez adrian17 Ekspert (344,100 p.)

jakim cudem isInteger dziala w pliku gatherPx skoro w pliku isInteger jest tylko taki zapis:

Px dziedziczy po Wx, więc korzysta z jego isInteger. Dokładnie po to jest dziedziczenie.

komentarz 15 sierpnia 2020 przez lujasjeden Użytkownik (860 p.)

mozliwe ze cos porypalem w argumentach bo  w sumie nie rozumiem tego w 100% i jestem zmeczony ale prosilbym o odpowiedz czemu w takim razie to nie dziala:

 

main:

#include <iostream>
#include "polynomials.h"
using namespace std;

int main()
{
    Wx w;
    Px p;

    w.gather(w.userStringNum);
    p.gather(p.userStringNum);
}

polynomials.h

#include <iostream>

using namespace std;

class Wx
{
public:

    string userStringNum;
    int degree;
    int helper;
    float *coefficients;

public:

    void gather(string &uNS);
    void show();
    void isInteger(int &d);

    Wx(string="0", int=0, int=0);
    ~Wx();

};

class Px :public Wx
{
public:
    void gather(string &uNS);
    //void show();
    void isInteger(int &d);

    Px(string="0", int=0, int=0);
    ~Px();
};

gatherWx:             //bedzie nazywal sie gather jezeli bede mogl to polaczyc i uzywac 1 pliku

#include <iostream>
#include "polynomials.h"
using namespace std;

void Wx::gather(string &uNS)
{
    cout<<"Input degree of polynomial W(x): ";
    isInteger(degree);

    cout<<endl;
}

wiem, ze nawet jak zadziala to bedzie wyswietlalo 2 razy W(x) a nie najpierw W(x) a potem P(x) ale to chyba jakos sie ogarnie

komentarz 15 sierpnia 2020 przez adrian17 Ekspert (344,100 p.)

czemu w takim razie to nie dziala

W jakim sensie nie działa? Nie wiem do czego nawiązujesz. Gdybym miał strzelać to...

class Px :public Wx
{
public:
    void gather(string &uNS);

Zadeklarowałeś nową metodę Px::gather, ale jej nie zaimplementowałeś, więc pewnie linker krzyczy?

komentarz 15 sierpnia 2020 przez lujasjeden Użytkownik (860 p.)
no dokladnie tak, z tym ze jak ja zaimplementuje to wychodzi 2 razy deklaracja dokladnie tej samej metody z roznica ze jedna jest do Wx a druga do Px, co prawda kazda klasa ma swoje atrybuty, ale myslalem ze da sie to jakos rozwiazac w 1 pliku. Myslalem ze dzieki dziedziczeniu i polimorfizmowi bedzie mniej kodu a wychodzi podobnie wszystko.
komentarz 15 sierpnia 2020 przez adrian17 Ekspert (344,100 p.)
Niezbyt rozumiem... mówisz sprzeczne rzeczy. Jeśli ją implementujesz dwukrotnie to nie korzystasz z dziedziczenia, więc nic dziwnego że nie pomaga.
komentarz 15 sierpnia 2020 przez lujasjeden Użytkownik (860 p.)

w innym kodzie (w kopii) mam tak: 

polynomials.h:

#include <iostream>

using namespace std;

class Polynomial
{
public:
    virtual void gather()=0;
    virtual void show()=0;
};

class Wx :public Polynomial
{
protected:
    string userStringNum;
    int degree;
    int helper;
    float *coefficients;

public:
    virtual void gather();
    virtual void show();
    void isInteger(int &d);

    Wx(string="0", int=0, int=0);
    ~Wx();

};

class Px :public Wx
{
public:
    virtual void gather();
    virtual void show();
    Px(string="0", int=0, int=0);
    ~Px();
};

gatherWx:

#include <iostream>
#include "polynomials.h"
using namespace std;

void Wx::gather()
{
    cout<<"Input degree of polynomial W(x): ";
    isInteger(degree);
    cout<<endl;
}

gatherPx:

#include <iostream>
#include "polynomials.h"
using namespace std;

void Px::gather()
{
    cout<<"Input degree of polynomial P(x): ";
    isInteger(degree);
    cout<<endl;
}

main:

#include <iostream>
#include "polynomials.h"
using namespace std;

int main()
{
    Wx w;
    Px p;

    Polynomial *pointerWx;
    Polynomial *pointerPx;
    pointerWx=&w;
    pointerPx=&p;
    pointerWx->gather();
    pointerPx->gather();
    pointerWx->show();
    pointerPx->show();
}

isInteger:

#include <iostream>
#include "polynomials.h"
#include <ctype.h> // isdigit()
#include <sstream> // stringstream
using namespace std;

void Wx::isInteger(int &d)
{
    int isInt=0;
    int decimalCount=0;

    bool isIntBool=false;
    bool containsSpaces = false;

    do
    {
        getline(cin, userStringNum);
        for (int i=0; i<userStringNum.size(); i++)
        {
            if (isspace(userStringNum[i]))
                containsSpaces=true;
        }

        if (userStringNum[0] == '-')
        {
            isInt++;

            if (userStringNum[1]=='0')
                isInt=0;
        }

        if ((userStringNum[0]=='0' && isdigit(userStringNum[1])))
            isInt = 0;
        else
        {
            for (int i=0; i<userStringNum.size(); i++)
            {
                if (isdigit(userStringNum[i]))
                    isInt++;
                if (userStringNum[i]=='.')
                    decimalCount++;
            }
        }

        if (decimalCount==1)
            isInt=0;

        if (isInt==userStringNum.size() && containsSpaces==false)
        {
            stringstream str_stream_object(userStringNum);
            str_stream_object>>d;

            isIntBool=1;
        }

        else
        {
            cout<<endl;
            cout<<"Degree of polynomial has to be an integer greater than 0, try again: ";

            isIntBool=0;
            isInt=0;
            decimalCount=0;
            containsSpaces=false;
        }

    }
    while (isIntBool==0);
}

isInteger nieistotny tu w sumie akurat ale zebys wiedzial po co jest w  gatherach, no a showWx i showPx tym bardziej nieistotne,

Ok chodzi mi o to ze gatherWx i gatherPx w zasadzie roznia sie tylko argumentami i  ze w jednym pisze W(x) a w drugim P(x), nie jest to niepotrzebna redundancja? Nie da sie tego jakos sprytniej zrobic? Czy tak ma byc wlasnie?

1
komentarz 15 sierpnia 2020 przez adrian17 Ekspert (344,100 p.)

w zasadzie roznia sie tylko argumentami

gdzie? Bo nic takiego nie widzę.

Widzę tylko różnicę w wypisywanych stringach... ale ten wypisywany string to 50% kodu gather(), więc nic dziwnego że w obu miejscach _coś_ trzeba napisać osobno.

Inna sprawa, że ogólnie ten kod jest dość dziwnie napisany :P Po funkcji o nazwie "isInteger" spodziewałbym się 5 linii kodu, nie 60 i gadania z userem...

komentarz 15 sierpnia 2020 przez lujasjeden Użytkownik (860 p.)
to jakbys inaczej sprawdzil czy wpisany znak z klawiatury jest liczba calkowita?

jezeli tak trzeba to ok, myslalem ze da sie to zrobic w jednym pliku i jakby polaczyc to i podsylac gather argumenty, ale jest to moj pierszy projekt z uzyciem oop wiec nie znam sie za bardzo dlatego pytam
1
komentarz 15 sierpnia 2020 przez adrian17 Ekspert (344,100 p.)

to jakbys inaczej sprawdzil czy wpisany znak z klawiatury jest liczba calkowita?

Cały ten kod w ogóle nie powinien być w klasie, parsowanie tekstu ma 0 związku z klasą zajmującą się wielomianami. To powinna być osobna funkcja.

To po pierwsze. Po drugie:

to jakbys inaczej sprawdzil czy wpisany znak z klawiatury jest liczba calkowita?

Zrobiłbym

cin >> liczba;

i sprawdził czy się udało. Jak nie, to nie wpisał liczby całkowitej... i tyle. Nie wiem po co tą całą analizę stringa pisałeś.

komentarz 15 sierpnia 2020 przez lujasjeden Użytkownik (860 p.)
Że cin.fail? Zrobiłem tak ale wpisując rzeczy typu 123hshs odczytuje jako 123

Czyli funkcje isInteger wywalić z obu klas i dać jako osobna funkcje? Zaprzyjaźnić ja z obiema klasami i tak je wywoływać? Tylko że problem taki że jak tak próbowałem to coś nie wychodziło przez to że funkcja nie była dostępna w funkcji gather
2
komentarz 15 sierpnia 2020 przez adrian17 Ekspert (344,100 p.)

Zrobiłem tak ale wpisując rzeczy typu 123hshs odczytuje jako 123

To brzmi jakbyś nie sprawdzał, że się nie udało.

Zaprzyjaźnić ja z obiema klasami i tak je wywoływać?

Nie, nie zaprzyjaźniać, to jest równie złe. Nie ma żadnego powodu by funkcja pytająca użytkownika o liczbę miała wiedzieć cokolwiek o klasach wielomianów.

komentarz 16 sierpnia 2020 przez lujasjeden Użytkownik (860 p.)

A jak się sprawdza czy się nie udało?

Nie, nie zaprzyjaźniać, to jest równie złe. Nie ma żadnego powodu by funkcja pytająca użytkownika o liczbę miała wiedzieć cokolwiek o klasach wielomianów.

To w jaki sposób to zrobić? Ma to być globalna funkcja która wywołuje w funkcjach gatherWx i gatherPx?

komentarz 16 sierpnia 2020 przez adrian17 Ekspert (344,100 p.)

A jak się sprawdza czy się nie udało?

Na przykład

https://stackoverflow.com/a/40031777/2468469

Ma to być globalna funkcja która wywołuje w funkcjach gatherWx i gatherPx?

Mówię o isInteger.

komentarz 16 sierpnia 2020 przez lujasjeden Użytkownik (860 p.)
Ja też, co z nią proponujesz zrobić jeżeli zdecydowałbym się funkcje isInteger zatrzymać?, później potestuje to co wysłałeś w linku bo narazie nie mam jak
komentarz 16 sierpnia 2020 przez lujasjeden Użytkownik (860 p.)
#include <iostream>

using namespace std;

int main()
{
    string response;
    cin>>response;

    size_t index=0;
    auto result = stoi(response, &index);

    if(index == response.length()){
    cout<<"ok";
    return result;
}
else{
    cout<<"nie ok";
}
    return 0;
}

dla np input: "a"

output:


terminate called after throwing an instance of 'std::invalid_argument'
  what():  stoi

Process returned 3 (0x3)   execution time : 5.540 s
Press any key to continue.

1) nie wiem co to size_t result i auto

2) nie dziala tak jakbym chcial

komentarz 16 sierpnia 2020 przez tkz Nałogowiec (42,000 p.)
komentarz 16 sierpnia 2020 przez lujasjeden Użytkownik (860 p.)
edycja 16 sierpnia 2020 przez lujasjeden
Ej dobra bo teraz to juz sie kompletnie zgubilem, proste pytanie czy jak odziedziczam w klasie Px atrybuty od Wx, to np operujac w funkcjach Wx::gather oraz Px::gather to operuje tak naprawde na tym samym?

Czy jak Px dziedziczy od Wx to dostaje jakby nowe stworzone odzielne atrybuty z tymi samymi nazwami ale pobierajac jaki atrybut od uzytkownika z klawiatury w funkcji Wx::gather to leci to do atrybutu tylko Wx czy do obu

 

Bo tak teraz sobie zdalem sprawe, ze jezeli nie przeslonie tych atrybutow w klasie pochodnej to nie jestem pewny jak to dziala, a znowu jak przeslonie to przeciez pisze dokladnie to samo jakbym nie robil dziedziczenia, juz nic nie rozumiem
komentarz 16 sierpnia 2020 przez tkz Nałogowiec (42,000 p.)
Tak średnio rozumiem Twój potok słów.
Jeżeli masz klasę A i klasę B, która dziedziczy po A, to klasa B nie dzieli pamięci z klasą A. Wszystko jest osobne. Dzielą TYLKO implementację.
komentarz 16 sierpnia 2020 przez lujasjeden Użytkownik (860 p.)
a ok, czyli ze jezeli wczytam jakis atrybut klasy A to klasa B go sobie rowniez nie przypisuje?
komentarz 16 sierpnia 2020 przez tkz Nałogowiec (42,000 p.)
// Example program
#include <iostream>

class A
{
    protected:
    int x;
    public:
    A(){}
    A(int _x):x{_x}{}
    int print(){return x;}
};

class B : public A
{
    public:
    B(){}
    B(int _x){x=_x;}
};

int main()
{
    A a(4);
    std::cout<<a.print()<<'\n';
    B b(3);
    std::cout<<b.print()<<'\n';
    std::cout<<a.print()<<'\n';

}

Nie przypisuje. 

komentarz 16 sierpnia 2020 przez lujasjeden Użytkownik (860 p.)

to ja juz nic nie wiem, siedze pare dni i praktycznie nic nie mam, dlaczego jak ten program dochodzi do momentu wywolania 

pointerPx->gather();

to nie wczytuje mi juz z klawiatury userStringNum, dla Wx wczytuje dla Px nie, domyslam sie, ze chodzi o to ze isInteger nie ma dostepu do Px::gather ale to jak to w takim razie zrobic, przeciez jak dam mu dostep w innym pliku i przekleje kod to to nie ma totalnie sensu, w ogole prosze o powiedzenie czy to w ogole co jest napisane ma sens, bo ja juz sie totalnie poglubilem, chodzi mi czy obie klasy maja swoje odzielne atrybuty, pobieranie od uzytkownika przypisuje poprawnym atrybutom (ze nie ma sytuacji ze Px::gather przypisuje dla atrybutu Wx::degree, bo ja juz serio mam metlik w glowie)

Tu sa wszystkie kody:

main:

#include <iostream>
#include "polynomials.h"
using namespace std;

int main()
{
    Wx w;
    Px p;

    Polynomial *pointerWx;
    Polynomial *pointerPx;
    pointerWx=&w;
    pointerPx=&p;
    pointerWx->gather();
    pointerPx->gather();
    pointerWx->show();
    pointerPx->show();
}

polynomials.h:

#include <iostream>

using namespace std;

class Polynomial
{
public:
    virtual void gather()=0;
    virtual void show()=0;
};

class Wx :public Polynomial
{
protected:
    string userStringNum;
    int degree;
    int helper;
    float *coefficients;

public:
    virtual void gather();
    virtual void show();
    void isInteger(int &d);

    Wx(string="0", int=0, int=0);
    ~Wx();

};

class Px :public Wx
{

public:
    virtual void gather();
    virtual void show();
    Px(string="0", int=0, int=0);
    ~Px();
};

structors.h:

#include <iostream>
#include "polynomials.h"

using namespace std;

Wx::Wx(string uNS, int d, int h)
{
    userStringNum=uNS;
    degree=d;
    helper=h;
    coefficients=new float[d+1];
    cout<<"1 konstruktor zadzwonil";
    cout<<endl;
}
Wx::~Wx()
{
    delete [] coefficients;
    cout<<"1 destruktor zadzwonil";
    cout<<endl;
}

Px::Px(string uNS, int d, int h)
:Wx(uNS, d, h)
{
    coefficients=new float[d+1];
    cout<<"2 konstruktor zadzwonil";
    cout<<endl;
}
Px::~Px()
{
    delete [] coefficients;
    cout<<"2 destruktor zadzwonil";
    cout<<endl;
}

gatherWx:

#include <iostream>
#include "polynomials.h"
using namespace std;

void Wx::gather()
{
    cout<<"Input degree of polynomial W(x): ";
    isInteger(degree);
    helper=degree;

    coefficients = new float[degree+1];

    cout<<"Input coefficients and constant of polynomial W(x): ";
    cout<<endl;
    for (int i=degree; i>=0; i--)
    {
        cin>>coefficients[i];
    }
}

gatherPx:

#include <iostream>
#include "polynomials.h"
using namespace std;

void Px::gather()
{
    cout<<"Input degree of polynomial P(x): ";
    isInteger(degree);
    helper=degree;

    coefficients = new float[degree+1];

    cout<<"Input coefficients and constant of polynomial P(x): ";
    cout<<endl;
    for (int i=degree; i>=0; i--)
    {
        cin>>coefficients[i];
    }
}

isInteger:

#include <iostream>
#include "polynomials.h"
#include <ctype.h> // isdigit()
#include <sstream> // stringstream
using namespace std;

void Wx::isInteger(int &d)
{
    int isInt=0;
    int decimalCount=0;

    bool isIntBool=false;
    bool containsSpaces = false;

    do
    {
        getline(cin, userStringNum);
        for (int i=0; i<userStringNum.size(); i++)
        {
            if (isspace(userStringNum[i]))
                containsSpaces=true;
        }

        if (userStringNum[0] == '-')
        {
            isInt++;

            if (userStringNum[1]=='0')
                isInt=0;
        }

        if ((userStringNum[0]=='0' && isdigit(userStringNum[1])))
            isInt = 0;
        else
        {
            for (int i=0; i<userStringNum.size(); i++)
            {
                if (isdigit(userStringNum[i]))
                    isInt++;
                if (userStringNum[i]=='.')
                    decimalCount++;
            }
        }

        if (decimalCount==1)
            isInt=0;

        if (isInt==userStringNum.size() && containsSpaces==false)
        {
            stringstream str_stream_object(userStringNum);
            str_stream_object>>d;

            isIntBool=1;
        }

        else
        {
            cout<<endl;
            cout<<"Degree of polynomial has to be an integer greater than 0, try again: ";

            isIntBool=0;
            isInt=0;
            decimalCount=0;
            containsSpaces=false;
        }

    }
    while (isIntBool==0);
}

showWx:

#include <iostream>
#include "polynomials.h"
using namespace std;

void Wx::show()
{
    cout<<"showWx zadzwonil";
    cout<<degree;
    cout<<helper;
    cout<<endl;
}

showPx:

#include <iostream>
#include "polynomials.h"
using namespace std;

void Px::show()
{
    cout<<"showPx zadzwonil";
    cout<<endl;
    cout<<degree;
    cout<<helper;
    cout<<endl;
}

Przy wywolaniu showPx wyswietla sie 00, czyli degree=0, helper=0, wiem ze to od konstruktora, czyli isInteger nie dziala dla gatherPx, dlaczego?

Skoro kiedy mam tylko tak:

#include <iostream>
#include "polynomials.h"
using namespace std;

void Wx::gather()
{
    cout<<"Input degree of polynomial W(x): ";
    isInteger(degree);
    helper=degree;

   /* coefficients = new float[degree+1];

    cout<<"Input coefficients and constant of polynomial W(x): ";
    cout<<endl;
    for (int i=degree; i>=0; i--)
    {
        cin>>coefficients[i];
    }
*/
}

#include <iostream>
#include "polynomials.h"
using namespace std;

void Px::gather()
{
    cout<<"Input degree of polynomial P(x): ";
    isInteger(degree);
    helper=degree;

 /*   coefficients = new float[degree+1];

    cout<<"Input coefficients and constant of polynomial P(x): ";
    cout<<endl;
    for (int i=degree; i>=0; i--)
    {
        cin>>coefficients[i];
    }
    */
}

output:

1 konstruktor zadzwonil
1 konstruktor zadzwonil
2 konstruktor zadzwonil
Input degree of polynomial W(x): 4
Input degree of polynomial P(x): 7
showWx zadzwonil44
showPx zadzwonil
77
2 destruktor zadzwonil
1 destruktor zadzwonil
1 destruktor zadzwonil

jak widac tutaj isInteger dziala bo wyskakuje 44, 77, a nie 44, 00 jakby wczesniej mialo miejsce, w ogole czy te 4 zostaja? ze Wx::degree=4; oraz Wx::helper=4 nadal czy one sa przeslaniane siódemkami?

 

Nie wiem mam wrazenie, ze czym dluzej nad tym siedze tym mniej rozumiem

Podobne pytania

0 głosów
4 odpowiedzi 6,003 wizyt
pytanie zadane 30 stycznia 2016 w C i C++ przez Mateo500 Nowicjusz (150 p.)
0 głosów
2 odpowiedzi 148 wizyt
pytanie zadane 5 czerwca 2023 w C i C++ przez p4wix Obywatel (1,040 p.)
0 głosów
2 odpowiedzi 191 wizyt

92,452 zapytań

141,262 odpowiedzi

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

...