[C++] Schemat sieci logicznych - problem

0

Robimy z kolegą projekt z programowania obiektowego, którego tematem jest: Stworzyć system klas służących do reprezentacji sieci logicznych, składających się z bramek AND, OR, NAND, NOR, XOR, NOT. Napisać program, który będzie wczytywał definicję sieci oraz wymuszenia, a następnie obliczał i wyprowadzał wynik oraz wyniki pośrednie. Napotkaliśmy kilka problemów:

  1. nie wiemy jak to zrobić aby pobierało i zapisywało do pliku ten schemat sieci logicznych np A10 (czyt. na bramce A jeden jest sygnał 0) - ja próbowałem już strumieniami ale wychodzi kompletna klapa :(

  2. nie wiemy jak zapisć operator logiczny w bramkach NOR(jednoczesne zaprzeczenie) i NAND(Zdanie utworzone za pomocą spójnika dysjunkcji jest fałszywe tylko wtedy, gdy prawdziwe są oba argumenty tego spójnika; w przeciwnym wypadku jest zawsze zdaniem prawdziwym.)

  3. i tu najważniejszy problem, nie bardzo wiemy jak ma wyglądać wywołująca funkcja przelatująca po całym układzie i wypisująca na końcu wynik

jeżeli ktoś miałby chwilkę czasu to dzięki wielkie za ewentualną pomoc/sugestie :)
pozdrawiam

#include <iostream>
using namespace std;

// Klasa bazowa
class Sygnal
{
      
virtual bool wyjscie() = 0;  // funkcja czysto wirtualna wiec klasa jest abstarakcyjna	

};

class Bramka
{
int Sygnal *wejscie1, *wejscie2;
virtual void wyjscie();

};

class Jedynka
{
      
};

class Zero
{
      
};

class AND: public Sygnal
{

bool AND::wyjscie()
{
     bool wynik;
     wynik = wejscie1->wyjscie() && wejscie2->wyjscie();
     return wynik;
}
};
class OR: public Sygnal
{

bool OR::wyjscie()
{
     bool wynik;
     wynik = wejscie1->wyjscie() || wejscie2->wyjscie();
     return wynik;
}
};

class XOR: public Sygnal
{

bool XOR::wyjscie()
{
     bool wynik;
     wynik = wejscie1->wyjscie() ^ wejscie2->wyjscie();
     return wynik;
}
};

class NOT: public Sygnal
{

bool NOT::wyjscie()
{
     bool wynik;
     wynik = wejscie1->wyjscie() ! wejscie2->wyjscie();
     return wynik;
}
};

class NOR: public Sygnal
{

bool NOR::wyjscie()
{
     bool wynik;
     wynik = wejscie1->wyjscie() ! wejscie2->wyjscie();
     return wynik;
}
};

class NAND: public Sygnal
{

bool NAND::wyjscie()
{
     bool wynik;
     wynik = wejscie1->wyjscie() && wejscie2->wyjscie();
     return wynik;
}
};



// wydruk informcji z klasy bazowej
void Sygnal::printData(){
	cout << "Wyjsciowy stan ukladu: " << stan << "\n";
}

	return 0;
}


0

add: schemat sieci będzie wczytywany z pliku za pomocą strumieni

0

Jeśli to początek to całkiem nieźle. Tu masz to nieco bardziej uporządkowane:

#include <iostream>

using namespace std;

// Klasa bazowa
class Sygnal
{
public:
      virtual bool wyjscie() const = 0;
};

class OperatorBinarny : public Sygnal
{
    Sygnal *wejscie1, *wejscie2;
public:
    OperatorBinarny(Sygnal* w1,Sygnal* w2) : wejscie1(w1), wejscie2(w2)
    {}

protected:
    bool wejscieA() const
    {
    if(wejscie1)
        return wejscie1->wyjscie();
    return false;
    }

    bool wejscieB() const
    {
    if(wejscie2)
        return wejscie2->wyjscie();
    return false;
    }
};

class OperatorUnarny : public Sygnal
{
    Sygnal *sygWejsciowy;
public:
    OperatorUnarny(Sygnal* w) : sygWejsciowy(w)
    {}

    bool wejscie() const
    {
    if(sygWejsciowy)
        return sygWejsciowy->wyjscie();
    return false;
    }
};

class SygnalWejsciowy: public Sygnal
{
     bool wartosc;
public:
     SygnalWejsciowy(bool a = false) : wartosc(a)
     {}

     void ustaw() { wartosc = true; }
     void wyczysc() { wartosc = false; }

     bool wyjscie() const
     { return wartosc; }
};

const SygnalWejsciowy Jedynka(true);
const SygnalWejsciowy Zero(false);

class BramkaAnd: public OperatorBinarny
{
public:
     BramkaAnd(Sygnal* w1,Sygnal* w2) : OperatorBinarny(w1,w2)
     {}

bool wyjscie() const
     {
     return wejscieA() && wejscieA();
     }
};

class BramkaOr: public OperatorBinarny
{
public:
     BramkaOr(Sygnal* w1,Sygnal* w2) : OperatorBinarny(w1,w2)
     {}

bool wyjscie()
     {
     return wejscieA() || wejscieB();
     }
};

class BramkaXor: public OperatorBinarny
{
public:
     BramkaXor(Sygnal* w1,Sygnal* w2) : OperatorBinarny(w1,w2)
     {}

bool wyjscie()
     {
     return wejscieA() != wejscieB();
     }
};

class BramkaNot: public OperatorUnarny
{
public:
     BramkaNot(Sygnal* w) : OperatorUnarny(w)
     {}

bool wyjscie()
     {
     return !wejscie();
     }
};

Co do wczytywania danych z pliku to ty musisz najpierw ustalić format danych. Musisz bardziej sprecyzować co ma dostawać program na wejściu, co ma być wynikiem i jak ma to wyglądać na wyjściu.

0

no ja to zrobiłem troszkę inaczej niż ty :) opisałem też na czym polega mój problem z tym wczytywaniem z pliku:

  1. w linijce bool w2 = Schemat::elementy[ wejscie2]-->wyjscie();
    wyskakuje mi taki błąd: ISO C++ forbids comparison between pointer and integer.

  2. nie wiem jak zrobić tak by z pliku o treści:
    5
    0
    1
    O01
    A10
    A23

gdzie : 5-ilość elementów w układzie logicznym
0,1 pierwsze wartości
O01 znaczy że bramka OR ma na 1 wejściu 0 a na drugim 1
A10 - bramka AND ma na wejściu pierwszym 1 na drugim 0
A23 tzn że to jest końcowa bramka AND i ma 2- jest to wejście gdzie wpada to co wyszło z bramki OR a 3 to tam wpada to co wyszło z tej pierwszej bramki AND.

wczytało mi to do tego programu tak by mogło to wszystko policzyć


#include <iostream>
#include <fstream>
using namespace std;

// Klasa bazowa
class Sygnal
{
public:      
virtual bool wyjscie() = 0;  // funkcja czysto wirtualna wiec klasa jest abstarakcyjna	

};

class Schemat
{
      friend class AND;
      friend class OR;
      friend class XOR;
      friend class NOT;
      friend class NOR;
      friend class NAND;
      static Sygnal** elementy;
      int ilosc_el;
      void Wczytaj_Uklad()
  {
      ifstream plik("bramki.txt",ios::in);
      plik >> ilosc_el;
      elementy = new Sygnal*[ilosc_el];
      elementy[e]->wejscie1 = odczytana_cyferka_1; 
      elementy[e]->wejscie2 = odczytana_cyferka_2;
  }   
};

class Bramka: public Sygnal
{
      public:
int wejscie1, wejscie2;
virtual bool wyjscie();

};

class Jedynka
{
bool wyjscie()
{
     cout << "1";

     return true;
}      
};

class Zero
{
bool wyjscie()
{
     cout << "0";

     return false;
}      
};

