Commit 4ab77d53 by Szeberényi Imre

lab 02

parents
Laborgyakorlat anyaga
=====================
TARTALOM:
--------
const_h.cpp file:
* Tanulságos hibák a konstans típusmódosító tanulásához.
A fájlt először fordítóprogram használata nélkül elemezze, majd próbálja lefordítani.
ref_h.cpp fájl:
* Tanulságos hibák a referencia típus tanulásához.
A fájlt először fordítóprogram használata nélkül elemezze, majd próbálja lefordítani.
string1 katalógus:
* A String adatszerkezet és az azt kezelő függvények
hibás megvalósítása C nyelven.
Hallgatói feladat a hibák kiszűrése egy működő C változat előállítása.
* A könyvtár tartalmazza a dinamikus memória kezelésével kapcsolatos gyakori hibák
felderítését segítő memtrace módszer állományait is.
string2_cpp katalógus:
* Ebben a könyvtárban kell előállítani a String azon változatát, ami már C++ nyelvi
elemeket használ, de még nem használja az OO elemeket/elveket.
A laborgyakorlat feladatainak részletes leírása [git.ik.bme.hu/Prog2/labor_peldak/lab_02](https://git.ik.bme.hu/Prog2/labor_peldak/lab_02) oldalon olvasható.
void ff(const int *ip) {
*ip = 3;
}
int main()
{
// 1.
const int i;
// 2.
const int j = 10;
j++;
// 3.
const int l = 10;
int *p=&l;
(*p)++;
// 4.
extern void f(int *i);
const int iv = 100;
f(&iv);
// 5.
const int ivv = 100;
ff(&ivv);
// 6.
const int v[] = {1,2,3};
v[1]++;
// 7.
const int siz = 20;
int t[siz];
// 8.
char s1[] = "Hello konstans szoveg";
const char *pc = s1;
pc[0] = 'A';
pc++;
// 9.
char s2[] = "Hello konstans pointer";
char* const cp = s2;
cp[0] = 'B';
cp++;
// 10.
char s3[] = "Hello konstans szoveg konstans pointer";
const char* const cpc = s3;
cpc[0] = 'C';
cpc++;
// 11.
enum Szinek { tok, zold, makk, piros };
Szinek adu;
adu = 1;
adu = Szinek(10);
return(0);
}
// 1.
long glob;
float fglob;
// 2.
long& fr()
{
return glob;
}
// 3.
int& fifi()
{
int a;
return a;
}
// 4.
int *fp()
{
int a;
return &a;
}
// 5.
long& fr(long& a, char c)
{
return a;
}
// 6.
long& fr(long x)
{
return x;
}
// 7.
float& fr(long x)
{
return fglob;
}
// 8.
float szg(int a = 1, float x)
{
return a * x;
}
// 9.
int main()
{
fr()++;
fr() = 54;
fr() = fr() + 4;
return 0;
}
#
# Makefile pelda a string1 feladat (2. labor) megoldasanak forditasara
# gnumake valtozat
# Linuxokon es ural2-n is elerheto
#
# A make paranccsorabol magadott CMD valtozo tartalma atadodik a forditonak
# Pl:
# make CMD=-DMEMTRACE
#
PROG = string1 # a program neve (ezt allitjuk elo)
PROG_O = string1.o string1_main.o # program object fajljai
PROG_H = string1.h # program header fajljai
PROG_L = # program libjei
MTRACE_O = memtrace.o # memtrace object fajl
MTRACE_H = memtrace.h # memtrace header fajlja
CC = gcc # a C fordito neve
#CC = clang # clang-ot (llvm) is erdemes kiprobalni
CFLAGS = -std=c99 -pedantic -Wall # kapcsolok: C99, legyen bobeszedu es pedans
CFLAGS += -g # es legyeb debug info is
CFLAGS += $(CMD) # es amit a parancsorbol megadnak
LDFLAGS = -g # debug a linkelesnel
# osszes object, osszes header osszes lib
OBJS = $(PROG_O) $(MTRACE_O)
HEADS = $(PROG_H) $(MTRACE_H)
LIBS = $(PROG_L)
# alapertelmezett cel: program
.PHONY: all
all: $(PROG)
$(PROG): $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) -o $@ $(LIBS)
# feltetelezzuk, hogy az osszes obj fugg az osszes headertol
$(OBJS): $(HEADS)
# takaritas igeny szerint
.PHONY: clean
clean:
rm -f $(OBJS) $(PROG)
#ifndef GTEST_LITE_H
#define GTEST_LITE_H
/**
* \file gtest_lite.h
*
* Google gtest keretrendszerhez hasonló rendszer.
* Sz.I. 2015., 2016., 2017. (_Has_X)
*
* 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(); }
// 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_STREQ(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_STRNE(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.")
/// 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
#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édfüggvény egy publikus adattag, vagy tagfüggvény létezésének tesztelésére fordítási időben
void hasMember(...) {}
/// -----------------------------------
/// 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
#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
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;
}
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) {
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
/*********************************
Memoriaszivargas-detektor
Keszitette: Peregi Tamas, BME IIT, 2011
petamas@iit.bme.hu
Kanari: Szeberenyi Imre, 2013.,
VS 2012: Szebernyi Imre, 2015.,
mem_dump: 2016.
inclue-ok: 2017., 2018.
*********************************/
#ifndef MEMTRACE_H
#define MEMTRACE_H
#if defined(MEMTRACE)
/*ha definilva van, akkor a hibakat ebbe a fajlba rja, egybkent stderr-re*/
/*#define MEMTRACE_ERRFILE MEMTRACE.ERR*/
/*ha definialva van, akkor futas kozben lancolt listat epit. Javasolt a hasznalata*/
#define MEMTRACE_TO_MEMORY
/*ha definialva van, akkor futas kozben fajlba irja a foglalasokat*/
/*ekkor nincs ellenorzes, csak naplozas*/
/*#define MEMTRACE_TO_FILE*/
/*ha definialva van, akkor a megallaskor automatikus riport keszul */
#define MEMTRACE_AUTO
/*ha definialva van, akkor malloc()/calloc()/realloc()/free() kovetve lesz*/
#define MEMTRACE_C
#ifdef MEMTRACE_C
/*ha definialva van, akkor free(NULL) nem okoz hibat*/
#define ALLOW_FREE_NULL
#endif
#ifdef __cplusplus
/*ha definialva van, akkor new/delete/new[]/delete[] kovetve lesz*/
#define MEMTRACE_CPP
#endif
#if defined(__cplusplus) && defined(MEMTRACE_TO_MEMORY)
/*ha definialva van, akkor atexit helyett objektumot hasznal*/
/*ajanlott bekapcsolni*/
#define USE_ATEXIT_OBJECT
#endif
/******************************************/
/* INNEN NE MODOSITSD */
/******************************************/
#ifdef NO_MEMTRACE_TO_FILE
#undef MEMTRACE_TO_FILE
#endif
#ifdef NO_MEMTRACE_TO_MEMORY
#undef MEMTRACE_TO_MEMORY
#endif
#ifndef MEMTRACE_AUTO
#undef USE_ATEXIT_OBJECT
#endif
#ifdef __cplusplus
#define START_NAMESPACE namespace memtrace {
#define END_NAMESPACE } /*namespace*/
#define TRACEC(func) memtrace::func
#include <new>
#else
#define START_NAMESPACE
#define END_NAMESPACE
#define TRACEC(func) func
#endif
// THROW deklarci vltozatai
#if defined(_MSC_VER)
// VS rosszul kezeli az __cplusplus makrot
#if _MSC_VER < 1900
// * nem biztos, hogy j gy *
#define THROW_BADALLOC
#define THROW_NOTHING
#else
// C++11 vagy jabb
#define THROW_BADALLOC noxcept(false)
#define THROW_NOTHING noexcept
#endif
#else
#if __cplusplus < 201103L
// C++2003 vagy rgebbi
#define THROW_BADALLOC throw (std::bad_alloc)
#define THROW_NOTHING throw ()
#else
// C++11 vagy jabb
#define THROW_BADALLOC noexcept(false)
#define THROW_NOTHING noexcept
#endif
#endif
START_NAMESPACE
int allocated_blocks();
END_NAMESPACE
#if defined(MEMTRACE_TO_MEMORY)
START_NAMESPACE
int mem_check(void);
END_NAMESPACE
#endif
#if defined(MEMTRACE_TO_MEMORY) && defined(USE_ATEXIT_OBJECT)
#include <cstdio>
START_NAMESPACE
class atexit_class {
private:
static int counter;
static int err;
public:
atexit_class() {
#if defined(CPORTA) && !defined(CPORTA_NOSETBUF)
if (counter == 0) {
setbuf(stdout, 0);
setbuf(stderr, 0);
}
#endif
counter++;
}
int check() {
if(--counter == 0)
err = mem_check();
return err;
}
~atexit_class() {
check();
}
};
static atexit_class atexit_obj;
END_NAMESPACE
#endif/*MEMTRACE_TO_MEMORY && USE_ATEXIT_OBJECT*/
/*Innentol csak a "normal" include eseten kell, kulonben osszezavarja a mukodest*/
#ifndef FROM_MEMTRACE_CPP
#include <stdlib.h>
#ifdef __cplusplus
#include <iostream>
/* ide gyjtjk a nemtrace-vel sszeakad headereket, hogy elbb legyenek */
#include <fstream> // VS 2013 headerjben van deleted definici
#include <sstream>
#include <vector>
#include <algorithm>
#endif
#ifdef MEMTRACE_CPP
namespace std {
typedef void (*new_handler)();
}
#endif
#ifdef MEMTRACE_C
START_NAMESPACE
#undef malloc
#define malloc(size) TRACEC(traced_malloc)(size,#size,__LINE__,__FILE__)
void * traced_malloc(size_t size, const char *size_txt, int line, const char * file);
#undef calloc
#define calloc(count,size) TRACEC(traced_calloc)(count, size, #count","#size,__LINE__,__FILE__)
void * traced_calloc(size_t count, size_t size, const char *size_txt, int line, const char * file);
#undef free
#define free(p) TRACEC(traced_free)(p, #p,__LINE__,__FILE__)
void traced_free(void * p, const char *size_txt, int line, const char * file);
#undef realloc
#define realloc(old,size) TRACEC(traced_realloc)(old,size,#size,__LINE__,__FILE__)
void * traced_realloc(void * old, size_t size, const char *size_txt, int line, const char * file);
void mem_dump(void const *mem, size_t size, FILE* fp);
END_NAMESPACE
#endif/*MEMTRACE_C*/
#ifdef MEMTRACE_CPP
START_NAMESPACE
#undef set_new_handler
#define set_new_handler(f) TRACEC(_set_new_handler)(f)
void _set_new_handler(std::new_handler h);
void set_delete_call(int line, const char * file);
END_NAMESPACE
void * operator new(size_t size, int line, const char * file) THROW_BADALLOC;
void * operator new[](size_t size, int line, const char * file) THROW_BADALLOC;
void * operator new(size_t size) THROW_BADALLOC;
void * operator new[](size_t size) THROW_BADALLOC;
void operator delete(void * p) THROW_NOTHING;
void operator delete[](void * p) THROW_NOTHING;
/* Visual C++ 2012 miatt kell, mert hklis, hogy nincs megfelel delete, br senki sem hasznlja */
void operator delete(void *p, int, const char *) THROW_NOTHING;
void operator delete[](void *p, int, const char *) THROW_NOTHING;
#define new new(__LINE__, __FILE__)
#define delete memtrace::set_delete_call(__LINE__, __FILE__),delete
#ifdef CPORTA
//#define system(...) // system(__VA_ARGS__)
#endif
#endif /*MEMTRACE_CPP*/
#endif /*FROM_MEMTRACE_CPP*/
#endif /*MEMCHECK*/
#endif /*MEMTRACE_H*/
/**
* \file string1.c
* (UTF-8 kodolasu fajl. Allitsa/konvertalja at a kodolast,
* ha a tovabbi kommentek nem olvashatok helyesen!)
*
* Dinamikus sztring létrehozása C-ben.
* A példa a C++ osztály fogalmának megértését készíti elő.
* Az egységesség kedvéért minden sztring paramétert pointerrel adtunk át.
* A kód kihasználja, hogy a c90-es szabványtól a free(NULL) használata legális.
*
* Figyelem:
* UTF-8 kódolásban az ékezetes betűk a memóriában több bájtot foglalnak el.
* Ha csak a kommentekben használ ékezetet, akkor nincs teendője.
* Ha adatban, konstansban is, akkor ezt külön kell kezelni.
* Ebben a feladatbab azonban ilyenre nem lesz szükség.
*/
#include <stdio.h> // Kiíratáshoz
#include <stdlib.h> // malloc miatt
#include <string.h> // Stringműveletekhez
#include <assert.h> // hibakezeléshez
/// malloc, new felüldefiniálásával készített memóriaszivárgás és konzisztencia ellenőrző
#include "memtrace.h" // a standard headerek után kell lennie
#include "string1.h" /// saját sztring header
/**
* Inicializálatlan struktúrát hoz alapállapotba
* @param s0 - pointer az adatstruktúrára (String-re)
*/
void createString(String *s0) {
s0->pData = NULL;
s0->len = 0;
}
/**
* Sztring felszabadítása
* Ha dinamikus memóriát használunk, gondoskodni kell a lefoglalt terület felszabadításról is.
* Feltételezzük, hogy csak létező (inicializált) Stringre használjuk.
* @param s0 - pointer a String-re
*/
void disposeString(String *s0) {
free(s0->pData); // felszabadítjuk
}
/**
* C sztringre konvertál, azaz visszaad egy pointert a tárolt,
* nullával lezárt sztring-re.
* Most így tárolunk, de nem feltétlen kell így tárolnunk.
* Ez az interfész (fv.) elfedi a belső tárolást.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - pointer a String-re
*/
const char* StringC_str(const String *s0) {
return s0->pData;
}
/**
* Visszaadja a sztring tényleges hosszát (lezáró nulla nélkül).
* Most így tárolunk, de nem feltétlen kell így tárolnunk.
* Ez az interfész (fv.) elfedi a belső tárolást.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - pointer a String-re
*/
unsigned int StringLen(const String *s0) {
return s0->len;
}
/**
* Kiírunk egy sztringet (debug célokra)
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - pointer a String-re
*/
void printStringDbg(const String *s0) {
printf("[%d], %s|\n", s0->len, s0->pData);
}
/**
* Sztringet készít egy karakterből
* Feltételezzük, hogy a sztring nem létezik még (pData és len inicializálatlan).
* Ha elfogy a memória, akkor assert error
* @param s0 - pointer a String-re
* @param ch - a karakter amiből elkészíti a Stringet
*/
void createStringFromChar(String *s0, char ch) {
/// Meghatározzuk a hosszát
s0->len = 1;
/// Lefoglalunk a helyet a hossznak + a lezáró nullának
s0->pData = (char*)malloc(s0->len+1);
assert(s0->pData != NULL); // nincs jobb ötletünk a hibajelzésre; (később lesz)
/// Betesszük a karaktert
s0->pData[0] = ch;
s0->pData[1] = '\0';
/// A memóriahibák figyelését tesztelendő csúnyán beleírunk a memóriába
s0->pData[-4] = '#';
}
/**
* Sztringet készít nullával lezárt karaktersorozatból (C-sztringből)
* Feltételezzük, hogy a sztring nem létezik még (pData és len inicializálatlan).
* Ha elfogy a memória, akkor assert error
* @param s0 - pointer a String-re
* @param p - pointer a C sztringre (feltételezhetjük, hogy nem NULL)
*/
void createStringFromCstr(String *s0, const char *p) {
// Meghatározzuk a hosszát
s0->len = strlen(p);
// Helyet foglalunk
s0->pData = (char*)malloc(s0->len+1);
assert(s0->pData != NULL); // nincs jobb ötletünk a hibajelzésre; (később lesz)
// Bemásoljuk a sztringet, ami le van zárva 0-val így használható az strcpy is
strcpy(s0->pData, p);
}
/**
* Stringet készít egy szringből
* Feltételezzük, hogy a sztring nem létezik még (pData és len inicializálatlan).
* Ha elfogy a memória, akkor assert error
* @param s0 - pointer a String-re
* @param s1 - pointer a másik String-re (Feltételezzük, hogy ez létezik!)
*/
void createStringFromString(String *s0, const String *s1) {
// Meghatározzuk a hosszát
s0->len = s1->len;
// Helyet foglalunk
s0->pData = (char*)malloc(s0->len+1);
assert(s0->pData != NULL); // nincs jobb ötletünk a hibajelzésre; (később lesz)
// Bemásoljuk a sztringet, ami le van zárva 0-val így használható az strcpy is
strcpy(s0->pData, s1->pData);
}
/**
* Két Sztringet fűz össze.
* Az eredményt egy harmadikba (visszatérési érték) írja.
* Feltételezzük, hogy a paraméterként megadott Stringek léteznek
* Ha elfogy a memória, akkor assert error
* @param s0 - pointer az egyik String-re
* @param s1 - pointer a másik String-re
* @return új String: A két sztring összefûzve.
*/
String addString2String(const String *s0, const String *s1) {
String res; // ide kerül az eredmény
// Meghatározza az új sztring hosszát
res.len = s0->len + s1->len;
// Helyet foglalunk
res.pData = (char*)malloc(res.len+1);
assert(res.pData != NULL); // nincs jobb ötletünk a hibajelzésre; (később lesz)
// Az elejére bemásolja az első sztringet
strcpy(res.pData, s0->pData);
// Bemásolja a második sztringet.
strcat(res.pData, s1->pData);
return res; // visszatér az eredménnyel
}
/**
* Sztring végéhez karaktert ad.
* Az eredményt egy harmadikba (visszatérési érték) írja.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* Ha elfogy a memória, akkor assert error
* @param s0 - pointer a String-re
* @param ch - a karakter amit hozzáfűz
* @return új String
*
* Ez a függvény visszavezeti a feladatot a korábbiakra.
* Ezért ezt elkészítettük, de a megvalósításba memória szivárgás
* hiba csúszott
*/
String addChar2String(const String *s0, char ch) {
String res, temp;
createStringFromChar(&temp, ch); /// char-ból sztring
res = addString2String(s0, &temp);
return res;
}
/**
* Egy megadott indexű elemmel tér vissza.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* Hibás index esetén assert error
* @param s0 - pointer a String-re
* @param idx - index
* @return idx indexű karakter
*/
char charAtString(const String *s0, unsigned int idx) {
assert(idx < s0->len);
return s0->pData[idx];
}
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="string1" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/string1" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-g" />
<Add option="-DMEMTRACE" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin/Release/string1" 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="-Wall" />
</Compiler>
<Unit filename="memtrace.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="memtrace.h" />
<Unit filename="string1.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="string1.h" />
<Unit filename="string1_main.c">
<Option compilerVar="CC" />
</Unit>
<Extensions>
<code_completion />
<debugger />
<envvars />
<DoxyBlocks>
<comment_style block="0" line="0" />
<doxyfile_project />
<doxyfile_build />
<doxyfile_warnings />
<doxyfile_output />
<doxyfile_dot />
<general />
</DoxyBlocks>
</Extensions>
</Project>
</CodeBlocks_project_file>
#ifndef STRING1_H
#define STRING1_H
/**
* \file string1.h
* (UTF-8 kodolasu fajl. Allitsa at a kodolast,
* ha a tovabbi kommentek nem olvashatok helyesen!)
*
* Dinamikus String létrehozása C-ben.
* A példa a C++ osztály fogalmának megértését készíti elő.
* Az egységesség kedvéért minden sztring paramétert pointerrel adtunk át.
* A kód kihasználja, hogy a c90-es szabványtól a free(NULL) használata legális.
*
* Figyelem:
* UTF-8 kódolásban az ékezetes betűk a memóriában több bájtot foglalnak el.
* Ha csak a kommentekben használ ékezetet, akkor nincs teendője.
* Ha adatban, konstansban is, akkor ezt külön kell kezelni.
* Ebben a feladatbab azonban ilyenre nem lesz szükség.
*/
/**
* String struktúra
* A pData által mutatott dinamikus területen vannak a karakterek (a lezáró nullával együtt).
* A len mező a tényleges hossz, amibe nem számít bele a lezáró nulla.
*/
typedef struct String {
char *pData; /// pointer az adatra
unsigned int len; /// hossz lezáró nulla nélkül
} String;
/**
* Inicializálatlan struktúrát hoz alapállapotba
* @param s0 - pointer az adatstruktúrára (String-re)
*/
void createString(String *s0);
/**
* Sztring felszabadítása
* Ha dinamikus memóriát használunk, gondoskodni kell a lefoglalt terület felszabadításról is.
* Feltételezzük, hogy csak létező (inicializált) Stringre használjuk.
* @param s0 - pointer a String-re
*/
void disposeString(String *s0);
/**
* C sztringre konvertál, azaz visszaad egy pointert a tárolt,
* nullával lezárt sztring-re.
* Most így tárolunk, de nem feltétlen kell így tárolnunk.
* Ez az interfész (fv.) elfedi a belső tárolást.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - pointer a String-re
*/
const char* StringC_str(const String *s0);
/**
* Visszaadja a sztring tényleges hosszát (lezáró nulla nélkül).
* Most így tárolunk, de nem feltétlen kell így tárolnunk.
* Ez az interfész (fv.) elfedi a belső tárolást.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - pointer a String-re
*/
unsigned int StringLen(const String *s0);
/**
* Kiírunk egy sztringet (debug célokra)
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - pointer a String-re
*/
void printStringDbg(const String *s0);
/**
* Sztringet készít egy karakterből
* Feltételezzük, hogy a sztring nem létezik még (pData és len inicializálatlan).
* Ha elfogy a memória, akkor assert error
* @param s0 - pointer a String-re
* @param ch - a karakter amiből elkészíti a Stringet
*/
void createStringFromChar(String *s0, char ch);
/**
* Sztringet készít nullával lezárt karaktersorozatból (C-sztringből)
* Feltételezzük, hogy a sztring nem létezik még (pData és len inicializálatlan).
* Ha elfogy a memória, akkor assert error
* @param s0 - pointer a String-re
* @param p - pointer a C sztringre (feltételezhetjük, hogy nem NULL)
*/
void createStringFromCstr(String *s0, const char *p);
/**
* Stringet készít egy szringből
* Feltételezzük, hogy a sztring nem létezik még (pData és len inicializálatlan).
* Ha elfogy a memória, akkor assert error
* @param s0 - pointer a String-re
* @param s1 - pointer a másik String-re (Feltételezzük, hogy ez létezik!)
*/
void createStringFromString(String *s0, const String *s1);
/**
* Két Sztringet fűz össze.
* Az eredményt egy harmadikba (visszatérési érték) írja.
* Feltételezzük, hogy a paraméterként megadott Stringek léteznek
* Ha elfogy a memória, akkor assert error
* @param s0 - pointer az egyik String-re
* @param s1 - pointer a másik String-re
* @return új String: A két sztring összefûzve.
*/
String addString2String(const String *s0, const String *s1);
/**
* Sztring végéhez karaktert ad.
* Az eredményt egy harmadikba (visszatérési érték) írja.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* Ha elfogy a memória, akkor assert error
* @param s0 - pointer a String-re
* @param ch - a karakter amit hozzáfűz
* @return új String
*
* Ez a függvény visszavezeti a feladatot a korábbiakra.
* Ezért ezt elkészítettük, de a megvalósításba memória szivárgás
* hiba csúszott
*/
String addChar2String(const String *s0, char ch);
/**
* Egy megadott indexű elemmel tér vissza.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* Hibás index esetén assert error
* @param s0 - pointer a String-re
* @param idx - index
* @return idx indexű karakter
*/
char charAtString(const String *s0, unsigned int idx);
#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>{45DA0C9C-8626-43DE-B7F0-301B612CD05A}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>strinng1</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;MEMTRACE;%(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>
<ClCompile Include="memtrace.c" />
<ClCompile Include="string1.c" />
<ClCompile Include="string1_main.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="memtrace.h" />
<ClInclude Include="string1.h" />
</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>
<ClCompile Include="memtrace.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="string1.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="string1_main.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="memtrace.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="string1.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
/**
* \file main.c
*
* (UTF-8 kodolasu fajl. Allitsa at a kodolast,
* ha a tovabbi kommentek nem olvashatok helyesen!)
*
* C nyelven létrehozott String modul kipróbálása.
* Ha jól valósította meg a modul függvényeit akkor
* A program a következő sorokat írja a standard kimenetre:
* [1], x|
* [4], alma|
* a
* [4], alma|
* [5], xalma|
* [8], almaalma|
* [6], xalmaA|
*
* Figyelem:
* UTF-8 kódolásban az ékezetes betűk a memóriában több bájtot foglalnak el.
* Ha csak a kommentekben használ ékezetet, akkor nincs teendője.
* Ha adatban, konstansban is, akkor ezt külön kell kezelni.
* Ebben a feladatbab azonban ilyenre nem lesz szükség.
*/
#include <stdio.h> /// Kiíratáshoz
/// malloc, new felüldefiniálásával készített memóriaszivárgás és konzisztencia ellenőrző
#include "memtrace.h"
#include "string1.h" /// String modulunk fejlécállománya
/**
* Egyszerű program a függvények kipróbálásához.
*/
int main() {
//
String a; createStringFromChar(&a, 'x'); /// 'a' létrehozása
printStringDbg(&a); /// Ezt kellene látni: [1], x|
//
String b; createStringFromCstr(&b, "alma"); /// 'b' létrehozása
printStringDbg(&b); /// Ezt kellene látni: [4], alma|
printf("%c\n", charAtString(&b, 3));/// Ezt kellene látni: a
//
String c; createStringFromString(&c, &b); /// 'c' létrehozása
printStringDbg(&c); /// Ezt kellene látni: [4], alma|
//
String d = addString2String(&a, &b);/// Összefűzzük a két stringet egy újba
printStringDbg(&d); /// Ezt kellene látni: [5], xalma|
String e = addString2String(&b, &c);
printStringDbg(&e); /// Ezt kellene látni: [8], almaalma|
//
disposeString(&e); /// e-t másra akarjuk használni, felszabadítjuk
e = addChar2String(&d, 'A'); /// Ezt kellene látni: [6], xalmaA|
printStringDbg(&e);
//
disposeString(&e);
disposeString(&d);
disposeString(&c);
disposeString(&b);
disposeString(&a);
return 0;
}
#
# Makefile pelda a string1 feladat (2. labor) megoldasanak forditasara
# gnumake valtozat
# Linuxokon es ural2-n is elerheto
#
# A make paranccsorabol magadott CMD valtozo tartalma atadodik a forditonak
# Pl:
# make CMD=-DMEMTRACE
#
PROG = string1_cpp # a program neve (ezt allitjuk elo)
PROG_O = string1.o string1_main.o # program object fajljai
PROG_H = string1.h # program header fajljai
PROG_L = # program libjei
MTRACE_O = memtrace.o # memtrace object fajl
MTRACE_H = memtrace.h # memtrace header fajlja
CXX = g++ # a C fordito neve
#CXX = clang++ # clang-ot (llvm) is erdemes kiprobalni
CXXFLAGS = -pedantic -Wall # kapcsolok: legyen bobeszedu es pedans
CXXFLAGS += -g # es legyeb debug info is
CXXFLAGS += $(CMD) # es amit a parancsorbol megadnak
LDFLAGS = -g # debug a linkelesnel
# osszes object, osszes header osszes lib
OBJS = $(PROG_O) $(MTRACE_O)
HEADS = $(PROG_H) $(MTRACE_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)
# takaritas igeny szerint
.PHONY: clean
clean:
rm -f $(OBJS) $(PROG)
/*********************************
Memoriaszivargas-detektor
Keszitette: Peregi Tamas, BME IIT, 2011
petamas@iit.bme.hu
Kanari: Szeberenyi Imre, 2013.,
VS 2012: Szebernyi Imre, 2015.,
mem_dump: 2016.
inclue-ok: 2017., 2018.
*********************************/
#ifndef MEMTRACE_H
#define MEMTRACE_H
#if defined(MEMTRACE)
/*ha definilva van, akkor a hibakat ebbe a fajlba rja, egybkent stderr-re*/
/*#define MEMTRACE_ERRFILE MEMTRACE.ERR*/
/*ha definialva van, akkor futas kozben lancolt listat epit. Javasolt a hasznalata*/
#define MEMTRACE_TO_MEMORY
/*ha definialva van, akkor futas kozben fajlba irja a foglalasokat*/
/*ekkor nincs ellenorzes, csak naplozas*/
/*#define MEMTRACE_TO_FILE*/
/*ha definialva van, akkor a megallaskor automatikus riport keszul */
#define MEMTRACE_AUTO
/*ha definialva van, akkor malloc()/calloc()/realloc()/free() kovetve lesz*/
#define MEMTRACE_C
#ifdef MEMTRACE_C
/*ha definialva van, akkor free(NULL) nem okoz hibat*/
#define ALLOW_FREE_NULL
#endif
#ifdef __cplusplus
/*ha definialva van, akkor new/delete/new[]/delete[] kovetve lesz*/
#define MEMTRACE_CPP
#endif
#if defined(__cplusplus) && defined(MEMTRACE_TO_MEMORY)
/*ha definialva van, akkor atexit helyett objektumot hasznal*/
/*ajanlott bekapcsolni*/
#define USE_ATEXIT_OBJECT
#endif
/******************************************/
/* INNEN NE MODOSITSD */
/******************************************/
#ifdef NO_MEMTRACE_TO_FILE
#undef MEMTRACE_TO_FILE
#endif
#ifdef NO_MEMTRACE_TO_MEMORY
#undef MEMTRACE_TO_MEMORY
#endif
#ifndef MEMTRACE_AUTO
#undef USE_ATEXIT_OBJECT
#endif
#ifdef __cplusplus
#define START_NAMESPACE namespace memtrace {
#define END_NAMESPACE } /*namespace*/
#define TRACEC(func) memtrace::func
#include <new>
#else
#define START_NAMESPACE
#define END_NAMESPACE
#define TRACEC(func) func
#endif
// THROW deklarci vltozatai
#if defined(_MSC_VER)
// VS rosszul kezeli az __cplusplus makrot
#if _MSC_VER < 1900
// * nem biztos, hogy j gy *
#define THROW_BADALLOC
#define THROW_NOTHING
#else
// C++11 vagy jabb
#define THROW_BADALLOC noxcept(false)
#define THROW_NOTHING noexcept
#endif
#else
#if __cplusplus < 201103L
// C++2003 vagy rgebbi
#define THROW_BADALLOC throw (std::bad_alloc)
#define THROW_NOTHING throw ()
#else
// C++11 vagy jabb
#define THROW_BADALLOC noexcept(false)
#define THROW_NOTHING noexcept
#endif
#endif
START_NAMESPACE
int allocated_blocks();
END_NAMESPACE
#if defined(MEMTRACE_TO_MEMORY)
START_NAMESPACE
int mem_check(void);
END_NAMESPACE
#endif
#if defined(MEMTRACE_TO_MEMORY) && defined(USE_ATEXIT_OBJECT)
#include <cstdio>
START_NAMESPACE
class atexit_class {
private:
static int counter;
static int err;
public:
atexit_class() {
#if defined(CPORTA) && !defined(CPORTA_NOSETBUF)
if (counter == 0) {
setbuf(stdout, 0);
setbuf(stderr, 0);
}
#endif
counter++;
}
int check() {
if(--counter == 0)
err = mem_check();
return err;
}
~atexit_class() {
check();
}
};
static atexit_class atexit_obj;
END_NAMESPACE
#endif/*MEMTRACE_TO_MEMORY && USE_ATEXIT_OBJECT*/
/*Innentol csak a "normal" include eseten kell, kulonben osszezavarja a mukodest*/
#ifndef FROM_MEMTRACE_CPP
#include <stdlib.h>
#ifdef __cplusplus
#include <iostream>
/* ide gyjtjk a nemtrace-vel sszeakad headereket, hogy elbb legyenek */
#include <fstream> // VS 2013 headerjben van deleted definici
#include <sstream>
#include <vector>
#include <algorithm>
#endif
#ifdef MEMTRACE_CPP
namespace std {
typedef void (*new_handler)();
}
#endif
#ifdef MEMTRACE_C
START_NAMESPACE
#undef malloc
#define malloc(size) TRACEC(traced_malloc)(size,#size,__LINE__,__FILE__)
void * traced_malloc(size_t size, const char *size_txt, int line, const char * file);
#undef calloc
#define calloc(count,size) TRACEC(traced_calloc)(count, size, #count","#size,__LINE__,__FILE__)
void * traced_calloc(size_t count, size_t size, const char *size_txt, int line, const char * file);
#undef free
#define free(p) TRACEC(traced_free)(p, #p,__LINE__,__FILE__)
void traced_free(void * p, const char *size_txt, int line, const char * file);
#undef realloc
#define realloc(old,size) TRACEC(traced_realloc)(old,size,#size,__LINE__,__FILE__)
void * traced_realloc(void * old, size_t size, const char *size_txt, int line, const char * file);
void mem_dump(void const *mem, size_t size, FILE* fp);
END_NAMESPACE
#endif/*MEMTRACE_C*/
#ifdef MEMTRACE_CPP
START_NAMESPACE
#undef set_new_handler
#define set_new_handler(f) TRACEC(_set_new_handler)(f)
void _set_new_handler(std::new_handler h);
void set_delete_call(int line, const char * file);
END_NAMESPACE
void * operator new(size_t size, int line, const char * file) THROW_BADALLOC;
void * operator new[](size_t size, int line, const char * file) THROW_BADALLOC;
void * operator new(size_t size) THROW_BADALLOC;
void * operator new[](size_t size) THROW_BADALLOC;
void operator delete(void * p) THROW_NOTHING;
void operator delete[](void * p) THROW_NOTHING;
/* Visual C++ 2012 miatt kell, mert hklis, hogy nincs megfelel delete, br senki sem hasznlja */
void operator delete(void *p, int, const char *) THROW_NOTHING;
void operator delete[](void *p, int, const char *) THROW_NOTHING;
#define new new(__LINE__, __FILE__)
#define delete memtrace::set_delete_call(__LINE__, __FILE__),delete
#ifdef CPORTA
//#define system(...) // system(__VA_ARGS__)
#endif
#endif /*MEMTRACE_CPP*/
#endif /*FROM_MEMTRACE_CPP*/
#endif /*MEMCHECK*/
#endif /*MEMTRACE_H*/
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="string2_cpp" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/string2_test" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-g" />
<Add option="-DMEMTRACE" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin/Release/string2_test" 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="-Wall" />
<Add option="-DMEMTRACE" />
</Compiler>
<Unit filename="gtest_lite.h" />
<Unit filename="memtrace.cpp" />
<Unit filename="memtrace.h" />
<Unit filename="string2.cpp" />
<Unit filename="string2.h" />
<Unit filename="string2_main.cpp" />
<Extensions>
<code_completion />
<debugger />
<envvars />
</Extensions>
</Project>
</CodeBlocks_project_file>
/**
* \file string2.cpp
* (UTF-8 kodolasu fajl. Allitsa/konvertalja at a kodolast,
* ha a tovabbi kommentek nem olvashatok helyesen!)
*
* Dinamikus String létrehozása C-ben.
* A példa a C++ osztály fogalmának megértését készíti elő.
* Az egységesség kedvéért minden String paramétert referenciaként adtunk át.
*
* FELADAT:
* Valósítsa meg a hiányzó függvényeket C++ nyelven!
* (2 db createString, charAtString, és 2 db addString)
* A függvények prototípusát a fájl végére másoltuk sring2.h fáljból
* A megvalósítást segíti a C nyelvű változat (string1.c).
*/
#include <iostream> // Kiíratáshoz
#include <cstring> // Stringműveletekhez
#include "string2.h"
/// malloc, new felüldefiniálásával készített memóriaszivárgás és konzisztencia ellenőrző
#include "memtrace.h" // a standard headerek után kell lennie
#include "string2.h" /// saját sztring header
using std::cout;
using std::endl;
/**
* Inicializálatlan struktúrát hoz alapállapotba
* @param s0 - referencia az adatstruktúrára (String-re)
*/
void createString(String &s0) {
s0.pData = NULL;
s0.len = 0;
}
/**
* Sztring felszabadítása
* Ha dinamikus memóriát használunk, gondoskodni kell a lefoglalt terület felszabadításról is.
* Feltételezzük, hogy csak létező (inicializált) String-re használjuk.
* @param s0 - referencia a String-re
*/
void disposeString(String& s0) {
delete[] s0.pData; // felszabadítjuk
}
/**
* C sztringre konvertál, azaz visszaad egy pointert a tárolt,
* nullával lezárt sztring-re.
* Most így tárolunk, de nem feltétlen kell így tárolnunk.
* Ez az interfész (fv.) elfedi a belső tárolást.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - referencia a String-re
*/
const char* StringC_str(const String &s0) {
return s0.pData;
}
/**
* Visszaadja a sztring tényleges hosszát (lezáró nulla nélkül).
* Most így tárolunk, de nem feltétlen kell így tárolnunk.
* Ez az interfész (fv.) elfedi a belső tárolást.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - referencia a String-re
*/
unsigned int StringLen(const String &s0) {
return s0.len;
}
/**
* Kiírunk egy sztringet (debug célokra)
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - referencia a String-re
*/
void printStringDbg(const String &s0) {
#ifdef DEBUG
cout << '[' << s0.len << "], " << s0.pData << '|' << endl;
#endif
}
/**
* Stringet készít egy karakterből
* Feltételezzük, hogy a sztring nem létezik még (pData és len inicializálatlan).
* @param s0 - referencia a String-re
* @param ch - a karakter amiből elkészíti a Stringet
*/
void createString(String& s0, char ch) {
/// Meghatározzuk a hosszát
s0.len = 1;
/// Lefoglalunk a helyet a hossznak + a lezáró nullának
s0.pData = new char[s0.len+1];
/// Betesszük a karaktert
s0.pData[0] = ch;
s0.pData[1] = '\0';
}
// Az alábbi függvényeket kell megvalósítania.
// Alakítsa át a deklarációkat definíciókká!
/**
* SZringet készít nullával lezárt karaktersorozatból (C-sztringből)
* Feltételezzük, hogy a String nem létezik még (pData és len inicializálatlan).
* @param s0 - referencia a String-re
* @param p - pointer a C sztringre (feltételezhetjük, hogy nem NULL)
*/
void createString(String& s0, const char *p);
/**
* Stringet készít egy sztringből
* Feltételezzük, hogy a sztring nem létezik még (pData és len inicializálatlan).
* @param s0 - referencia a String-re
* @param s1 - referencia a másik String-re (Feltételezzük, hogy ez létezik!)
*/
void createString(String& s0, const String& s1);
/**
* Egy megadott indexű elemmel tér vissza.
* Feltételezzük, hogy a paraméterként megadott String létezik
* Hibás index esetén const char* kivételt dob-
* @param s0 - referencia a String-re
* @param idx - index
* @return idx indexű karakter
*/
char charAtString(const String& s0, unsigned int idx);
/**
* Két sztringet összefűz.
* Az eredményt egy harmadikba (visszatérési érték) írja.
* Feltételezzük, hogy a paraméterként megadott String-ek léteznek
* @param s0 - referencia az egyik String-re
* @param s1 - referencia a másik String-re
* @return új String: A két sztring összefûzve.
*/
String addString(const String& s0, const String& s1);
/**
* String végéhez karaktert ad.
* Az eredményt egy harmadikba (visszatérési érték) írja.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - referencia a String-re
* @param ch - a karakter amit hozzáfűz
* @return új String
*/
String addString(const String& s0, char ch);
#ifndef STRING1_H
#define STRING1_H
/**
* \file string2.h
* (UTF-8 kodolasu fajl. Allitsa/konvertalja at a kodolast,
* ha a tovabbi kommentek nem olvashatok helyesen!)
*
*
* Dinamikus String létrehozása C++-ban.
* A példa a C++ osztály fogalmának megértését készíti elő.
*
* A C nyelvű megoldáshoz képesti változtatások:
* 1. Kihasználjuk, hogy a struktúra név típussá változott.
* 2. Kihasználjuk a fv túlterhelés (oveload) lehetőségét, így az azonos
* funkciójú függvényeknek azonos a neve (createString, addString)
* 3. A String paramétereket pointer helyett referenciával adjuk át.
* 4. C++ memóriakezelését használjuk.
* 5. Hibás indexelést kivétellel jelezzük
*
*/
#define ELKESZULT 0 /// értékeit l. alább
/**
* Az ELKESZULT makró értékét annak megfelelően állítsa
* 0,1,2,3,4 vagy 5 értékűre, hogy hol tart a feladat megoldásában!
* Ha folyamatosan halad, akkor a kód mindig fordítható és futtatható lesz.
* Így az egyes részek a teljes feladat befejezése nélkül is kipróbálhatók.
*
* ELKESZULT lehetséges értékei:
* 0 - Nem egészített ki egyetlen hiányos függvényt sem.
* 1 - Elkészítette a createString(String&, const char*) függvényt.
* 2 - Elkészítette a createString(String&, const String&) függvényt.
* 3 - Elkészítette a charAtString(const String& s0, unsigned int idx) függvényt
* 4 - Elkészítette az addString(cont String&, char) függvényt.
* 5 ELkészítette az addString(const String&, const String& b) függvényt
*/
/**
* String struktúra
* A pData által mutatott dinamikus területen vannak a karakterek (a lezáró nullával együtt).
* A len mező a tényleges hossz, amibe nem számít bele a lezáró nulla.
*/
struct String {
char *pData; /// pointer az adatra
unsigned int len; /// hossz lezáró nulla nélkül
};
/**
* Inicializálatlan struktúrát hoz alapállapotba
* @param s0 - referencia az adatstruktúrára (String-re)
*/
void createString(String &s0);
/**
* Sztring felszabadítása
* Ha dinamikus memóriát használunk, gondoskodni kell a lefoglalt terület felszabadításról is.
* Feltételezzük, hogy csak létező (inicializált) String-re használjuk.
* @param s0 - referencia a String-re
*/
void disposeString(String& s0);
/**
* C sztringre konvertál, azaz visszaad egy pointert a tárolt,
* nullával lezárt sztring-re.
* Most így tárolunk, de nem feltétlen kell így tárolnunk.
* Ez az interfész (fv.) elfedi a belső tárolást.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - referencia a String-re
*/
const char* StringC_str(const String &s0);
/**
* Visszaadja a sztring tényleges hosszát (lezáró nulla nélkül).
* Most így tárolunk, de nem feltétlen kell így tárolnunk.
* Ez az interfész (fv.) elfedi a belső tárolást.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - referencia a String-re
*/
unsigned int StringLen(const String &s0);
/**
* Kiírunk egy sztringet (debug célokra)
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - referencia a String-re
*/
void printStringDbg(const String &s0);
/**
* Stringet készít egy karakterből
* Feltételezzük, hogy a sztring nem létezik még (pData és len inicializálatlan).
* @param s0 - referencia a String-re
* @param ch - a karakter amiből elkészíti a Stringet
*/
void createString(String &s0, char ch);
/**
* SZringet készít nullával lezárt karaktersorozatból (C-sztringből)
* Feltételezzük, hogy a String nem létezik még (pData és len inicializálatlan).
* @param s0 - referencia a String-re
* @param p - pointer a C sztringre (feltételezhetjük, hogy nem NULL)
*/
void createString(String& s0, const char *p);
/**
* Stringet készít egy sztringből
* Feltételezzük, hogy a sztring nem létezik még (pData és len inicializálatlan).
* @param s0 - referencia a String-re
* @param s1 - referencia a másik String-re (Feltételezzük, hogy ez létezik!)
*/
void createString(String& s0, const String& s1);
/**
* Egy megadott indexű elemmel tér vissza.
* Feltételezzük, hogy a paraméterként megadott String létezik
* Hibás index esetén const char* kivételt dob-
* @param s0 - referencia a String-re
* @param idx - index
* @return idx indexű karakter
*/
char charAtString(const String& s0, unsigned int idx);
/**
* Két sztringet összefűz.
* Az eredményt egy harmadikba (visszatérési érték) írja.
* Feltételezzük, hogy a paraméterként megadott String-ek léteznek
* @param s0 - referencia az egyik String-re
* @param s1 - referencia a másik String-re
* @return új String: A két sztring összefûzve.
*/
String addString(const String& s0, const String& s1);
/**
* String végéhez karaktert ad.
* Az eredményt egy harmadikba (visszatérési érték) írja.
* Feltételezzük, hogy a paraméterként megadott sztring létezik
* @param s0 - referencia a String-re
* @param ch - a karakter amit hozzáfűz
* @return új String
*/
String addString(const String& s0, char ch);
#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>{45DA0C9C-8626-43DE-B7F0-301B612CD05A}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>strinng1</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;MEMTRACE;%(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="memtrace.h" />
<ClInclude Include="string1.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="memtrace.cpp" />
<ClCompile Include="string1.cpp" />
<ClCompile Include="string1_main.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="memtrace.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="string1.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="memtrace.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="string1.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="string1_main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
/**
* \file string2_main.cpp
* (UTF-8 kodolasu fajl. Allitsa at a kodolast,
* ha a tovabbi kommentek nem olvashatok helyesen!)
*
* C++ nyelvre átírt dinamikus String működését teszteli.
*
* Ha a javasolt sorrendben oldja meg a feladatot, akkor lépésről-lépésre
* tesztelheti az elkészített függvényeket. Ehhez a string1.h fájlban definiált
* ELKESZULT makró értékét kell megfelelően változtatni.
*
* A C verzióval ellentétben nem csak szemrevételezéssel ellenőrizzük az egyes
* függvények helyességét, hanem a gtest_lite EXPECT_... makróival is.
*
* C változatnál látott szöveges kiírások akkor látszanak, ha a DEBUG azonosító definiált.
*
* Figyelem:
* UTF-8 kódolásban az ékezetes betűk a memóriában több bájtot foglalnak el.
* Ha csak a kommentekben használ ékezetet, akkor nincs teendője.
* Ha adatban, konstansban is, akkor ezt külön kell kezelni.
* Ebben a feladatbab azonban ilyenre nem lesz szükség.
*/
/**
*
* A példa a dinamikus memória használatánál előforduló hibákat
* a labor útmutatóban ismertetett memtrace módszerrel ellenőrzi.
*
* Az ellenőrzés aktivizálásához minden fájl elején definiálni kell
* a MEMTRACE makrót. Ezt célszerű fordítási opcióként megadni.
* (ld. a labor útmutatójában)
*/
#include <cstring> /// Stringműveletekhez
/// malloc, new felüldefiniálásával készített memóriaszivárgás és konzisztencia ellenőrző
#include "memtrace.h" /// a standard headerek után kell lennie
#include "gtest_lite.h"
#include "string2.h"
using std::cout;
using std::endl;
int main() {
TEST(String1, Inic) {
String a; createString(a);
EXPECT_EQ(0u, StringLen(a));
EXPECT_EQ((char const*)(NULL), StringC_str(a));
} END
String a; createString(a, 'x'); /// 'a' létrehozása
TEST(String1, FromChar) {
EXPECT_EQ(1u, StringLen(a));
EXPECT_STREQ("x", StringC_str(a));
printStringDbg(a); /// Ezt kellene látni: [1], x|
} END
// Ha létezik a createString(String&, const char*) függvény.
#if ELKESZULT >= 1
String b; createString(b, "alma"); /// 'b' létrehozása
TEST(String1, FromCstr) {
EXPECT_EQ(4, StringLen(b));
EXPECT_STREQ("alma", StringC_str(b));
printStringDbg(b); /// Ezt kellene látni: [4], alma|
} END
#endif
// Ha létezik a createString(String&, const String&) függvény.
#if ELKESZULT >= 2
String c; createString(c, b); /// 'c' létrehozása
TEST(String1, FromStr) {
EXPECT_EQ(4, StringLen(b));
EXPECT_STREQ("alma", StringC_str(b));
printStringDbg(b); /// Ezt kellene látni: [4], alma|
} END
#endif
// Ha létezik a charAtString(const String& s0, unsigned int idx) függvény.
#if ELKESZULT >= 3
TEST(String1, CharAt3) {
char ch;
EXPECT_NO_THROW(ch = charAtString(b, 3));
EXPECT_EQ('a', ch);
#ifdef DEBUG
cout << charAtString(b, 3) << endl; /// Ezt kellene látni: a
#endif
} END
TEST(String1, CharAt4) {
EXPECT_THROW(charAtString(b, 4), const char*);
} END
TEST(String1, CharAt_1) {
EXPECT_THROW(charAtString(b, -1), const char*);
} END
#endif
// Ha létezik az addString(cont String&, char) függvény.
#if ELKESZULT >= 4
String d = addString(a, b); /// Összefűzzük a két stringet egy újba
TEST(String1, AddStr2Str1) {
EXPECT_EQ(5, StringLen(d));
EXPECT_STREQ("xalma", StringC_str(d));
printStringDbg(d); /// Ezt kellene látni: [5], xalma|
} END
#endif
// Ha létezik az addString(const String&, const String& b) függvény.
#if ELKESZULT >= 5
String e = addString(b, c);
TEST(String1, AddStr2Str2) {
EXPECT_EQ(8, StringLen(e));
EXPECT_STREQ("almaalma", StringC_str(e));
printStringDbg(e); /// Ezt kellene látni: [8], almaalma|
} END
//
disposeString(e); /// e-t másra akarjuk használni, felszabadítjuk
e = addString(d, 'A');
TEST(String1, AddStr2Str2) {
EXPECT_EQ(6, StringLen(e));
EXPECT_STREQ("xalmaA", StringC_str(e));
printStringDbg(e); /// Ezt kellene látni: [6], xalmaA|
} END
#endif
// Attól függően, hogy mi keletkezett, fel is kell azokat szabadítani
#if ELKESZULT >= 5
disposeString(e);
#endif
#if ELKESZULT >= 4
disposeString(d);
#endif
#if ELKESZULT >= 2
disposeString(c);
#endif
#if ELKESZULT >= 1
disposeString(b);
#endif
disposeString(a);
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