Commit 490e6527 by Szeberényi Imre

v0

parents
#
# sinx.gnu
#
fn(x)=sin(x)/x
plot [x=-20:20] fn(x), sin(x)
pause -1
#
# Makefile pelda a string1 feladat (3. labor) megoldasanak forditasara
# gnumake valtozat
# Linuxokon es ural2-n is elerheto
#
# A make paranccsorabol magadott FLG valtozo tartalma atadodik a forditonak
# Pl:
# make FLG=-DRENDEZ
#
PROG = string2_test # a program neve (ezt allitjuk elo)
PROG_S = string2.cpp string2_test.cpp rendez.cpp # program forras fajljai
PROG_H = string2.h rendez.h rendez_u8.h gtest_lite.h # program header fajljai
PROG_L = # program libjei
CXX = g++ # a C fordito neve
#CXX = clang++ # clang-ot (llvm) is erdemes kiprobalni
CXXFLAGS += -g # es legyeb debug info is
CXXFLAGS += $(FLG) # es amit a parancsorbol megadnak
LDFLAGS = -g # debug a linkelesnel
######
# osszes object, osszes header osszes lib
OBJS = $(PROG_S:.cpp=.o)
HEADS = $(PROG_H)
LIBS = $(PROG_L)
#
# alapertelmezett cel: program
.PHONY: all
all: $(PROG)
$(PROG): $(OBJS)
$(CXX) $(LDFLAGS) $(OBJS) -o $@ $(LIBS)
# feltetelezzuk, hogy az osszes obj fugg az osszes headertol
$(OBJS): $(HEADS)
# legeneraljuk a dokumentaciot es belinkeljuk a public_html-be
.PHONY: doc
doc: $(HOME)/public_html
doxygen Doxyfile
ln -s `pwd`/html ~/public_html/string2
# public_html letrehozása
$(HOME)/public_html:
mkdir ~/public_html
# takaritas igeny szerint
.PHONY: clean
clean:
rm -f $(OBJS) $(OBJSUTF) $(PROG) $(PROGUTF) $(HOME)/public_html/string2
rm -rf html latex rtf
#ifndef GTEST_LITE_H
#define GTEST_LITE_H
/**
* \file gtest_lite.h
*
* A gtest keretrendszerhez hasonló rendszer.
* A tesztelés legalapvetőbb funkcióit támogató függvények és makrók
* Sz.I. 2015.
*
* 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 <cassert>
#include <cmath>
#include <cstring>
#include <limits>
#include <string>
#include <fstream>
// 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(); }
// 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.tstatus(true, __FILE__, __LINE__)
/// Sikertelen teszt makrója
#define FAIL() gtest_lite::test.tstatus(false, __FILE__, __LINE__)
/// Azonosságot elváró makró
#define EXPECT_EQ(expected, actual) EXPECTCMP((expected) == (actual), expected, actual)
/// Eltérést elváró makró
#define EXPECT_NE(expected, actual) EXPECTNE((expected) == (actual), expected, actual)
/// Igaz értéket elváró makró
#define EXPECT_TRUE(actual) EXPECTCMP(actual, "true", actual)
/// Hamis értéket elváró makró
#define EXPECT_FALSE(actual) EXPECTCMP(!(actual), "false", actual)
/// Valós számok azonosságát elváró makró
#define EXPECT_DOUBLE_EQ(expected, actual) EXPECTCMP(gtest_lite::almostEQ(expected, actual), expected, actual)
/// C stringek (const char *) azonosságát tesztelő makró
#define EXPECT_STR_EQ(expected, actual) ((actual != NULL) ? \
EXPECTCMP(strcmp(expected, actual) == 0, expected, actual) : \
EXPECT(false, "STR_EQ NULL pointert kapott!"))
/// C stringek (const char *) eltéréset tesztelő makró
#define EXPECT_STR_NE(expected, actual) ((actual != NULL) ? \
EXPECTNE(strcmp(expected, actual) != 0, expected, actual) : \
EXPECT(false, "STR_EQ NULL pointert kapott!"))
/// 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 é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.")
/// 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.")
/// -----------------------------------
/// Belső megvalósításhoz tartozó makrók, és osztályok.
/// Nem célszerű közvetlenül használni, vagy módosítani
/// -----------------------------------
/// EXPECT: makró, hogy könnyen lecserélhető legyen
#define EXPECT(expr, msg) gtest_lite::test.expect(expr, __FILE__, __LINE__, #msg)
/// EXPECTEXP: általános kifejezés kiértékelése
#define EXPECTEXP(expr, exp, act) gtest_lite::test.expect(expr, __FILE__, __LINE__, #expr) \
<< "**A(z) '"#act << "'kifejezes\n** erteke: " << std::boolalpha << (act) \
<< "\n** elvart: " << (exp) << std::endl
/// EXPECTCMP: összehasonlítás
#define EXPECTCMP(expr, exp, act) gtest_lite::test.expect(expr, __FILE__, __LINE__, #act) \
<< "**A(z) '"#act << "'kifejezes\n** erteke: " << std::boolalpha << (act) \
<< "\n** elvart: " << (exp) << std::endl
/// EXPECTNE: összehasonlítás
#define EXPECTNE(expr, exp, act) gtest_lite::test.expect(expr, __FILE__, __LINE__, #act) \
<< "**A(z) '"#act << "'kifejezes\n** erteke : " << std::boolalpha << (act) \
<< "\n** elvart, hogy nem: " << (exp) << std::endl
/// 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
/// 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
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
Test() :sum(0), failed(0), status(false), null("/dev/null") {}
/// Teszt kezdete
void begin(const char *n) {
name = n; status = true;
#ifndef CPORTA
std::cerr << "\n---> " << name << std::endl;
#endif // CPORTA
++sum;
}
/// Teszt vége
void end() {
#ifdef CPORTA
if (!status)
#endif // CPORTA
std::cerr << (status ? " SIKERES" : "** HIBAS ****") << "\t" << name << " <---" << std::endl;
}
/// Eredményt adminisztráló tagfüggvény True a jó eset.
std::ostream& expect(bool st, const char *file, int line, const char *expr) {
if (!st) {
++failed;
status = false;
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**** HIBA: " << &file[i] << "(" << line << "): " << expr << " ****" << std::endl;
}
return null;
}
/// Eredményt adminisztráló tagfüggvény True a jó eset, mindig ír
std::ostream& tstatus(bool st, const char *file, int line) {
if (!st) {
++failed;
status = false;
}
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 << (status ? "** SIKERES" : "** HIBAS") << " TESZT "<< &file[i] << "(" << line << ") **" << std::endl;
}
/// Destruktor
~Test() {
#ifdef CPORTA
if (failed)
#endif // CPORTA
std::cerr << "\n==== TESZT VEGE ==== HIBAS/OSSZES: " << failed << "/" << sum << std::endl;
}
};
/// Egytelen statikus példány
static Test test;
/// Segédfüggvény 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
inline bool almostEQ(double a, double b) {
// eps: ha a relatív, vagy abszolút hiba ettől kisebb, akkor elfogadjuk
double eps = 10 * std::numeric_limits<double>::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
/**
* \file rendez.cpp
*
* Egyszerű teszt modul az ékezetes karaktereket tartalmazó
* String kipróbálására.
* Az összehasonlítás figyelembe veszi az LC_COLLATE beállítást
*
* A programból kiírt szövegkonstansok megjelenése azonban függ
* a forrásfájl karakterkódolásától.
* Ezt itt meglehetősen fapados módon feltételes include-dal próbáltuk
* megoldani.
* Igazi hordozható megoldást csak valamilyen lokalizációs technika
* használata ad (pl. gettext, wxString, stb.)
*
*/
#ifdef _MSC_VER
// MSC ne adjon figyelmeztető üzenetet a stringkezelő függvényekre.
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <clocale>
#if defined(WIN32) || defined(_WIN32)
# include <windows.h>
# include "rendez.h" // latin-2 kódolású szövegek
#else
# include "rendez_u8.h" // UTF8 kódolású szövegek
#endif
#include "string2.h"
using std::cout;
using std::endl;
using std::cin;
#if ELKESZULT >= 11
/// Összehasonlító a qsorthoz
int cmp(const void* s1, const void* s2) {
return strcoll((*(const String**)s1)->c_str(), (*(const String**)s2)->c_str());
}
void rendez() {
cout << endl;
cout << String(INDUL) << endl;
const int N = 15;
String szavak[N]; /// Itt lesznek a szavak
String *poik[N]; /// Itt pedig a pointerek a rendezéshez
int db;
cout << String(IRJON) << N << String(SZOVEGET) << endl <<
String(UTOLSO) << endl;
cout << String(MINTA) << endl;
for (db = 0; db < N && cin >> szavak[db]; ++db)
poik[db] = &szavak[db]; /// címek tömbjét képezzük
/// Pointerek tömbjét rendezzük
qsort(poik, db, sizeof(String*), cmp);
cout << "----- Rendezve: ------" << endl;
for (int i = 0; i < db; ++i) {
poik[i]->printDbg(""); /// így a hossz is látszik UTF-8-nál nem egyezik meg a betűk számával
// cout << *poik[i] << endl;
}
}
#endif
#ifndef RENDEZ_H
#define RENDEZ_H
/*
* latin-2 kodolasu szovegek
*
* windows alatt ez kell
*/
#define INDUL "kezetes betk prbja:"
#define IRJON "rjon legfeljebb "
#define SZOVEGET " szbl ll szveget!"
#define UTOLSO "Az utols sor utn EOF (ctrl-Z/ctrl-D) legyen!"
#define MINTA " Pl: dm Bla Ern s Ott kgyt bvl"
void rendez();
#endif
/*
* utf-8 kodolasu szovegek
*
* Nem windows alatt feltehetoen ez kell
*/
#define INDUL "Ékezetes betűk próbája:"
#define IRJON "Írjon legfeljebb "
#define SZOVEGET " szóból álló szöveget!"
#define UTOLSO "Az utolsó sor után EOF (ctrl-Z/ctrl-D) legyen!"
#define MINTA " Pl: Ádám Béla Ernő és Ottó kígyót bűvöl"
void rendez();
/**
* EZ EGY HIBÁS megoldása a 6. heti labrofeladatnak!
* A problémák az üres string kezelésével kacsolatosak
* A String + String művelet megvalósításában memóriavesztés is lehetséges
*
* \file string2_kesz.cpp
*
* Itt kell megvalósítania a hiányzó tagfüggvényeket.
* Segítségül megadtuk a C-ben megírt változatban (string1.c) használt függvényneveket.
*
* Ha valamit INLINE-ként valósít meg, akkor annak a .h-ba kell kerülnie,
* akár kívül akár osztályon belül definiálja. (Az inline függvényeknek minden
* fordítási egységben elérhetőknek kell lenniük)
* *
* A teszteléskor ne felejtse el beállítani a header állományban az ELKESZULT makrót.
* A VC saját memóriafogyás ellenőrzője csak debug módban (Debug->Start) működik!
*
*/
#ifdef _MSC_VER
// MSC ne adjon figyelmeztető üzenetet a stringkezelő függvényekre.
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <iostream> // Kiíratáshoz
#include <cstring> // Stringműveletekhez
#include "string2.h"
using std::cin;
using std::ios_base;
/// Konstruktor: egy char karakterből (createStrFromChar)
String::String(char ch) {
// Meghatározzuk a hosszát
len = 1;
// Lefoglalunk a helyet a hossznak + a lezaró nullának
pData = new char[len+1];
// Betesszük a karaktert
pData[0] = ch;
pData[1] = '\0';
}
// Konstruktor: egy nullával lezárt char sorozatból (createStringFromCharStr)
String::String(const char *p) {
// Meghatározzuk a hosszát
len = strlen(p);
// Helyet foglalunk
pData = new char[len+1];
// Bemásoljuk a stringet, ami le van zárva 0-val így használható az strcpy is
strcpy(pData, p);
}
// Másoló konstruktor
String::String(const String& s1) {
// Meghatározzuk a hosszát
len = s1.len;
// Helyet foglalunk
pData = new char[len+1];
// Bemásoljuk a stringet, ami le van zárva 0-val így használható az strcpy is
strcpy(pData, s1.pData);
}
// operator=
String& String::operator=(const String& rhs_s) {
if (this != &rhs_s) {
delete[] pData;
len = rhs_s.len;
// Helyet foglalunk
pData = new char[len+1];
// Bemásoljuk a stringet, ami le van zárva 0-val így használható az strcpy is
strcpy(pData, rhs_s.pData);
}
return *this;
}
// [] operátorok: egy megadott indexű elem REFERENCIÁJÁVAL térnek vissza.
// indexhiba esetén dobjon egy const char * típusú hibát!
char& String::operator[](unsigned int idx) {
if (idx >= len) throw "String: indexelesi hiba";
return pData[idx];
}
const char& String::operator[](unsigned int idx) const {
if (idx >= len) throw "String: indexelesi hiba";
return pData[idx];
}
// + operátor, ami két stringet ad össze (concatString)
String String::operator+(const String& rhs_s) const {
String temp; // ide kerül az eredmény
// Meghatározza az új string hosszát
temp.len = len + rhs_s.len;
// lefoglalja a memóriát az új stringnek.
temp.pData = new char[temp.len+1];
// Az elejére bemásolja az első stringet
strcpy(temp.pData, pData);
// Bemásolja a második stringet.
strcat(temp.pData, pData);
return temp; // visszatér az eredménnyel
}
// << operator, ami kiír az ostream-re
std::ostream& operator<<(std::ostream& os, const String& s0) {
os << s0.c_str();
return os;
}
// << operátor, ami beolvas az istreamről egy szót
std::istream& operator>>(std::istream& is, String& s0) {
unsigned char ch;
s0 = String(""); // üres string, ehhez fűzünk hozzá
std::ios_base::fmtflags fl = is.flags(); // eltesszük a régi flag-eket
is.setf(ios_base::skipws); // az elején eldobjuk a ws-t
while (is >> ch) {
is.unsetf(ios_base::skipws); // utána pedig már nem
if (isspace(ch)) {
is.putback(ch); // na ezt nem kérjük
break;
} else {
s0 = s0 + ch; // végére fűzzük a karaktert
}
}
is.setf(fl); // visszaállítjuk a flag-eket
return is;
}
#ifndef STRING_H
#define STRING_H
/**
* EZ EGY HIBÁS megoldása a 6. heti labrofeladatnak!
* A problémák az üres string kezelésével kacsolatosak
* A String + String művelet megvalósításában memóriavesztés is lehetséges
*
* \file string2.h
*
* Ez a fájl tartalmazza a
* - String osztály deklarációját
* - az inline függvényeket. Ha valamit inline-ként akar megvalósítani,
* akkor azt ebbe a fájlba írja! Tipikusan a rövid kódokat szokás
* inline-két megvalósítani (pl: c_str).
* Más függvényeket ill definiciókat ne írjon a .h fájlba!
*
* A C-ben megírt (string1.c) függvények most tagfüggvényekké váltak, és
* eltűnt az első paraméterük (s0) (ebből lett a this).
* A nevük is megváltozott, mert most már az összetartozást, és a
* paraméterek típusára való utalást már nem a név hordozza, hanem az osztály.
* A createString... alakú függvényekből konstruktorok keletkeztek.
* A disposeString destruktorrá alakült át.
* Egyes műveletvégző függvényekből pedig operátor függvény lett.
*/
/**
* Az Ön feladata a string2.cpp fájlban megvalósítani (definiálni) az egyes
* függvényeket.
*
* Ahogyan halad a megvalósítással egyre több tesztesetet kell lefuttatni,
* ezért az ELKESZULT makro értéket folyamatosan növelje a feladatsorszámoknak
* megfelelően!
*
* Tanulságos a megvalósítás előtt már a megnövelt értékkel is lefordítani
* a programot, és elemezni a kapott hibajelzést.
*
*/
#define ELKESZULT 13
/**
* \section fel Feladat:
* A tantermi gyakorlatokon, valamint a 3. laborgyakorlaton is foglalkoztunk egy
* olyan sztring (String) adatszerkezet és a rajta műveleteket végző függvények
* megtervezésével/impelmentálásával ami dinamikusan tárol és annyi memóriát foglal
* amennyi a tároláshoz szükséges.
*
* Ezeket és a tanultakat felhasználva a string2.h és a string2.cpp állományokban
* definiáljon ill. implementáljon egy olyan sztring (String) osztályt C++ nyelven, ami
* dinamikusan tárol és rendelkezik az alábbi tulajosnágokkal!
*
* 1 A paraméter nélkül hívható konstruktora üres sztringet hozzon étre!
* 2. Van olyan tagfüggvénye ( c_str() ), ami C-sztringgel, azaz nullával lezárt
* karaktersorozatra mutató pointerel (const char *) tér vissza.
* 3. Van olyan konstruktora, ami karakterből hoz létre sztringet.
* 4. Van olyan konstruktora, ami C-sztringből (const char*) hoz létre sztringet.
* 5. Az osztályból létrehozott objektum legyen átadható értékkparaméterként!
* 6. Támogassa a többszörös értékadást (b = a = a)!
* 7 Legyenek olyan operárorai (operator+), amivel a sztring végéhez sztringet,
* és karaktert lehet fűzni!
* 8. Lehessen karaterhez is sztringet fűzni a + operátorral!
* 9. A tárolt a karakterek legyenek elérhetőek a szokásos módon indexeléssel!
* Az indexeléssel elér elem legyen használható balértékként is!
* A konstans objektumok is legyenek indexelhetők.
* Az indexelés operátor hiba esetén dobjon const char * kivételt!
* 10. Készítsen olyan << operátort, amivel egy sztring kiírható egy ostream típusú
* objektumra!
*
* Szorgalmi feladatok:
* 11. Készítsen olyan fűzhető >> operátort, amivel be tud olvasni egy szót egy sztring-be!
* A beolvasó működjön úgy, mint a scanf %s, azaz a szó végét white space határolja!
* A szó eleji white space karaktereket pedig el kell dobni.
* *Megj: az istream wshite space kezelése a flags() tagfüggvénnyel szabályozható
* 12. Próbálja ki az ékezetes karakterek rendezését is! Ehhez elkészítettünk egy
* egyszerű kódrészletet ami qsort() függvényt használ.
* Értse meg a rendez.cpp fájlban levő kód működését és futtassa a programot!
* 13. A setlocale függvényhívás beállítja a karakterek és sztringek összehasonlításához
* szükséges nyelvi környezetet (LC_COLLATE) próbálja ki! Változott a rendezési
* sorrend?
*/
#include <iostream>
#include <cstring>
/**
* Header fájlokból megfontoltan kell include-ot használni.
* Névteret azonban nem célszerű kinyitni, mert annak hatása zavaró lehet
* ott ahol ez a header include-olva lesz.
*/
/**
* A String osztály.
* A 'pData'-ban vannak a karakterek (a lezáró nullával együtt), 'len' a hossza.
* A hosszba nem számít bele a lezáró nulla.
*/
class String {
char *pData; /// pointer az adatra
unsigned int len; /// hossz lezáró nulla nélkül
public:
/// Az első két feladatot előre megoldottuk, de lehet, hogy nem jól.
/// Az üres string reprezentációja nem szerecsés, mert így NULL pointerré
/// konvertál a c_str(), ami külön kezelést igényel a későbbiekben, így
/// a teszt program sem fogadja el.
/// Gondolja végig, és változtassa meg!
/// Két lehetőség van:
/// a) nem NULL pointert tárol, hanem ténylegesen üres sringet.
/// b) a c_str() üres stringet ad vissza
/// Bármelyik jó, mert ez az osztály belügye.
/// Default konstruktor:
String() :pData(0), len(0) {}
/// C-stringet ad vissza
const char* c_str() const { if (pData) return pData; else return "";}
/// Konstruktor: egy char karakterből (createStrFromChar)
String(char ch);
/// Konstruktor: egy nullával lezárt char sorozatból (createStringFromCharStr)
String(const char *p);
/// MÁSOLÓ konstruktor, ami a createStringFromString-ből keletkezett
/// @param s1 - String, amiből létrehozzuk az új String-et
String(const String& s1);
/// Destruktor (disposeString)
~String() { delete[] pData; }
/// Egyéb tagfüggvények:
/// Kiírunk egy Stringet (debug célokra) (ez kész)
/// Elötte kiírunk egy tetszőleges szöveget.
/// @param txt - nullával lezárt szövegre mutató pointer
void printDbg(const char *txt = "") const {
std::cout << txt << "[" << len << "], "
<< (pData ? pData : "(NULL)") << std::endl;
}
/// Operátorok:
/// Értékadó operátor is kell !
/// @param rhs_s - jobboldali String
/// @return baoldali (módosított) string (referenciája)
String& operator=(const String& rhs_s);
/// Két Stringet összefűz (concatString)
/// @param rhs_s - jobboldali String
/// @return új String, ami tartalmazza a két stringet egmás után
String operator+(const String& rhs_s) const ;
/// Sztrinhez karaktert összefűz (concatString)
/// @param rhs_c - jobboldali karakter
/// @return új String, ami tartalmazza a két sztringet egymás után
String operator+(char rhs_c) const { return *this + String(rhs_c);}
/// A string egy megadott indexű elemének REFERENCIÁJÁVAL tér vissza.
/// charAtString-ből keletkezett, de ezt bal oldalon is lehet használni
/// @param idx - charakter indexe
/// @return karakter (referencia)
/// Indexelési hiba esetén const char* kivételt dob (assert helyett).
char& operator[](unsigned int idx);
/// A string egy megadott indexű elemének REFERENCIÁJÁVAL tér vissza.
/// charAtString-ből keletkezett. Konstans stringre alkalmazható.
/// Indexelési hiba esetén const char* kivételt dob (assert helyett).
/// @param idx - charakter indexe
/// @return karakter (referencia)
/// Indexelési hiba esetén const char* kivételt dob (assert helyett).
const char& operator[](unsigned int idx) const;
};
/// Globális függvények:
/// kiír az ostream-re (printString)
/// Nem célszerű using-ot használni, mert ez egy include file. Így ki kell írni az std::-t
/// @param os - ostream típusú objektum
/// @param s0 - String, amit kiírunk
/// @return os
/// Vigyázat nem tagfüggvény! Nem is tűnik el az s0 !
/// Nem kell, hogy barát legyen, mert a c_str() segít
std::ostream& operator<<(std::ostream& os, const String& s0);
/// Beolvas az istream-ről egy szót egy string-be.
/// @param is - istream típusú objektum
/// @param s0 - String, amibe beolvas
/// @return is
/// Vigyázat nem tagfüggvény! Nem is tűnik el az s0 !
/// Nem kell, hogy barát legyen mert van Str + ch
std::istream& operator>>(std::istream& is, String& s0);
/// String operator+(char ch, const String& str);
/// Vagy inline, vagy nem itt a helye!
inline String operator+(char ch, const String& str) { return String(ch) + str; }
#endif
#ifndef STRING_H
#define STRING_H
/**
* EZ EGY HIBÁS megoldása a 6. heti labrofeladatnak!
* A problémák az üres string kezelésével kacsolatosak
* A String + String művelet megvalósításában memóriavesztés is lehetséges
*
* \file string2.h
*
* Ez a fájl tartalmazza a
* - String osztály deklarációját
* - az inline függvényeket. Ha valamit inline-ként akar megvalósítani,
* akkor azt ebbe a fájlba írja! Tipikusan a rövid kódokat szokás
* inline-két megvalósítani (pl: c_str).
* Más függvényeket ill definiciókat ne írjon a .h fájlba!
*
* A C-ben megírt (string1.c) függvények most tagfüggvényekké váltak, és
* eltűnt az első paraméterük (s0) (ebből lett a this).
* A nevük is megváltozott, mert most már az összetartozást, és a
* paraméterek típusára való utalást már nem a név hordozza, hanem az osztály.
* A createString... alakú függvényekből konstruktorok keletkeztek.
* A disposeString destruktorrá alakült át.
* Egyes műveletvégző függvényekből pedig operátor függvény lett.
*/
/**
* Az Ön feladata a string2.cpp fájlban megvalósítani (definiálni) az egyes
* függvényeket.
*
* Ahogyan halad a megvalósítással egyre több tesztesetet kell lefuttatni,
* ezért az ELKESZULT makro értéket folyamatosan növelje a feladatsorszámoknak
* megfelelően!
*
* Tanulságos a megvalósítás előtt már a megnövelt értékkel is lefordítani
* a programot, és elemezni a kapott hibajelzést.
*
*/
#define ELKESZULT 13
/**
* \section fel Feladat:
* A tantermi gyakorlatokon, valamint a 3. laborgyakorlaton is foglalkoztunk egy
* olyan sztring (String) adatszerkezet és a rajta műveleteket végző függvények
* megtervezésével/impelmentálásával ami dinamikusan tárol és annyi memóriát foglal
* amennyi a tároláshoz szükséges.
*
* Ezeket és a tanultakat felhasználva a string2.h és a string2.cpp állományokban
* definiáljon ill. implementáljon egy olyan sztring (String) osztályt C++ nyelven, ami
* dinamikusan tárol és rendelkezik az alábbi tulajosnágokkal!
*
* 1 A paraméter nélkül hívható konstruktora üres sztringet hozzon étre!
* 2. Van olyan tagfüggvénye ( c_str() ), ami C-sztringgel, azaz nullával lezárt
* karaktersorozatra mutató pointerel (const char *) tér vissza.
* 3. Van olyan konstruktora, ami karakterből hoz létre sztringet.
* 4. Van olyan konstruktora, ami C-sztringből (const char*) hoz létre sztringet.
* 5. Az osztályból létrehozott objektum legyen átadható értékkparaméterként!
* 6. Támogassa a többszörös értékadást (b = a = a)!
* 7 Legyenek olyan operárorai (operator+), amivel a sztring végéhez sztringet,
* és karaktert lehet fűzni!
* 8. Lehessen karaterhez is sztringet fűzni a + operátorral!
* 9. A tárolt a karakterek legyenek elérhetőek a szokásos módon indexeléssel!
* Az indexeléssel elér elem legyen használható balértékként is!
* A konstans objektumok is legyenek indexelhetők.
* Az indexelés operátor hiba esetén dobjon const char * kivételt!
* 10. Készítsen olyan << operátort, amivel egy sztring kiírható egy ostream típusú
* objektumra!
*
* Szorgalmi feladatok:
* 11. Készítsen olyan fűzhető >> operátort, amivel be tud olvasni egy szót egy sztring-be!
* A beolvasó működjön úgy, mint a scanf %s, azaz a szó végét white space határolja!
* A szó eleji white space karaktereket pedig el kell dobni.
* *Megj: az istream wshite space kezelése a flags() tagfüggvénnyel szabályozható
* 12. Próbálja ki az ékezetes karakterek rendezését is! Ehhez elkészítettünk egy
* egyszerű kódrészletet ami qsort() függvényt használ.
* Értse meg a rendez.cpp fájlban levő kód működését és futtassa a programot!
* 13. A setlocale függvényhívás beállítja a karakterek és sztringek összehasonlításához
* szükséges nyelvi környezetet (LC_COLLATE) próbálja ki! Változott a rendezési
* sorrend?
*/
#include <iostream>
#include <cstring>
/**
* Header fájlokból megfontoltan kell include-ot használni.
* Névteret azonban nem célszerű kinyitni, mert annak hatása zavaró lehet
* ott ahol ez a header include-olva lesz.
*/
/**
* A String osztály.
* A 'pData'-ban vannak a karakterek (a lezáró nullával együtt), 'len' a hossza.
* A hosszba nem számít bele a lezáró nulla.
*/
class String {
char *pData; /// pointer az adatra
unsigned int len; /// hossz lezáró nulla nélkül
public:
/// Az első két feladatot előre megoldottuk, de lehet, hogy nem jól.
/// Az üres string reprezentációja nem szerecsés, mert így NULL pointerré
/// konvertál a c_str(), ami külön kezelést igényel a későbbiekben, így
/// a teszt program sem fogadja el.
/// Gondolja végig, és változtassa meg!
/// Két lehetőség van:
/// a) nem NULL pointert tárol, hanem ténylegesen üres sringet.
/// b) a c_str() üres stringet ad vissza
/// Bármelyik jó, mert ez az osztály belügye.
char* strcpy(char *to, const char *from) const {
if (from) ::strcpy(to, from);
else *to = 0;
return to;
}
char* strcat(char *to, const char *from) const {
if (from) ::strcat(to, from);
return to;
}
/// Default konstruktor:
String() :pData(0), len(0) {}
/// C-stringet ad vissza
const char* c_str() const { if (pData) return pData; else return "";}
/// Konstruktor: egy char karakterből (createStrFromChar)
String(char ch);
/// Konstruktor: egy nullával lezárt char sorozatból (createStringFromCharStr)
String(const char *p);
/// MÁSOLÓ konstruktor, ami a createStringFromString-ből keletkezett
/// @param s1 - String, amiből létrehozzuk az új String-et
String(const String& s1);
/// Destruktor (disposeString)
~String() { delete[] pData; }
/// Egyéb tagfüggvények:
/// Kiírunk egy Stringet (debug célokra) (ez kész)
/// Elötte kiírunk egy tetszőleges szöveget.
/// @param txt - nullával lezárt szövegre mutató pointer
void printDbg(const char *txt = "") const {
std::cout << txt << "[" << len << "], "
<< (pData ? pData : "(NULL)") << std::endl;
}
/// Operátorok:
/// Értékadó operátor is kell !
/// @param rhs_s - jobboldali String
/// @return baoldali (módosított) string (referenciája)
String& operator=(const String& rhs_s);
/// Két Stringet összefűz (concatString)
/// @param rhs_s - jobboldali String
/// @return új String, ami tartalmazza a két stringet egmás után
String operator+(const String& rhs_s) const ;
/// Sztrinhez karaktert összefűz (concatString)
/// @param rhs_c - jobboldali karakter
/// @return új String, ami tartalmazza a két sztringet egymás után
String operator+(char rhs_c) const { return *this + String(rhs_c);}
/// A string egy megadott indexű elemének REFERENCIÁJÁVAL tér vissza.
/// charAtString-ből keletkezett, de ezt bal oldalon is lehet használni
/// @param idx - charakter indexe
/// @return karakter (referencia)
/// Indexelési hiba esetén const char* kivételt dob (assert helyett).
char& operator[](unsigned int idx);
/// A string egy megadott indexű elemének REFERENCIÁJÁVAL tér vissza.
/// charAtString-ből keletkezett. Konstans stringre alkalmazható.
/// Indexelési hiba esetén const char* kivételt dob (assert helyett).
/// @param idx - charakter indexe
/// @return karakter (referencia)
/// Indexelési hiba esetén const char* kivételt dob (assert helyett).
const char& operator[](unsigned int idx) const;
};
/// Globális függvények:
/// kiír az ostream-re (printString)
/// Nem célszerű using-ot használni, mert ez egy include file. Így ki kell írni az std::-t
/// @param os - ostream típusú objektum
/// @param s0 - String, amit kiírunk
/// @return os
/// Vigyázat nem tagfüggvény! Nem is tűnik el az s0 !
/// Nem kell, hogy barát legyen, mert a c_str() segít
std::ostream& operator<<(std::ostream& os, const String& s0);
/// Beolvas az istream-ről egy szót egy string-be.
/// @param is - istream típusú objektum
/// @param s0 - String, amibe beolvas
/// @return is
/// Vigyázat nem tagfüggvény! Nem is tűnik el az s0 !
/// Nem kell, hogy barát legyen mert van Str + ch
std::istream& operator>>(std::istream& is, String& s0);
/// String operator+(char ch, const String& str);
/// Vagy inline, vagy nem itt a helye!
inline String operator+(char ch, const String& str) { return String(ch) + str; }
#endif
#
# .xsessionrc
#
x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
xeyes -geometry 50x50-50+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