class AND: public Bramka
{
bool wyjscie()
    {
    cout << "AND(";
    bool w1 = Schemat::elementy[wejscie1]->wyjscie();
        cout << ",";
        bool w2 = Schemat::elementy[ wejscie2]-->wyjscie();
        bool wynik = w1 && w2;
        cout << ")=" << wynik;
        return wynik;
}
};
class OR: public Bramka
{

bool wyjscie()
    {
        cout << "OR(";
        bool w1 = Schemat::elementy[wejscie1]->wyjscie();
        cout << ",";
        bool w2 = Schemat::elementy[ wejscie2]-->wyjscie();
        bool wynik = w1 || w2;
        cout << ")=" << wynik;
        return wynik;
    
    }
};

class XOR: public Bramka
{
bool wyjscie()
    {
        cout << "XOR(";
        bool w1 = Schemat::elementy[wejscie1]->wyjscie();
        cout << ",";
        bool w2 = Schemat::elementy[ wejscie2]-->wyjscie();
        bool wynik = w1 ^ w2;
        cout << ")=" << wynik;
        return wynik;
    
    }
};

class NOT: public Bramka
{

bool wyjscie()

        {
        cout << "NOT(";
        bool wynik = !Schemat::elementy[wejscie1]->wyjscie();
        cout << ")=" << wynik;
        return wynik;
    
    }
};

class NOR: public Bramka
{
bool wyjscie()

    {
        cout << "NOR(";
        bool w1 = Schemat::elementy[wejscie1]->wyjscie();
        cout << ",";
        bool w2 = Schemat::elementy[ wejscie2]-->wyjscie();
        bool wynik = !(w1 || w2);
        cout << ")=" << wynik;
        return wynik;
    
    }
};

class NAND: public Bramka
{
bool wyjscie()
    {
        cout << "NAND(";
        bool w1 = Schemat::elementy[wejscie1]->wyjscie();
        cout << ",";
        bool w2 = Schemat::elementy[ wejscie2]-->wyjscie();
        bool wynik = !(w1 && w2);
        cout << ")=" << wynik;
        return wynik;
    
    }
};






0

a nie zauważyłeś, że wpisałeś "-->" zamiast "->"?

0

no fakt ;) ale nadal nie wiem jak zrobić to wczytywanie

0

ja bym zrobił tak:

3 // liczba wejść zewnętrznych
AND 0 1 // typ bramki i od czego zależy jej wartość
OR 2 3 // jak wyżej tyle, że 3 nie oznacza już wejścia, ale sygnał wyjściowy bramki powyżej.

a wczytywanie tak (stosując moje wcześniejsze poprawki do kodu):

#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>

using namespace std;

// Klasa bazowa
class Sygnal
{
public:
      virtual bool wyjscie() const = 0;
};

class OperatorBinarny : public Sygnal
{
    Sygnal *wejscie1, *wejscie2;
public:
    OperatorBinarny(Sygnal* w1,Sygnal* w2) : wejscie1(w1), wejscie2(w2)
    {}

protected:
    bool wejscieA() const
    {
    if(wejscie1)
        return wejscie1->wyjscie();
    return false;
    }

    bool wejscieB() const
    {
    if(wejscie2)
        return wejscie2->wyjscie();
    return false;
    }
};

class OperatorUnarny : public Sygnal
{
    Sygnal *sygWejsciowy;
public:
    OperatorUnarny(Sygnal* w) : sygWejsciowy(w)
    {}

    bool wejscie() const
    {
    if(sygWejsciowy)
        return sygWejsciowy->wyjscie();
    return false;
    }
};

class SygnalWejsciowy: public Sygnal
{
     bool wartosc;
public:
     SygnalWejsciowy(bool a = false) : wartosc(a)
     {}

     void ustaw() { wartosc = true; }
     void wyczysc() { wartosc = false; }

     bool wyjscie() const
     { return wartosc; }
};

const SygnalWejsciowy Jedynka(true);
const SygnalWejsciowy Zero(false);

class BramkaAnd: public OperatorBinarny
{
public:
     BramkaAnd(Sygnal* w1,Sygnal* w2) : OperatorBinarny(w1,w2)
     {}

bool wyjscie() const
     {
     return wejscieA() && wejscieA();
     }
};

