Commit 16c28012 by Szeberényi Imre

I

parents
# Pelda Makefile a Cpp Ellenallas megoldasanak forditasara
# Solaris (ural2) es Linux ala.
objs1 = resistor.o resistor_test.o # forditando obj. fajlok
heads1 = resistor.h # # headerek, amitol minden fugg
prog1 = resistor_test # # a program neve
objs2 = resistor.o resistor_test2.o
heads2 = resistor.h
prog2 = resistor_test2
objs3 = resistor.o potmeter.o console.o potmeter_teszt.o
heads3 = resistor.h potmeter.h console.h
prog3 = potmeter_teszt
targets = $(prog1) $(prog2) $(prog3)
CXX = g++ # # a C++ fordito neve
#CXX = clang++ # # clang-ot (llvm) is erdemes kiprobalni
CXXFLAGS = -pedantic -Wall # # C++ kapcsolok: legyen bobeszedu,
CXXFLAGS += -g # # ... es legyen debug info is
CXXFLAGS += -fno-elide-constructors# ne optimalizálja másoló konstruktorok hívását
# alapertelmezett cel: erdeklodik, hogy melyik legyen
.PHONY: all
all:
@echo "Melyiket allitsuk elo?"
@for i in $(targets) ; do echo " > make $$i" ; done
$(prog1): $(objs1)
$(CXX) $(objs1) -o $@
$(objs1): $(heads1)
$(prog2): $(objs2)
$(CXX) $(objs2) -o $@
$(objs2): $(heads2)
$(prog3): $(objs3)
$(CXX) $(objs3) -o $@
$(objs3): $(heads3)
# takaritas igeny szerint
.PHONY: clean
clean:
rm -f $(objs1) $(prog1) $(objs2) $(prog2) $(objs3) $(prog3)
/**
* \file: console.cpp
* Console input/output kezelése
* Linux/UNIX alatt csak ANSI terminálbeállításokkal megy.
* (ncurses/pdcurses használatával hordozható lehetne! Help velcome!)
*
*/
#include "console.h"
#include <iostream>
#include <iomanip>
#if _WINX
#include <conio.h>
#include <windows.h>
#elif _UNIX
#include <termios.h> //termios, TCSANOW, ECHO, ICANON
#include <unistd.h> //STDIN_FILENO
#endif
#include <cstdio>
/// Noname névtér.
/// Csak ebből a fájlból érhető el
namespace {
#if _WINX
void clrscr() {
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(hstdout, &csbi)) {
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
DWORD dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hstdout, ' ', dwConSize, coordScreen, &cCharsWritten);
FillConsoleOutputAttribute(hstdout, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hstdout, coordScreen);
}
}
void gotoxy(int x, int y) {
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
COORD dwCursorPosition;
dwCursorPosition.X = (SHORT)x;
dwCursorPosition.Y = (SHORT)y;
SetConsoleCursorPosition(hstdout, dwCursorPosition);
}
#elif _UNIX
/// Kihasználjuk, hogy ANSI terminál
void clrscr() {
std::cout << "\x1b[2J";
}
/// Kihasználjuk, hogy ANSI terminál
void gotoxy(int x, int y) {
std::cout << "\x1b[" << y << ';' << x << 'H';
}
/// skipws kikapcsolása fontos!
int _getch() {
char c;
std::cin >> std::noskipws >> c;
return c;
}
/// Ide menti el a konzol beállítását, hogy vissza tudja állítani kilépésnél.
/// Logikusabb helyen lenne az osztályban, de így a console.h tisztább maradhat.
struct termios term_save;
#endif
} // noname namespace
/// Segédtípus a kódváltáshoz
struct Console::keyCodes {
int code;
int key;
};
/// Segédfüggvény a kódváltáshoz.
/// @param code - bejövő kód
/// @param kt - kod-újkód párok tömbje
/// @return ujkód, ha sikerült a váltás egyébként 0
inline int Console::trCode(int code, keyCodes* kt) {
for (int i = 0; kt[i].code != 0; i++)
if (kt[i].code == code)
return kt[i].key;
return 0;
}
/// UNIX/Linux alatt át ki kell kapcsolni az echo-t és a kanonikus módot
Console::Console() {
#if _UNIX
struct termios newt;
tcgetattr(STDIN_FILENO, &::term_save);
newt = term_save;
newt.c_lflag &= ~(ICANON|ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
#endif
}
/// Elmentett működési módok visszaállítása
Console::~Console() {
#if _UNIX
tcsetattr(STDIN_FILENO, TCSANOW, &::term_save);
#endif
}
/// Egy karakter olvasása echo nélkül
/// Ncurses-szerű inputot ad.
/// @return olvasott karakter kódja a speciális billentyűk 256 fölé kerülnek
int Console::getch() {
/// segédmakró
#define C(c, k) {c,k}
#if _WINX
static keyCodes arrows[] = { C(72,KEY_UP), C(80,KEY_DOWN), C(77,KEY_RIGHT), C(75,KEY_LEFT), C(0,0) };
int ch = ::_getch();
if (ch == 0xE0) { /// windows ezt a kódot adja a nyílbillentyűk előtt
ch = ::_getch(); /// utána jön a billentyű kódja
return trCode(ch, arrows);
}
#elif _UNIX
static keyCodes arrows[] = { C('A',KEY_UP), C('B',KEY_DOWN), C('C',KEY_RIGHT), C('D',KEY_LEFT), C(0,0) };
int ch = ::_getch();
if (ch == 0x1b) { /// ANSI módban ezt adja be a terminál a nyilak előtt
ch = ::_getch(); /// utána egy [
if ( ch != '[') return 0; /// nem tudjuk mi van
ch = ::_getch(); /// utána jön a billentyű kódja
return trCode(ch, arrows);
}
#endif
#undef C
return ch;
}
/// Képernyő törlés
void Console::clrscr() { ::clrscr(); }
/// Pozicionálás a képernyőn
/// (1,1) a kezdő pozíció a bal felső sarok
/// @param x - vízszintes pozíció (1..80)
/// @param y - függőleges pozíció (1..24?)
void Console::gotoxy(int x, int y) { ::gotoxy(x, y); }
/// Valós érték nagyságának megjelenítése egy vízszintes vonallal
/// @param value - érték
/// @param max - érték maximuma
/// @param width - megjelenítés szélessége
/// @param txt - vonal előtt kiírandó szöveg. Tartalmazhat printf formátumstringet a value-ra
/// @param y - vonal függőleges kezdő pozíciója
/// @param x - vonal vízszintes kezdő pozíciója
void Console::hMeter(double value, double max, int width, const char *txt, int y, int x) {
if (x > 0 || y > 0) gotoxy(x, y);
if (txt != NULL) {
/// milyan hosszú lesz?
int len = snprintf(NULL, 0, txt, value)+1;
/// annyit foglalunk és beleírjuk
char *s = new char[len];
snprintf(s, len, txt, value);
std::cout << s;
/// kiírtuk, nem kell már a buffer
delete[] s;
/// ennyivel csökken a szélesség
width -= len;
}
width -= 2; /// két szöglet miatt
double scale = value / max;
/// kirajzoljuk a vonalat
std::cout << "[";
int pos = int(width * scale);
for (int i = 0; i < width; ++i) {
if (i < pos) std::cout << "=";
else if (i == pos) std::cout << ">";
else std::cout << " ";
}
std::cout << "]\r";
std::cout.flush();
}
/**
* \file: console.h
* Console input/output kezelése
*
*/
#ifndef CONSOLE_H
#define CONSOLE_H
// VS: alatt nem megy #define _UNIX defined(__linux__) || defined(__sun)
#if defined(__linux__) || defined(__sun)
#define _UNIX
#endif
#if defined(_WIN32) || defined(_WIN64)
#define _WINX
#endif
/**
* Console ablak kezelését támogató osztály.
* Singleton minta szerint valósítjuk meg: csak egyetlen példányban létezik.
* Egy statikus objektummal a singleton minta nem teljesíthető, mert
* nem lehet kontrollálni az objektum élettartamát. (Később tanulnak róla)
* A bemutatott megoldásban is csak a keletkezést lehet befolyásolni,
* a megszűnést nem (de ez már megfelel a mintának).
*
*/
class Console {
public:
static const int KEY_DOWN = 0x102; /* Down arrow key */
static const int KEY_UP = 0x103; /* Up arrow key */
static const int KEY_LEFT = 0x104; /* Left arrow key */
static const int KEY_RIGHT = 0x105; /* Right arrow key */
static const int KEY_HOME = 0x106; /* home key */
private:
struct keyCodes;
int trCode(int code, keyCodes* kt);
Console(); ///< csak belülről érhető el
Console(const Console&); ///< nem engedélyezzük
Console& operator=(const Console&); ///< ezt sem
public:
/// példányosítás
static Console& con() {
static Console theConsole; /// a függvény első futásakor fut el a konstruktora
return theConsole;
}
/// Destruktor
~Console();
/// Egy karakter olvasása echo nélkül
/// Ncurses-szerű inputot ad.
/// @return olvasott karakter kódja a speciális billentyűk 256 fölé kerülnek
int getch();
/// Képernyő törlés
void clrscr();
/// Pozicionálás a képernyőn
/// (1,1) a kezdő pozíció a bal felső sarok
/// @param x - vízszintes pozíció (1..80)
/// @param y - függőleges pozíció (1..24?)
void gotoxy(int x, int y);
/// Valós érték nagyságának megjelenítése egy vízszintes vonallal
/// @param value - érték
/// @param max - érték maximuma
/// @param width - megjelenítés szélessége
/// @param txt - vonal előtt kiírandó szöveg. Tartalmazhat printf formátumstringet a value-ra
/// @param y - vonal függőleges kezdő pozíciója
/// @param x - vonal vízszintes kezdő pozíciója
void hMeter(double value, double max, int width = 70,
const char* txt = 0, int y = 0, int x = 0);
};
#endif // CONSOLE_H
#ifndef ELKESZULT_H
#define ELKESZULT_H
/**
* \file elkeszult.h
*
*/
/// Készültségi fok beállítása
#define ELKESZULT 0
/**
*ELKESZULT értéke - feladatok:
* 1. A paraméter nélküli és az egyparaméteres konstruktorokban van kiírás (ctor0, ctor1).
* 2. Van explicit deklarált másoló konstruktor, ami kiírja, hogy "copy".
* 3. Van explicit deklarált destruktor, ami kiírja, hogy "dtor".
* 4. Van explicit deklarált értékadó operátor, ami kiírja, hogy "assign".
* 5. Van getI() függvény.
* 6. Van getU() függvény.
*
* Szorgalmi feladatok:
* 7. Van egyenlőségvizsgáló operátor, ami figyelmen kívül hagyja a számábrázolási pontatlanságot
* 8. Van inserter.
*
*/
#endif // ELKESZULT_H
#ifndef GTEST_LITE_H
#define GTEST_LITE_H
/**
* \file gtest_lite.h (v2)
*
* Google gtest keretrendszerhez hasonló rendszer.
* Sz.I. 2015., 2016., 2017. (_Has_X)
* Sz.I. 2018 (template), ENDM, ENDMsg
* Sz.I. 2019 singleton
*
* A tesztelés legalapvetőbb funkcióit támogató függvények és makrók.
* Nem szálbiztos megvalósítás.
*
*
* Szabadon felhasználható, bővíthető.
*
* Használati példa:
* Teszteljük az f(x)=2*x függvényt:
* int f(int x) { return 2*x; }
*
* int main() {
* TEST(TeszEsetNeve, TesztNeve)
* EXPECT_EQ(0, f(0));
* EXPECT_EQ(4, f(2)) << "A függvény hibás eredményt adott" << std::endl;
* ...
* END
* ...
*
* A működés részleteinek megértése szorgalmi feladat.
*/
#include <iostream>
#include <cassert>
#include <cmath>
#include <cstring>
#include <limits>
#include <string>
#include <fstream>
#ifdef MEMTRACE
#include "memtrace.h"
#endif
// Két makró az egyes tesztek elé és mögé:
// A két makró a kapcsos zárójelekkel egy új blokkot hoz létre, amiben
// a nevek lokálisak, így elkerülhető a névütközés.
/// Teszt kezdete. A makró paraméterezése hasonlít a gtest
/// paraméterezéséhez. Így az itt elkészített testek könnyen átemelhetők
/// a gtest keretrendszerbe.
/// @param C - teszteset neve (csak a gtest kompatibilitás miatt van külön neve az eseteknek)
/// @param N - teszt neve
#define TEST(C, N) { gtest_lite::test.begin(#C"."#N);
/// Teszteset vége.
#define END gtest_lite::test.end(); }
/// Teszteset vége allokált blokkok számának összehasonlításával
/// Ez az ellenőrzés nem bomba biztos.
#define ENDM gtest_lite::test.end(true); }
/// Teszteset vége allokált blokkok számának összehasonlításával
/// Ez az ellenőrzés nem bomba biztos.
/// Ha hiba van kiírja az üzenetet.
#define ENDMsg(t) gtest_lite::test.end(true) << t << std::endl; }
// Eredmények vizsgálatát segítő makrók.
// A paraméterek és a funkciók a gtest keretrendszerrel megegyeznek.
/// Sikeres teszt makrója
#define SUCCEED() gtest_lite::test.expect(true, __FILE__, __LINE__, "SUCCEED()", true)
/// Sikertelen teszt makrója
#define FAIL() gtest_lite::test.expect(false, __FILE__, __LINE__, "FAIL()", true)
/// Azonosságot elváró makró
#define EXPECT_EQ(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::eq, __FILE__, __LINE__, "EXPECT_EQ(" #expected ", " #actual ")" )
/// Eltérést elváró makró
#define EXPECT_NE(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::ne, __FILE__, __LINE__, "EXPECT_NE(" #expected ", " #actual ")", "etalon" )
/// Kisebb, vagy egyenlő relációt elváró makró
#define EXPECT_LE(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::le, __FILE__, __LINE__, "EXPECT_LE(" #expected ", " #actual ")", "etalon" )
/// Kisebb, mint relációt elváró makró
#define EXPECT_LT(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::lt, __FILE__, __LINE__, "EXPECT_LT(" #expected ", " #actual ")", "etalon" )
/// Nagyobb, vagy egyenlő relációt elváró makró
#define EXPECT_GE(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::ge, __FILE__, __LINE__, "EXPECT_GE(" #expected ", " #actual ")", "etalon" )
/// Nagyobb, mint relációt elváró makró
#define EXPECT_GT(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::gt, __FILE__, __LINE__, "EXPECT_GT(" #expected ", " #actual ")", "etalon" )
/// Igaz értéket elváró makró
#define EXPECT_TRUE(actual) gtest_lite::EXPECT_(true, actual, gtest_lite::eq, __FILE__, __LINE__, "EXPECT_TRUE(" #actual ")" )
/// Hamis értéket elváró makró
#define EXPECT_FALSE(actual) gtest_lite::EXPECT_(false, actual, gtest_lite::eq, __FILE__, __LINE__, "EXPECT_FALSE(" #actual ")" )
/// Valós számok azonosságát elváró makró
#define EXPECT_FLOAT_EQ(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::almostEQ, __FILE__, __LINE__, "EXPECT_FLOAT_EQ(" #expected ", " #actual ")" )
/// Valós számok azonosságát elváró makró
#define EXPECT_DOUBLE_EQ(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::almostEQ, __FILE__, __LINE__, "EXPECT_DOUBLE_EQ(" #expected ", " #actual ")" )
/// C stringek (const char *) azonosságát tesztelő makró
#define EXPECT_STREQ(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::eqstr, __FILE__, __LINE__, "EXPECT_STREQ(" #expected ", " #actual ")" )
/// C stringek (const char *) eltéréset tesztelő makró
#define EXPECT_STRNE(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::nestr, __FILE__, __LINE__, "EXPECT_STRNE(" #expected ", " #actual ")", "etalon" )
/// Kivételt várunk
#define EXPECT_THROW(statement, exception_type) try { gtest_lite::test.tmp = false; statement; } \
catch (exception_type) { gtest_lite::test.tmp = true; } \
catch (...) { } \
EXPECTTHROW(statement, "kivetelt dob.", "nem dobott '"#exception_type"' kivetelt.")
/// Kivételt várunk
#define EXPECT_ANY_THROW(statement) try { gtest_lite::test.tmp = false; statement; } \
catch (...) { gtest_lite::test.tmp = true; } \
EXPECTTHROW(statement, "kivetelt dob.", "nem dobott kivetelt.")
/// Nem várunk kivételt
#define EXPECT_NO_THROW(statement) try { gtest_lite::test.tmp = true; statement; } \
catch (...) { gtest_lite::test.tmp = false; }\
EXPECTTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
/// Kivételt várunk és továbbdobjuk -- ilyen nincs a gtest-ben
#define EXPECT_THROW_THROW(statement, exception_type) try { gtest_lite::test.tmp = false; statement; } \
catch (exception_type) { gtest_lite::test.tmp = true; throw; } \
EXPECTTHROW(statement, "kivetelt dob.", "nem dobott '"#exception_type"' kivetelt.")
/// Segédmakró egy adattag, vagy tagfüggvény létezésének tesztelésére futási időben
/// Ötlet:
/// https://cpptalk.wordpress.com/2009/09/12/substitution-failure-is-not-an-error-2
/// Használat:
/// CREATE_Has_(size)
/// ... if (Has_size<std::string>::member)...
#define CREATE_Has_(X) \
template<typename T> struct _Has_##X { \
struct Fallback { int X; }; \
struct Derived : T, Fallback {}; \
template<typename C, C> struct ChT; \
template<typename D> static char (&f(ChT<int Fallback::*, &D::X>*))[1]; \
template<typename D> static char (&f(...))[2]; \
static bool const member = sizeof(f<Derived>(0)) == 2; \
};
/// Segédsablon típuskonverzió futás közbeni ellenőrzésere
template <typename F, typename T>
struct _Is_Types {
template<typename D> static char (&f(D))[1];
template<typename D> static char (&f(...))[2];
static bool const convertable = sizeof(f<T>(F())) == 1;
};
/// -----------------------------------
/// Belső megvalósításhoz tartozó makrók, és osztályok.
/// Nem célszerű közvetlenül használni, vagy módosítani
/// -----------------------------------
/// EXPECTTHROW: kivételkezelés
#define EXPECTTHROW(statement, exp, act) gtest_lite::test.expect(gtest_lite::test.tmp, __FILE__, __LINE__, #statement) \
<< "** Az utasitas " << (act) \
<< "\n** Azt vartuk, hogy " << (exp) << std::endl
#ifdef CPORTA
#define GTINIT(is) \
int magic; \
is >> magic;
#else
#define GTINIT(IS)
#endif // CPORTA
#ifdef CPORTA
#define GTEND(os) \
os << magic << (gtest_lite::test.fail() ? " NO" : " OK?") << std::endl;
#else
#define GTEND(os)
#endif // CPORTA
/// gtest_lite: a keretrendszer függvényinek és objektumainak névtere
namespace gtest_lite {
/// Tesztek állapotát tároló osztály.
/// Egyetlen egy statikus példány keletkezik, aminek a
/// destruktora a futás végén hívódik meg.
struct Test {
int sum; ///< tesztek számlálója
int failed; ///< hibás tesztek
int ablocks; ///< allokált blokkok száma
bool status; ///< éppen futó teszt státusza
bool tmp; ///< temp a kivételkezeléshez;
std::string name; ///< éppen futó teszt neve
std::fstream null; ///< nyelő, ha nem kell kiírni semmit
static Test& getInstance() {
static Test instance; ///< egyedüli (singleton) példány
return instance;
}
private: /// singleton minta miatt
Test() :sum(0), failed(0), status(false), null("/dev/null") {}
Test(const Test&);
void operator=(const Test&);
public:
/// Teszt kezdete
void begin(const char *n) {
name = n; status = true;
#ifdef MEMTRACE
ablocks = memtrace::allocated_blocks();
#endif
#ifndef CPORTA
std::cerr << "\n---> " << name << std::endl;
#endif // CPORTA
++sum;
}
/// Teszt vége
std::ostream& end(bool memchk = false) {
#ifdef MEMTRACE
if (memchk && ablocks != memtrace::allocated_blocks()) {
status = false;
return std::cerr << "** Lehet, hogy nem szabaditott fel minden memoriat! **" << std::endl;
}
#endif
#ifdef CPORTA
if (!status)
#endif // CPORTA
std::cerr << (status ? " SIKERES" : "** HIBAS ****") << "\t" << name << " <---" << std::endl;
if (!status)
return std::cerr;
else
return null;
}
bool fail() { return failed; }
/// Eredményt adminisztráló tagfüggvény True a jó eset.
std::ostream& expect(bool st, const char *file, int line, const char *expr, bool pr = false) {
if (!st) {
++failed;
status = false;
}
if (!st || pr) {
std::string str(file);
size_t i = str.rfind("\\");
if (i == std::string::npos) i = str.rfind("/");
if (i == std::string::npos) i = 0; else i++;
return std::cerr << "\n**** " << &file[i] << "(" << line << "): " << expr << " ****" << std::endl;
}
return null;
}
/// Destruktor
~Test() {
#ifdef CPORTA
if (failed)
#endif // CPORTA
std::cerr << "\n==== TESZT VEGE ==== HIBAS/OSSZES: " << failed << "/" << sum << std::endl;
}
};
/// A statikus referencia minden fordítási egységben keletkezik, de
/// mindegyik egyetlen példányra fog hivatkozni a singleton minta miatt
static Test& test = Test::getInstance();
/// általános sablon a várt értékhez.
template <typename T>
std::ostream& EXPECT_(T exp, T act, bool (*pred)(T, T), const char *file, int line,
const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") {
return test.expect(pred(exp, act), file, line, expr)
<< "** " << lhs << ": " << std::boolalpha << exp
<< "\n** " << rhs << ": " << std::boolalpha << act << std::endl;
}
/// pointerre specializált sablon a várt értékhez.
template <typename T>
std::ostream& EXPECT_(T* exp, T* act, bool (*pred)(T*, T*), const char *file, int line,
const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") {
return test.expect(pred(exp, act), file, line, expr)
<< "** " << lhs << ": " << (void*) exp
<< "\n** " << rhs << ": " << (void*) act << std::endl;
}
/// stringek összehasonlításához.
/// azért nem spec. mert a sima EQ-ra másként kell működnie.
inline
std::ostream& EXPECTSTR(const char *exp, const char *act, bool (*pred)(const char*, const char*), const char *file, int line,
const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") {
return test.expect(pred(exp, act), file, line, expr)
<< "** " << lhs << ": " << (exp == NULL ? "NULL pointer" : std::string("\"") + exp + std::string("\""))
<< "\n** " << rhs << ": " << (act == NULL ? "NULL pointer" : std::string("\"") + act + std::string("\"")) << std::endl;
}
/// segéd sablonok a relációkhoz.
/// azért nem STL (algorithm), mert csak a függvény lehet, hogy menjen a deduckció
template <typename T>
bool eq(T a, T b) { return a == b; }
inline
bool eqstr(const char *a, const char *b) {
if (a != NULL && b != NULL)
return strcmp(a, b) == 0;
return false;
}
template <typename T>
bool ne(T a, T b) { return a != b; }
inline
bool nestr(const char *a, const char *b) {
if (a != NULL && b != NULL)
return strcmp(a, b) != 0;
return false;
}
template <typename T>
bool le(T a, T b) { return a <= b; }
template <typename T>
bool lt(T a, T b) { return a < b; }
template <typename T>
bool ge(T a, T b) { return a >= b; }
template <typename T>
bool gt(T a, T b) { return a > b; }
/// Segédsablon valós számok összehasonlításához
/// Nem bombabiztos, de nekünk most jó lesz
/// Elméleti hátér:
/// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
template <typename T>
bool almostEQ(T a, T b) {
// eps: ha a relatív, vagy abszolút hiba ettől kisebb, akkor elfogadjuk
T eps = 10 * std::numeric_limits<T>::epsilon(); // 10-szer a legkisebb érték
if (a == b) return true;
if (fabs(a - b) < eps)
return true;
double aa = fabs(a);
double ba = fabs(b);
if (aa < ba) {
aa = ba;
ba = fabs(a);
}
return (aa - ba) < aa * eps;
}
} // namespace gtest_lite
#endif // GTEST_LITE_H
#ifndef POTMETER_H
#define POTMETER_H
#include "resistor.h"
/**
* \file potmeter.h
*
* Vegyünk egy potmétert melynek az ellenállása legyen R (a két végkivezetés között).
* A kezelőszerv forgatásával az egyik végpont és a középső pont között az
* ellenállás R 1%-a és 99%-a között változtatható.
*
* Modellezzük a potméter két végpontjának összekötésével létrejövő áramköri
* elemet: (SimPoti)!
*
* Az elemet úgy használjuk, hogy a középkivezetést és az összekötött végpontokat
* kötjük be az áramkörbe.
*
* A végpontok összekötésével létrejövő elem (SimPoti) működése két párhuzamosan
* kötött változtatható ellenállással (r1, r2) modellezhető, ahol r1 + r2 = R
* Jelentse POS a kezelőszerv állását (1-99), ekkor:
* r1 = R*POS/100, r2 = R*(100-POS)/100
*
*/
/**
* FELADAT:
* Valósítsa meg a potmeter.cpp állományban a SimPoti tagfüggvényeit!
* A megvalósításhoz használja fel a Resistor osztályt!
*/
class SimPoti {
double R; /// potméter ellenállása a két végpont között.
int pos; /// kezelőszerv állása (1..99);
public:
/// Konstruktor.
/// @param r - ellenállás értéke [ohm]
/// A konstruktor állítsa középállásba (50) a kezelőszervet!
SimPoti(double r);
/// Kezelőszerv poziciójának lekérdezése
/// @return - pozíció (1..50)
int getPos() const;
/// Két végpont és a középpont közötti eredő ellenállás
/// @return - Eredő ellenállás (Resistor)
Resistor getRes() const;
/// Kezelőszerv fogatása (növel)
/// A pozíció értéke nő, 99-nél fennakad
/// @return pillanatnyi pozció
int operator++();
/// Kezelőszerv fogatása (csökkent)
/// A pozíció értéke csökken, 1-nél fennakad
/// @return pillanatnyi pozció
int operator--();
};
#endif // POTMETER_H
/**
* \file potmeter_teszt.cpp
*
* Két végén összekötött potmétert modellező osztály tesztelése.
*
* Először gtest tesztekkel ellenőrizzük a működést pár esetre.
* Utána buta konzolos kijelzéssel "csavargatjuk" a kezelőszervet.
* Ez a rész Linux/UNIX alatt csak ANSI terminálbeállításokkal megy.
* (ncurses/pdcurses használatával hordozható lehetne! help velcome!)
*/
#include <iostream>
#include <cctype>
#include "gtest_lite.h"
#include "potmeter.h"
#include "console.h"
int main() {
TEST(SimPoti, Kozepallas) {
SimPoti p(100);
EXPECT_EQ(25., p.getRes().getR());
} END
TEST(SimPoti, Novel) {
SimPoti p(10);
++p;
EXPECT_DOUBLE_EQ(2.499, p.getRes().getR());
} END
TEST(SimPoti, Csokkent) {
SimPoti p(10);
--p;
EXPECT_DOUBLE_EQ(2.499, p.getRes().getR());
} END
TEST(SimPoti, Alsoveg) {
SimPoti p(200);
for (int i = 0; i < 1000; i++) --p;
EXPECT_DOUBLE_EQ(1.98, p.getRes().getR());
} END
TEST(SimPoti, Felsoveg) {
SimPoti p(1);
for (int i = 0; i < 1000; i++) ++p;
EXPECT_DOUBLE_EQ(0.0099, p.getRes().getR());
} END
std::cout << "Indulhat a teszt? ";
Console& con = Console::con(); // itt jön létre az egyetlen Console példány;
int ch = con.getch(); // karakter olvasás
con.clrscr(); // képernyő törlés
SimPoti p(100);
do {
switch (ch) {
case ' ':
case Console::KEY_UP:
++p;
break;
case Console::KEY_DOWN:
--p;
break;
}
/// Kezelőszerv kijelzés a 3. sorba
con.hMeter(p.getPos(), 99, 80, "Pos%4.0f:", 3);
/// Áramkijelzés (50V-al vizsgáljuk, 80 széles kijelzés az 5. sorba)
con.hMeter(p.getRes().getI(50), 50, 80, "I%5.1f: ", 5);
/// Feszültség kijelzés (2A-val vizsgáljuk)
con.hMeter(p.getRes().getU(2), 50, 80, "U%5.1f: ", 7);
/// Eredő ellenállás kijelzés
con.hMeter(p.getRes().getR(), 25, 80, "R%5.1f: ", 9);
/// kiírjuk a parancsokat
con.gotoxy(1, 11);
std::cout << "SP, FEL: novel, LE: csokkent, X: kilep";
} while ((ch = toupper(con.getch())) != 'X');
return 0;
}
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="resistor" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/resistor" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-g" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin/Release/resistor" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Release/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-pedantic-errors" />
<Add option="-pedantic" />
<Add option="-std=c++11" />
<Add option="-Wall" />
<Add option="-fno-elide-constructors" />
<Add option="-DDEBUG" />
</Compiler>
<Unit filename="elkeszult.h" />
<Unit filename="gtest_lite.h" />
<Unit filename="resistor.cpp" />
<Unit filename="resistor.h" />
<Unit filename="resistor_test.cpp" />
<Extensions>
<code_completion />
<envvars />
<debugger />
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>
#ifndef RESISTOR_H
#define RESISTOR_H
/**
* \file resistor.h
*
* Az CPP Ellenallas Jporta feladat Resistor osztálya
* a 4. laborgyakorlathoz kiegészítve
*
* Az Ön feladata a Jporta feladathoz elkészített resistor.cpp fájt kiegészíteni a hiányzó függvényekkel.
* Ahogyan halad a megvalósítással egyre több tesztesetet kell lefuttatni,
* ezért az ELKESZULT makró értéket a készültségi foknak megfelelően állítsa be az
* elkeszult.h fájlban!
* Ne hagyjon ki feladatot, sorban haladjon!
*
* Ebben a fájlban nem kell módosítania semmit, ugyanakkor célszerű a megvalósítandó tagfüggvények
* deklarációi kommentekkel együtt átmásolni a resistor.ccp-be, és azokat átalakítani definíciókká.
* Másolásnál ügyeljen arra, hogy a kontextus (scope) megváltozik.
*/
#include <iostream>
#ifdef DEBUG
# define Pr(str) std::cout << str <<std::endl
#else
# define Pr(...)
#endif
#include "elkeszult.h"
/**
* Ohmikus ellenállás
*/
class Resistor {
double R; // az ellenállás értéke ohmban
static double defR; // ellenállás alapértelmezett értéke ohmban
public:
/// Konstruktor.
/// Alapértelmezett értéket (defR) kap
Resistor();
/// Konstruktor.
/// @param r - ellenállás értéke [ohm]
Resistor(double r);
/// Default ellenállásérték beállítása
/// @param r - ellenállás értéke [ohm]
static void setDef(double r);
/// Ellenállás értékének lekérdezése.
/// @return - ellenállás értéke [ohm]
double getR() const {
return R;
}
/// Két ellenállás soros kapcsolása.
/// @param r - ellenállás
/// @return - eredő ellenállású Resistor
Resistor operator+(const Resistor& r) const;
/// Két ellenállás párhuzamos kapcsolása.
/// @param r - ellenállás
/// @return - eredő ellenállású Resistor
Resistor operator%(const Resistor& r) const;
/// -------- Itt következnek az elkészítendő tagfüggvények --------
#if ELKESZULT >= 2
/// Másoló konstruktor.
/// @param rhs - objektum amiről a másolatot kell létrehozni
Resistor(const Resistor& rhs);
#endif // ELKESZULT == 2
#if ELKESZULT >= 3
/// Destruktor
~Resistor();
#endif // ELKESZULT == 3
#if ELKESZULT >= 4
/// Értékadás
/// @param rhs - jobb oldali operandus (a bal a *this)
/// @return - referencia saját magára, hogy fűzhető legyen
Resistor& operator=(const Resistor& rhs);
#endif // ELKESZULT == 4
#if ELKESZULT >= 5
/// Ellenálláson folyó áram
/// @param u - áram
/// @return - áram
double getI(double u) const;
#endif // ELKESZULT >= 5
#if ELKESZULT >= 6
/// Ellenálláson eső feszültség
/// @param i - áram
/// @return - feszültség
double getU(double i) const;
#endif // ELKESZULT >= 6
#if ELKESZULT >= 7
/// Két ellenállás összehasonlítása.
/// @param r - ellenállás
/// @return - true, ha azonos
bool operator==(const Resistor& r) const;
#endif // ELKESZULT == 6
};
/// --- Globális függvények, operátorok ------
/// Többszörös: n darab egyforma r ellenállás összege (soros kapcsolása).
/// @param n - darabszám
/// @param rhs - ellenállás (jobb oldali operandus)
/// @return - eredő ellenállású Resistor
Resistor operator*(int n, const Resistor& rhs);
/// Inserter.
/// Ellenállás adatainak kiírása std::ostream-re
/// @param os - ouput stream
/// @param rhs - a kíírandó Resistor (jobb oldali operandus)
/// @return - output stream
std::ostream& operator<<(std::ostream& os, const Resistor& rhs);
#endif
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{2BBC8737-D00B-41B9-98A8-D44DD9053CEE}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>resistor</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="gtest_lite.h" />
<ClInclude Include="resistor.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="resistor.cpp" />
<ClCompile Include="resistor_test.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="gtest_lite.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resistor.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="resistor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="resistor_test.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
/**
* \file resistor_test.cpp
* (UTF-8 kodolasu fajl. Allitsa at a megjenetes kodolasat,
* ha a tovabbi kommentek nem olvashatok helyesen!)
*
* Ohmikus ellenállást modellező osztály kipróbálása
*
* Néhány ellenállás összekapcsolása, az elvárt eredmények megjegyzésben.
*/
#include <iostream>
#include "resistor.h"
using std::cout;
using std::endl;
using std::cin;
int main()
{
// cporta tesztesetei miatt csak egészeket írunk ki.
cout.setf(std::ios::fixed);
cout.precision(0);
Resistor r;
cout << r.getR() << endl; // default érték
cout << Resistor(130).getR() << endl; // 130
cout.precision(0);
Resistor r1(1000), r2(3000), r3(6000);
// o--[r1]--[r2]--o
cout << (r1 + r2).getR() << endl // 4000
// +--[r1]--+
// o--+ +---o
// +--[r1]--+
<< (r1 % r1).getR() << endl // 500
// o--[r1]--[r1]--o
<< (2 * r1).getR() << endl // 2000
// o--[r1]--[r1]--[r2]--o
<< (2*r1 + r2).getR() << endl // 5000
// o--[r1]--[r2]---[r1]--[r2]--o
<< (2 * (r1+r2)).getR() << endl // 8000
// +--[r2]--+ +--[r2]--+
// o--+ +---+ +---o
// +--[r3]--+ +--[r3]--+
<< (2 * (r2%r3)).getR() << endl; // 4000
#ifndef NO_STATIC
Resistor::setDef(2); // 2 ohm a default
#endif
Resistor rt[10]; // a tömb minden eleme 2 ohmos lesz
cout << rt[5].getR() << endl; // 5. elem is 2
try {
cout << (3 * r1).getR() << endl;
cout << (8 * r1).getR() << endl;
cout << (-8 * r1).getR() << endl;
}
catch (const char *s) {
cout << s << endl; // dobott kivétel
}
return 0;
}
/**
* \file resistor_test2.cpp
*
* Ohmikus ellenállást megvalósító osztály tesztesetei gtest_lite eszközkészletével
* megvalósítva a 4. laborfeladathoz.
* A feladat elsősorban az implicit tagfüggvények létrejöttét, használatát mutatja be.
*
* A laborfeladat megoldásához ebben az állományban nem kell módosítani.
*
* Az elkeszult.h-ban definiált ELKESZULT makró vezérli az egyes tesztesetek
* fordítását. A legutolsó teszteset az ELKESZULT értékét vizsgálja.
*
*/
#include <iostream>
#include <sstream>
#include "gtest_lite.h"
#include "resistor.h"
int main() {
GTINIT(std::cin); // Csak C(J)PORTA működéséhez kell
Resistor r;
TEST(Resistor, HazibanAdottR) {
double d = r.getR();
EXPECT_EQ(999999., d) << "Jporta feladatban megadott default ertekkel hasonlitson!" << std::endl;
} END
Resistor r1(1000), r2(3000);
TEST(Resistor, EgyPareteresKonsruktor) {
double d = r1.getR(); // 1000
EXPECT_DOUBLE_EQ(1000., d);
} END
TEST(Resistor, Masolo) {
Resistor r11 = r1;
double d = r11.getR(); // 1000
EXPECT_DOUBLE_EQ(1000., d);
} END
TEST(Resistor, Osszeg) {
double d = (r1 + r2).getR(); // 4000
EXPECT_DOUBLE_EQ(4000., d);
} END
TEST(Resistor, SetDef) {
Resistor::setDef(20);
Resistor rt[5];
double d = rt[3].getR(); // 20
EXPECT_DOUBLE_EQ(20., d);
} END
TEST(Resistor, Ertekadas) {
r1 = r2;
double d = r1.getR(); // 3000
EXPECT_DOUBLE_EQ(3000., d);
} END
#if ELKESZULT >= 5
TEST(ResistorTest, getI) { // getI
const Resistor r0(2);
EXPECT_DOUBLE_EQ(6.06, r0.getI(12.12));
} END
#endif
#if ELKESZULT >= 6
TEST(ResistorTest, getU) { // getU
const Resistor r0(12.12);
EXPECT_DOUBLE_EQ(24.24, r0.getU(2));
} END
#endif
#if ELKESZULT >= 7
TEST(ResistorTest, EQ) { // operator==
const Resistor r0(12345.6789);
const Resistor r1(123456789); // r1 ez pont a 10-szerese r0-nak
EXPECT_TRUE(r0 == r0); // önmagával
EXPECT_FALSE(r0 == r1);
Resistor r2 = 10000 * r0; // számítás nem lesz pontos
EXPECT_TRUE(r2 == r1);
r2 = r2 + Resistor(1e-5); // de ha tényleg eltér?
EXPECT_FALSE(r2 == r1);
const Resistor r3(1e-18); // kis értéknél hogy viselkedik?
r2 = r3 + Resistor(1e-18);
EXPECT_FALSE(r3 == r1);
} END
#endif
#if ELKESZULT >= 8
TEST(ResistorTest, Inserter) {
std::ostringstream oss; // stringstream-be írunk, és szövegesen hasonlítunk !
oss << Resistor(8.45) << '\t' << Resistor(100);
EXPECT_STREQ("8.45\t100", oss.str().c_str());
} END
#endif // ELKESZULT >= 8
/// Itt a vége
if (ELKESZULT < 6)
FAIL() << "\nLegalabb az elso ot feladatot oldja meg!" << std::endl;
if (ELKESZULT == 8 && !gtest_lite::test.fail())
std::cout << "Szuper! Mind kesz" << std::endl;
else
std::cout << "EKESZULT = " << ELKESZULT << std::endl;
GTEND(std::cerr); // Csak C(J)PORTA működéséhez kell
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment