most tests are done

This commit is contained in:
Damimani 2026-11-06 11:36:52 +01:00
parent a72fa4c5a1
commit 938e557caa
6 changed files with 360 additions and 74 deletions

View file

@ -1,6 +1,8 @@
// Tóth Dániel Mátyás | IFPQYY | v1 // Tóth Dániel Mátyás | IFPQYY | v1
#include "pch.h" #include "pch.h"
#include "CppUnitTest.h" #include "CppUnitTest.h"
#include <CMyString.h>
#include <CMyStringException.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Microsoft::VisualStudio::CppUnitTestFramework;
@ -9,9 +11,304 @@ namespace UnitTest1
TEST_CLASS(UnitTest1) TEST_CLASS(UnitTest1)
{ {
public: public:
TEST_METHOD(EmptyTests)
TEST_METHOD(TestMethod1)
{ {
CMyString empty = CMyString();
Assert::AreEqual(0, (int)empty.size());
Assert::AreEqual(1, (int)empty.capacity());
Assert::IsTrue(empty.empty());
}
TEST_METHOD(c_strTests)
{
try
{
char* tmp = "txt";
CMyString str = CMyString((const char*)tmp);
Assert::IsFalse(tmp == str.c_str()); //memory addr
Assert::AreEqual(tmp, str.c_str()); //value
}
catch (...)
{
Assert::IsTrue(false);
}
}
TEST_METHOD(StringConstructionTests)
{
//char* constructor
char* pszargs[] = {
{nullptr},
{""},
{"test"},
{"long text aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
};
int pszres[] = {
0,
0,
4,
48,
};
int testcount = sizeof(pszres) / sizeof(int);
for (size_t i = 0; i < testcount; i++)
{
try
{
CMyString pszctor = CMyString(pszargs[i]);
Assert::AreEqual(pszres[i], (int)pszctor.size());
Assert::AreEqual((pszres[i]) + 1, (int)pszctor.capacity());
if (pszargs[i] != nullptr)
{
Assert::AreEqual(pszargs[i], pszctor.c_str());
}
}
catch (...)
{
Assert::IsTrue(false);
}
}
//repeat constructor
char repeatchargs[] = {
'\0',
'\0',
'a',
'a',
};
int repeatcntargs[] = {
0,
5,
0,
5,
};
int repeatres[] = {
0,
0,
0,
5,
};
char* repeattextres[] = {
nullptr,
nullptr,
nullptr,
"aaaaa",
};
testcount = sizeof(repeatres) / sizeof(int);
for (size_t i = 0; i < testcount; i++)
{
try
{
CMyString repeatctor = CMyString(repeatchargs[i], repeatcntargs[i]);
Assert::AreEqual(repeatres[i], (int)repeatctor.size());
Assert::AreEqual((repeatres[i]) + 1, (int)repeatctor.capacity());
if (repeattextres[i] != nullptr)
{
Assert::AreEqual(repeattextres[i], repeatctor.c_str());
}
}
catch (...)
{
Assert::IsTrue(false);
}
}
//copy constructor
CMyString strargs[] = {
CMyString(),
CMyString("test"),
CMyString('a', 10),
CMyString("really long text thats to be cleared"),
};
strargs[3].clear();
int strres[] = {
0,
4,
10,
0,
};
int allocLengths[] = {
1,
5,
11,
1,
};
char* cpytextres[] = {
"",
"test",
"aaaaaaaaaa",
"",
};
testcount = sizeof(strres) / sizeof(int);
for (size_t i = 0; i < testcount; i++)
{
try
{
CMyString cpy = CMyString(strargs[i]);
CMyString strctor = CMyString(cpy);
Assert::AreEqual(strres[i], (int)strctor.size());
Assert::AreEqual((allocLengths[i]), (int)strctor.capacity());
Assert::AreEqual(cpytextres[i], strctor.c_str());
}
catch (...)
{
Assert::IsTrue(false);
}
}
}
TEST_METHOD(ClearTests) {
CMyString str[]{
CMyString(),
CMyString("test"),
CMyString('a', 10),
CMyString(CMyString("to be copied then cleared")),
};
int allocLengths[] = {
1,
5,
11,
26,
};
int testcount = sizeof(allocLengths) / sizeof(int);
for (size_t i = 0; i < testcount; i++)
{
try
{
str[i].clear();
Assert::IsTrue(str[i].empty());
Assert::AreEqual(allocLengths[i], (int)str[i].capacity());
}
catch (...)
{
Assert::IsTrue(false);
}
}
}
TEST_METHOD(GetAtTests) {
CMyString str[]{
CMyString(),
CMyString(),
CMyString("test"),
CMyString("test"),
CMyString("test"),
CMyString('a', 10),
CMyString(CMyString("to be copied then cleared")),
};
int pos[] = {
1,
0,
4,
-1,
1,
9,
12,
};
char character[] = {
'\0',
'\0',
'\0',
'\0', //first four are invalid
'e',
'a',
' ',
};
int testcount = sizeof(pos) / sizeof(int);
for (size_t i = 0; i < testcount; i++)
{
try
{
Assert::AreEqual(character[i], str[i].getat(pos[i]));
}
catch(const CMyStringException& e)
{
if (i < 4)
{
Assert::AreEqual(CMyStringException::ErrOutOfRange, e.what());
}
else
{
Assert::IsTrue(false);
}
}
catch (...)
{
Assert::IsTrue(false);
}
}
}
TEST_METHOD(SetAtTests) {
CMyString str[]{
CMyString(),
CMyString("test"),
CMyString("test"),
CMyString('a', 10),
};
int pos[] = {
0,
4,
-1,
3,
};
char* text[] = {
'\0',
'\0',
'\0', //first three are invalid
"aaataaaaaa",
};
int testcount = sizeof(pos) / sizeof(int);
for (size_t i = 0; i < testcount; i++)
{
try
{
str[i].setat(pos[i], 't');
Assert::AreEqual(text[i], str[i].c_str());
}
catch (const CMyStringException& e)
{
if (i < 3)
{
Assert::AreEqual(CMyStringException::ErrOutOfRange, e.what());
}
else
{
Assert::IsTrue(false);
}
}
catch (...)
{
Assert::IsTrue(false);
}
}
}
TEST_METHOD(ReserveTests) {
int allocs[] = {
1,
5,
10,
33,
};
int testcount = sizeof(allocs) / sizeof(int);
for (size_t i = 0; i < testcount; i++)
{
try
{
CMyString str = CMyString("test");
str.reserve(allocs[i]);
Assert::AreEqual(allocs[i], (int)str.capacity());
}
catch (const CMyStringException& e)
{
Assert::AreEqual(CMyStringException::ErrOutOfRange, e.what());
}
}
}
TEST_METHOD(EraseTests) {
//TODO
} }
}; };
} }