class BramkaOr: public OperatorBinarny
{
public:
     BramkaOr(Sygnal* w1,Sygnal* w2) : OperatorBinarny(w1,w2)
     {}

bool wyjscie() const
     {
     return wejscieA() || wejscieB();
     }
};

class BramkaXor: public OperatorBinarny
{
public:
     BramkaXor(Sygnal* w1,Sygnal* w2) : OperatorBinarny(w1,w2)
     {}

bool wyjscie()
     {
     return wejscieA() != wejscieB();
     }
};

class BramkaNot: public OperatorUnarny
{
public:
     BramkaNot(Sygnal* w) : OperatorUnarny(w)
     {}

bool wyjscie() const
     {
     return !wejscie();
     }
};

class Uklad // i szara siec ;)
{
    typedef std::vector<Sygnal *> ZbiorSygnalow;
    ZbiorSygnalow sygnaly;
    std::vector<SygnalWejsciowy *> wejscia;

public:

    void wyczysc()
    {
        wejscia.clear();

        for(ZbiorSygnalow::iterator i = sygnaly.begin();
                i!=sygnaly.end(); ++i) {
            delete *i;
        }

        sygnaly.clear();
    }

    istream& Wczytaj(istream& strumien)
    {
        wyczysc();
        string linia;

        getline(strumien,linia); //wczytaj pierwszą linię
        {
            int liczbaWejsc;
            istringstream pierwszaLinia(linia);
            pierwszaLinia >> liczbaWejsc; // na jej podstawie stwórz wejścia
            while(liczbaWejsc--!=0) {
                wejscia.push_back(new SygnalWejsciowy);
            }
            sygnaly.insert(sygnaly.begin(),wejscia.begin(),wejscia.end());
        }

        while(getline(strumien,linia)) { //czytaj wszystkie pozostałe linie
            istringstream czytajLinie(linia);
            string typBramki;
            unsigned int w1,w2;

            czytajLinie >> typBramki; // wczytaj pierwsze słowo identyfikujące typ bramki
            czytajLinie >> w1 >> w2; // wczytaj z czym połączyć wejścia bramki
            if(w1>=sygnaly.size()) { // czy pierwsze wejście ma sens
                cerr << "Zle zdefiniowana bramka" << endl;
                break;
            }

            if(typBramki=="AND") {
                if(w2>=sygnaly.size()) { // czy drugie wejście ma sens
                    cerr << "Zle zdefiniowana bramka" << endl;
                    break;
                }
                sygnaly.push_back(new BramkaAnd(sygnaly[w1],sygnaly[w2]));
            } else if (typBramki=="OR") {
                if(w2>=sygnaly.size()) { // czy drugie wejście ma sens
                    cerr << "Zle zdefiniowana bramka" << endl;
                    break;
                }
                sygnaly.push_back(new BramkaOr(sygnaly[w1],sygnaly[w2]));
            } else if (typBramki=="NOT") {
                 sygnaly.push_back(new BramkaNot(sygnaly[w1]));
            } else if (typBramki=="END") {
                 break; // koniec wczytywania bramek
            } else {
                 cerr << "nieznana nazwa bramki"<<endl;
                 break;
            }
        }
        return strumien;
    }
};
0

dzieki wielkie :)

a to poniżej:

3 // liczba wejść zewnętrznych
AND 0 1 // typ bramki i od czego zależy jej wartość
OR 2 3 // jak wyżej tyle, że 3 nie oznacza już wejścia, ale sygnał wyjściowy bramki powyżej.

ma się znaleźć w pliku bramka.txt i trzeba dopisać komendę :

ifstream plik("bramki.txt",ios::in);

i ogólnie program wyrzuca taki błąd:

ld: fatal: Symbol referencing errors. No output written to uklad
collect2: ld returned 1 exit status
0

Ha, zrobiłem mały byk (kod się kraszuje) w miejscu copy. Na górze masz poprawione.
A wczytywać powinieneś tak:

ifstream plik("DaneUkładu.txt");
JakisUklad.Wczytaj(plik);

// albo tak, z konsoli
JakisUklad.Wczytaj(cin);

