Dzień dobry, chciałbym prosić o ocenę kodu.
Klasa ma dwie metody publiczne:
1. doesItHaveOnlyLettersDigitsDollarsAndUnderscores sprawdza, czy słowo spełnia wymagania algorytmu.
2. makeShorter skraca podane słowo do maksymalnej długości według poniższego algorytmu:
napisz nazwę zmiennej w postaci, w której życzyłbyś sobie ją widzieć – używaj tylko liter, cyfr oraz znaków '_' (podkreślenie) i '$' (dolar); może zabrzmi to dziwnie, ale znak '$' traktować będziemy jak literę (czyni to do dzisiaj wiele kompilatorów);
jeśli długość nazwy jest mniejsza bądź równa n, możesz jej użyć i nie musisz robić nic więcej
w przeciwnym wypadku usuwaj z nazwy, począwszy od końca, wszystkie znaki, które nie są literami i cyframi – w chwili, w której długość nazwy osiągnie n, możesz zakończyć pracę i użyć nazwy zmiennej
jeśli długość nazwy nadal jest większa od n, usuwaj z niej, począwszy od końca, kolejne cyfry - w chwili, w której długość nazwy osiągnie n możesz zakończyć pracę i użyć nazwy zmiennej
jeśli długość nazwy nadal jest większa od n, usuwaj z niej, począwszy od początku, kolejne samogłoski z wyjątkiem pierwszej (chodzi o to, by w nazwie została chociaż jedna samogłoska, o ile jakakolwiek została użyta) - w chwili, w której długość nazwy osiągnie n, możesz zakończyć pracę i użyć nazwy zmiennej
jeśli długość nazwy nadal jest większa od n, usuwaj z niej znaki od końca, począwszy od przedostatniego - w chwili, w której długość nazwy osiągnie n, możesz zakończyć pracę i użyć nazwy zmiennej
Do testów jednostkowych wykorzystany został CppUnitTest. Assert::AreEqual(expected, actual).
WordShortenerTest.cpp
#include "CppUnitTest.h"
#include "../WordShortener/WordShortener.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace UnitTest {
TEST_CLASS(WordShortenerTest)
{
public:
TEST_METHOD(testForCorrectData)
{
WordShortener ws;
Assert::IsTrue(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("ABCDEFGHIJKLMNOPRSTUVWXYZabcdefghijklmnoprstuvwxyz1234567890_$"));
}
TEST_METHOD(testForIncorrectData)
{
WordShortener ws;
//Control characters
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("\a"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("\b"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("\t"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("\n"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("\v"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("\f"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("\r"));
//Punctuation characters
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("\""));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("\'"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("\\"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("\?"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("!"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores(" "));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores(","));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("."));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores(":"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores(";"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("-"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("("));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores(")"));
//Other characters
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("+"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("*"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("/"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("="));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores(">"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("<"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("#"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("%"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("`"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("|"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("~"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("{"));
Assert::IsFalse(ws.doesItHaveOnlyLettersDigitsDollarsAndUnderscores("}"));
}
TEST_METHOD(testForWordSizeLowerThanSpecifiedMaxSize)
{
WordShortener ws;
Assert::AreEqual(std::string("ABC"), ws.makeShorter("ABC", 5));
}
TEST_METHOD(testForWordSizeEqualToSpecifiedMaxSize)
{
WordShortener ws;
Assert::AreEqual(std::string("ABC"), ws.makeShorter("ABC", 3));
}
TEST_METHOD(testForWordWithTooManyUnderscores)
{
WordShortener ws;
Assert::AreEqual(std::string("ABC"), ws.makeShorter("___A___B___C___", 3));
Assert::AreEqual(std::string("___A_BC"), ws.makeShorter("___A___B___C___", 7));
}
TEST_METHOD(testForWordWithTooManyDigits)
{
WordShortener ws;
Assert::AreEqual(std::string("ABC"), ws.makeShorter("123A456B789C0", 3));
Assert::AreEqual(std::string("123A45BC"), ws.makeShorter("123A456B789C0", 8));
}
TEST_METHOD(testForWordWithTooManyVowels)
{
WordShortener ws;
Assert::AreEqual(std::string("ABBBBUB"), ws.makeShorter("ABEBIBOBUB", 7));
Assert::AreEqual(std::string("abbbbub"), ws.makeShorter("abebibobub", 7));
}
TEST_METHOD(testForWordWithTooManyConsonants)
{
WordShortener ws;
Assert::AreEqual(std::string("BCDFZ"), ws.makeShorter("BCDFGHJKLMNPQRSTVWXYZ", 5));
Assert::AreEqual(std::string("bcdfz"), ws.makeShorter("bcdfghjklmnpqrstvwxyz", 5));
}
TEST_METHOD(testForWordWithTooManyDollars)
{
WordShortener ws;
Assert::AreEqual(std::string("$B$CF"), ws.makeShorter("$B$C$D$F", 5));
Assert::AreEqual(std::string("B$C$$"), ws.makeShorter("B$C$D$F$", 5));
}
};
}
WordShortener.h
#pragma once
#include <string>
class WordShortener {
public:
bool doesItHaveOnlyLettersDigitsDollarsAndUnderscores(const std::string& word) const;
std::string makeShorter(const std::string& word, const std::size_t& maxSize) const;
private:
void deleteUnderscores(std::string& source, const size_t& maxSize) const;
void deleteDigits(std::string& source, const size_t& maxSize) const;
void deleteVowelsWithoutFirst(std::string& shortenedWord, const size_t& maxSize) const;
void deleteCharactersWithoutLast(std::string& source, const size_t& maxSize) const;
bool isDollar(char character) const { return character == '$'; }
bool isUnderscore(char character) const { return character == '_'; }
bool isVowel(char character) const;
};
WordShortener.cpp
#include "WordShortener.h"
#include <cctype>
bool WordShortener::doesItHaveOnlyLettersDigitsDollarsAndUnderscores(const std::string& word) const
{
for (char character : word)
if (!isalnum(character) && !isDollar(character) && !isUnderscore(character))
return false;
return true;
}
std::string WordShortener::makeShorter(const std::string& word, const std::size_t& maxSize) const
{
if (word.size() <= maxSize)
return word;
std::string shortenedWord(word);
deleteUnderscores(shortenedWord, maxSize);
if (shortenedWord.size() <= maxSize)
return shortenedWord;
deleteDigits(shortenedWord, maxSize);
if (shortenedWord.size() <= maxSize)
return shortenedWord;
deleteVowelsWithoutFirst(shortenedWord, maxSize);
if (shortenedWord.size() <= maxSize)
return shortenedWord;
deleteCharactersWithoutLast(shortenedWord, maxSize);
return shortenedWord;
}
void WordShortener::deleteUnderscores(std::string& source, const size_t& maxSize) const
{
for (std::size_t i = source.size() - 1; i > 0 && source.size() > maxSize; i--)
if (isUnderscore(source[i]))
source.erase(i, 1);
if (source.size() > maxSize && isUnderscore(source.front()))
source.erase(0, 1);
}
void WordShortener::deleteDigits(std::string& source, const size_t& maxSize) const
{
for (std::size_t i = source.size() - 1; i > 0 && source.size() > maxSize; i--)
if (isdigit(source[i]))
source.erase(i, 1);
if (source.size() > maxSize && isdigit(source.front()))
source.erase(0, 1);
}
void WordShortener::deleteVowelsWithoutFirst(std::string& shortenedWord, const size_t& maxSize) const
{
bool firstVowel = true;
for (std::size_t i = 0; i < shortenedWord.size() && shortenedWord.size() > maxSize; i++) {
if (isVowel(shortenedWord[i]) && firstVowel)
firstVowel = false;
else if (isVowel(shortenedWord[i]))
shortenedWord.erase(i, 1);
}
}
void WordShortener::deleteCharactersWithoutLast(std::string& source, const size_t& maxSize) const
{
for (std::size_t i = source.size() - 2; i > 0 && source.size() > maxSize; i--)
source.erase(i, 1);
if (source.size() > maxSize)
source.erase(0, 1);
}
bool WordShortener::isVowel(char character) const
{
char lower = tolower(character);
switch (lower) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
return true;
default:
return false;
}
}