View file

@ -144,7 +144,7 @@
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>C:\Users\danit\Desktop\2026-27-cpp-homework\feladat5\feladat5\x64\Debug;$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>C:\Users\danit\Desktop\2026-27-cpp-homework\feladat5\feladat5\x64\Debug;$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>CMyString;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CMyString;CMyStringException;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

View file

@ -6,7 +6,7 @@
static int strLength(const char* str) { static int strLength(const char* str) {
if (str == nullptr) if (str == nullptr)
{ {
return 0; return -1;
} }
int cnt = 0; int cnt = 0;
while (str[cnt]) while (str[cnt])
@ -16,9 +16,10 @@ static int strLength(const char* str) {
return cnt; return cnt;
} }
static void CopyStr(char* dest, const char* src, size_t length) { static void CopyStr(char* dest, const char* src, size_t length) {
if (dest == nullptr || src == nullptr) { if (dest == nullptr || src == nullptr) {
throw new bad_exception; return;
} }
size_t i; size_t i;
for (i = 0; i < length; i++) for (i = 0; i < length; i++)
@ -28,68 +29,69 @@ static void CopyStr(char* dest, const char* src, size_t length) {
dest[i] = '\0'; dest[i] = '\0';
} }
static void MakeEmptyStr(size_t* datalngth, size_t* alloclngth, char** ptr) {
*datalngth = 0;
*alloclngth = 1;
*ptr = new char[1];
(*ptr)[0] = '\0';
}
CMyString::CMyString() { CMyString::CMyString() {
m_nDataLength = 0; MakeEmptyStr(&m_nDataLength, &m_nAllocLength, &m_pchData);
m_nAllocLength = 1;
m_pchData = new char[m_nAllocLength];
m_pchData[0] = '\0';
} }
CMyString::CMyString(const char* psz) { CMyString::CMyString(const char* psz) {
m_nDataLength = 0;
if (psz == nullptr) if (psz == nullptr)
{ {
m_nAllocLength = 1; MakeEmptyStr(&m_nDataLength, &m_nAllocLength, &m_pchData);
} }
else else
{ {
m_nDataLength = 0;
while (psz[m_nDataLength]) while (psz[m_nDataLength])
{ {
m_nDataLength++; m_nDataLength++;
} }
m_nAllocLength = m_nDataLength + 1; m_nAllocLength = m_nDataLength + 1;
m_pchData = new char[m_nAllocLength];
CopyStr(m_pchData, psz, m_nDataLength);
} }
m_pchData = new char[m_nAllocLength];
CopyStr(m_pchData, psz, m_nDataLength);
} }
CMyString::CMyString(char ch, size_t repeat) { CMyString::CMyString(char ch, size_t repeat) {
if (ch == '\0') if (ch == '\0' || repeat == 0)
{ {
m_nDataLength = 0; MakeEmptyStr(&m_nDataLength, &m_nAllocLength, &m_pchData);
m_nAllocLength = 1;
} }
else else
{ {
m_nDataLength = repeat; m_nDataLength = 0;
m_nAllocLength = repeat + 1; m_nAllocLength = repeat + 1;
m_pchData = new char[m_nAllocLength];
while (m_nDataLength < repeat)
{
m_pchData[m_nDataLength++] = ch;
}
m_pchData[m_nAllocLength-1] = '\0';
} }
m_pchData = new char[m_nAllocLength];
int i = 0;
while (i < m_nDataLength)
{
m_pchData[i] = ch;
i++;
}
m_pchData[i] = '\0';
} }
CMyString::CMyString(const CMyString& str) { CMyString::CMyString(const CMyString& str) {
if (str.empty()) if (str.empty())
{ {
m_nDataLength = 0; MakeEmptyStr(&m_nDataLength, &m_nAllocLength, &m_pchData);
} }
else else
{ {
m_nDataLength = str.size(); m_nDataLength = str.size();
m_nAllocLength = m_nDataLength + 1;
m_pchData = new char[m_nAllocLength];
int i = 0;
const char* cont = str.c_str();
while (cont[i])
{
m_pchData[i] = cont[i];
i++;
}
m_pchData[m_nDataLength] = '\0';
} }
m_nAllocLength = m_nDataLength + 1;
m_pchData = new char[m_nAllocLength];
int i = 0;
const char* cont = str.c_str();
while (cont[i]) // will never be a nullptr
{
m_pchData[i] = cont[i];
i++;
}
m_pchData[i] = '\0'; //i will never go over nAllocLength
} }
CMyString::~CMyString() { CMyString::~CMyString() {
delete m_pchData; delete m_pchData;
@ -98,7 +100,7 @@ size_t CMyString::size() const {
return m_nDataLength; return m_nDataLength;
} }
size_t CMyString::capacity() const { size_t CMyString::capacity() const {
return m_nDataLength; return m_nAllocLength;
} }
const char* CMyString::c_str() const { const char* CMyString::c_str() const {
return m_pchData; return m_pchData;
@ -110,35 +112,36 @@ void CMyString::clear() {
char CMyString::getat(size_t index) const { char CMyString::getat(size_t index) const {
if (index >= m_nDataLength) if (index >= m_nDataLength)
{ {
throw new CMyStringException(CMyStringException::ErrOutOfRange); throw CMyStringException(CMyStringException::ErrOutOfRange);
} }
return m_pchData[index]; return m_pchData[index];
} }
void CMyString::setat(size_t index, char ch) { void CMyString::setat(size_t index, char ch) {
if (index >= m_nDataLength) if (index >= m_nDataLength)
{ {
throw new CMyStringException(CMyStringException::ErrOutOfRange); throw CMyStringException(CMyStringException::ErrOutOfRange);
} }
if (ch == '\0') if (ch == '\0')
{ {
throw new CMyStringException(CMyStringException::ErrInvalidChar); throw CMyStringException(CMyStringException::ErrInvalidChar);
} }
m_pchData[index] = ch; m_pchData[index] = ch;
} }
void CMyString::reserve(size_t newcapacity) { void CMyString::reserve(size_t newcapacity) {
if (newcapacity < m_nAllocLength) if (newcapacity < m_nAllocLength)
{ {
throw new CMyStringException(CMyStringException::ErrUnexpected); throw CMyStringException(CMyStringException::ErrOutOfRange);
} }
char* tmp = m_pchData; char* tmp = m_pchData;
m_pchData = new char[newcapacity]; m_nAllocLength = newcapacity;
m_pchData = new char[m_nAllocLength];
CopyStr(m_pchData, tmp, m_nDataLength); CopyStr(m_pchData, tmp, m_nDataLength);
delete tmp; delete tmp;
} }
void CMyString::erase(size_t pos, size_t count) { void CMyString::erase(size_t pos, size_t count) {
if (pos >= m_nDataLength) if (pos >= m_nDataLength)
{ {
throw new CMyStringException(CMyStringException::ErrOutOfRange); throw CMyStringException(CMyStringException::ErrOutOfRange);
} }
if (pos + count > m_nDataLength) if (pos + count > m_nDataLength)
{ {
@ -160,17 +163,14 @@ void CMyString::display() const {
} }
void CMyString::shrink_to_fill() { void CMyString::shrink_to_fill() {
m_nAllocLength = m_nDataLength + 1; m_nAllocLength = m_nDataLength + 1;
char* tmp = m_pchData; this->reserve(m_nAllocLength);
m_pchData = new char[m_nAllocLength];
CopyStr(m_pchData, tmp, m_nDataLength);
delete tmp;
} }
void CMyString::reverse() { void CMyString::reverse() {
if (!empty()) if (!empty())
{ {
for (size_t i = 0; i < m_nDataLength / 2; i++) for (size_t i = 0; i < m_nDataLength / 2; i++)
{ {
int j = m_nDataLength - i - 1; size_t j = m_nDataLength - i - 1;
char tmp = m_pchData[i]; char tmp = m_pchData[i];
m_pchData[i] = m_pchData[j]; m_pchData[i] = m_pchData[j];
m_pchData[j] = tmp; m_pchData[j] = tmp;
@ -182,25 +182,21 @@ void CMyString::append(const char* psz, unsigned offset, unsigned count) {
{ {
return; return;
} }
int len = strLength(psz); size_t len = strLength(psz);
if (count == ~0) if (count == ~0)
{ {
count = len; count = (int)len;
} }
if (len < (count - offset)) if (len < (int)(count - offset))
{ {
throw new CMyStringException(CMyStringException::ErrOutOfRange); throw CMyStringException(CMyStringException::ErrOutOfRange);
} }
if (count + m_nDataLength > m_nAllocLength) if (count + m_nDataLength > m_nAllocLength)
{ {
char* tmp = m_pchData; this->reserve((m_nAllocLength + count)*2);
m_nAllocLength = (count + m_nDataLength) * 2;
m_pchData = new char[m_nAllocLength];
CopyStr(m_pchData, tmp, m_nDataLength);
delete tmp;
} }
int i = m_nDataLength; size_t i = m_nDataLength;
int j = offset; size_t j = offset;
while (j < count) while (j < count)
{ {
m_pchData[i++] = psz[j++]; m_pchData[i++] = psz[j++];
@ -209,27 +205,20 @@ void CMyString::append(const char* psz, unsigned offset, unsigned count) {
m_pchData[i] = '\0'; m_pchData[i] = '\0';
} }
CMyString& CMyString::operator=(const CMyString& str) { CMyString& CMyString::operator=(const CMyString& str) {
if (m_pchData != str.c_str()) if (this != &str)
{ {
if (!str.empty()) if (!str.empty())
{ {
if (str.capacity() > m_nAllocLength) if (str.size() >= m_nAllocLength)
{ {
m_nAllocLength = str.capacity(); this->reserve(str.capacity() * 2);
char* cpy = m_pchData;
m_pchData = new char[m_nAllocLength];
delete cpy;
} }
CopyStr(m_pchData, str.c_str(), m_nDataLength);
m_nDataLength = str.size(); m_nDataLength = str.size();
CopyStr(m_pchData, str.c_str(), m_nDataLength);
} }
else else
{ {
m_nDataLength = 0; MakeEmptyStr(&m_nDataLength, &m_nAllocLength, &m_pchData);
m_nAllocLength = 1;
delete m_pchData;
m_pchData = new char[m_nAllocLength];
m_pchData[0] = '\0';
} }
} }
return *this; return *this;

View file

@ -1,6 +1,6 @@
// Tóth Dániel Mátyás | IFPQYY | v1 // Tóth Dániel Mátyás | IFPQYY | v1
#pragma once #pragma once
class CMyString { // memóriát kétszeresére növeld amikor növelni kell gyerek class CMyString {
public: public:
CMyString(); CMyString();
CMyString(const char* psz); CMyString(const char* psz);

View file

@ -31,6 +31,6 @@ CMyStringException::CMyStringException(const char* input) {
msg = unique_ptr<char[]>(new char[len+1]); msg = unique_ptr<char[]>(new char[len+1]);
CopyStr(msg.get(), input, len); CopyStr(msg.get(), input, len);
} }
const char* CMyStringException::what() { const char* CMyStringException::what() const {
return msg.get(); return msg.get();
} }

View file

@ -5,7 +5,7 @@ using namespace std;
class CMyStringException { class CMyStringException {
public: public:
CMyStringException(const char* input); CMyStringException(const char* input);
const char* what(void); const char* what(void) const;
static constexpr const char* ErrOutOfRange = "Hiba: index hiba!"; static constexpr const char* ErrOutOfRange = "Hiba: index hiba!";
static constexpr const char* ErrInvalidChar = "Hiba: érvénytelen karakter!"; static constexpr const char* ErrInvalidChar = "Hiba: érvénytelen karakter!";
static constexpr const char* ErrCount = "Hiba: karakterek száma 0!"; static constexpr const char* ErrCount = "Hiba: karakterek száma 0!";