Przykład danych wejściowych na układ dający bramkę XOR:

2
OR 0 1
NOT 2
AND 0 1
OR 3 4
NOT 5
0

mam jeszcze pytanko zawarte w kodzie:


int main()
{
    int q;
cout<<"Program Bramki Logiczne\n\n";

                   cout<<"Co chcesz zrobic?\n\n";
                   cout<<"Obliczanie ukladu wczytanego z pliku - 1\n";
                   cout<<"wyjscie - 0\n";
                   
                   
               for(;;)
                   {
                   cin>>q;
                   if (q==0)
                   {
                           break;
                   }  
                   switch(q)
                           {
                            case 1: //obliczanie
                            { 
                                 Uklad::< - do jakiej funkcji mam się tu odwołać ?
                                                }
                             break;
                     default:
                                           {

                                           cout<<"Nie podales zadnego odpowiednika dzialania.\n";
                                           }  

0

rusz mózgownicą choć trochę. Za bardzo cię rozleniwiłem.

0

spoko spoko już mam ją trochę zrytą bo od kilku dni to ćwicze :(

jednakże błąd mimo tej poprawki przy copy nadal jest taki sam, stąd nie mam nawet jak przećwiczyć dodania tam funkcji

0

Sprawdź czy naprawdę masz tą poprawkę, miałem jakiś kłopot z przeglądarką i 2 razy nie załapało mi zmian (u mnie teraz działa).

0
#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>

using namespace std;

// Klasa bazowa
class Sygnal
{
public:
      virtual bool wyjscie() const = 0;
};

class OperatorBinarny : public Sygnal
{
    Sygnal *wejscie1, *wejscie2;
public:
    OperatorBinarny(Sygnal* w1,Sygnal* w2) : wejscie1(w1), wejscie2(w2)
    {}

protected:
    bool wejscieA() const
    {
    if(wejscie1)
        return wejscie1->wyjscie();
    return false;
    }

    bool wejscieB() const
    {
    if(wejscie2)
        return wejscie2->wyjscie();
    return false;
    }
};

class OperatorUnarny : public Sygnal
{
    Sygnal *sygWejsciowy;
public:
    OperatorUnarny(Sygnal* w) : sygWejsciowy(w)
    {}

    bool wejscie() const
    {
    if(sygWejsciowy)
        return sygWejsciowy->wyjscie();
    return false;
    }
};

class SygnalWejsciowy: public Sygnal
{
     bool wartosc;
public:
     SygnalWejsciowy(bool a = false) : wartosc(a)
     {}

     void ustaw() { wartosc = true; }
     void wyczysc() { wartosc = false; }

     bool wyjscie() const
     { return wartosc; }
};

const SygnalWejsciowy Jedynka(true);
const SygnalWejsciowy Zero(false);

class BramkaAnd: public OperatorBinarny
{
public:
     BramkaAnd(Sygnal* w1,Sygnal* w2) : OperatorBinarny(w1,w2)
     {}

bool wyjscie() const
     {
     return wejscieA() && wejscieA();
     }
};

class BramkaOr: public OperatorBinarny
{
public:
     BramkaOr(Sygnal* w1,Sygnal* w2) : OperatorBinarny(w1,w2)
     {}

bool wyjscie() const
     {
     return wejscieA() || wejscieB();
     }
};

class BramkaXor: public OperatorBinarny
{
public:
     BramkaXor(Sygnal* w1,Sygnal* w2) : OperatorBinarny(w1,w2)
     {}

bool wyjscie()
     {
     return wejscieA() != wejscieB();
     }
};

class BramkaNot: public OperatorUnarny
{
public:
     BramkaNot(Sygnal* w) : OperatorUnarny(w)
     {}

bool wyjscie() const
     {
     return !wejscie();
     }
};

class Uklad // i szara siec ;)
{
    typedef std::vector<Sygnal *> ZbiorSygnalow;
    ZbiorSygnalow sygnaly;
    std::vector<SygnalWejsciowy *> wejscia;

public:

    void wyczysc()
    {
        wejscia.clear();

        for(ZbiorSygnalow::iterator i = sygnaly.begin();
                i!=sygnaly.end(); ++i) {
            delete *i;
        }

        sygnaly.clear();
    }

    istream& Wczytaj(istream& strumien)
    {
        wyczysc();
        string linia;

        getline(strumien,linia); //wczytaj pierwszą linię
        {
            int liczbaWejsc;
            istringstream pierwszaLinia(linia);
            pierwszaLinia >> liczbaWejsc; // na jej podstawie stwórz wejścia
            while(liczbaWejsc--!=0) {
                wejscia.push_back(new SygnalWejsciowy);
            }
            sygnaly.insert(sygnaly.begin(),wejscia.begin(),wejscia.end());
        }

        while(getline(strumien,linia)) { //czytaj wszystkie pozostałe linie
            istringstream czytajLinie(linia);
            string typBramki;
            unsigned int w1,w2;

            czytajLinie >> typBramki; // wczytaj pierwsze słowo identyfikujące typ bramki
            czytajLinie >> w1 >> w2; // wczytaj z czym połączyć wejścia bramki
            if(w1>=sygnaly.size()) { // czy pierwsze wejście ma sens
                cerr << "Zle zdefiniowana bramka" << endl;
                break;
            }

            if(typBramki=="AND") {
                if(w2>=sygnaly.size()) { // czy drugie wejście ma sens
                    cerr << "Zle zdefiniowana bramka" << endl;
                    break;
                }
                sygnaly.push_back(new BramkaAnd(sygnaly[w1],sygnaly[w2]));
            } else if (typBramki=="OR") {
                if(w2>=sygnaly.size()) { // czy drugie wejście ma sens
                    cerr << "Zle zdefiniowana bramka" << endl;
                    break;
                }
                sygnaly.push_back(new BramkaOr(sygnaly[w1],sygnaly[w2]));
            } else if (typBramki=="NOT") {
                 sygnaly.push_back(new BramkaNot(sygnaly[w1]));
            } else if (typBramki=="END") {
                 break; // koniec wczytywania bramek
            } else {
                 cerr << "nieznana nazwa bramki"<<endl;
                 break;
            }
        }
        return strumien;
    }
};

taki kod skopiowałem i niestety nie działa nadal jest ten sam błąd (pod devem : [Linker error] undefined reference to `WinMain@16' ld returned 1 exit status ) i pod g++ na unixie tylko ld returned 1 exit status

0

Eeee... , że tak głupie spytam, ty chyba nie założyłeś, że dałem ci kod co do ostatniej linijki.

  1. musisz utworzyć projekt konsolowy.
  2. musisz napisać swoją metodę main (ja sobie nabazgrałem coś na dwie linijki i to wystarczyło, żeby to uruchomić).
    Nie dałem ci też kodu, obliczającego stan wszystkich bramek. Pokazałem ci jak powinna mniej więcej wyglądać struktura hierarchii klas i jak wczytać dane o układzie resztę spróbuj sam bo inaczej się niczego nie nauczysz.
0

no na to uczenie to nie bardzo, bo zacząłem programowanie w tym semestrze a tu już takie projekty.

mam to oddać jutro na ocenę, męczę się już z tym od kilku dni

napisałem maina podstawowego co widzisz wyżej jednakże to nie starcza by uruchomić to na unixie

a wczytywanie pliku jak zrobiłem to też wywalało błędy

jeżeli uważasz, że nie ma co pomagać debilowi z programowania to zrozumiem, zaniose nie kompletny plik może połowę punktów dostanę, bo nie mogę zajmować się tylko tym bo mam jutro jeszcze kilka laborek m.in teorię obwodów do których też się muszę nauczyć

//quetz: uu, przykre.. tyle do nauki? ajaj.. a ze tak wrednie spytam: od kiedy wiedziales ze to trzeba zrobic.sie nauczyc? za samo takie uzalanie sie i zebranine na-dzien-przed temat polecialby do kosza, ale juz Ci ludzie poodpisywali..

1 użytkowników online, w tym zalogowanych: 0, gości: 1