Dzień dobry, chciałbym prosić o ocenę kodu.
Program ma za zadanie pobrać od użytkownika maksymalną długość słowa oraz słowo. Następnie skrócić 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
Github:
https://github.com/huberti1/NameShortener.git
Kod źródłowy:
#include <iostream>
#include <string>
struct Name
{
std::string name;
int sizeMaximum = 0;
};
int getTestsResult();
bool testNameSizeLowerThenMaximumSize();
bool testNameSizeEquelMaximumSize();
bool testTooManyAllOthers();
bool testTooManyPartOthers();
bool testTooManyAllDigits();
bool testTooManyPartDigits();
bool testTooManyAllVowels();
bool testTooManyPartVowels();
bool testTooManyAllWithoutVowel();
bool testTooManyAll();
Name setupShortener();
std::string shortenToSizeMaximum(Name name);
bool isSizeMaximumExceeded(const Name & name);
std::string excludeUnnecessaryOthers(const Name & name);
int calculateAmountNecessaryOthers(const Name & name);
int calculateAmountWithoutOthers(const Name & name);
bool isOther(char source);
bool isDollar(char source);
std::string excludeUnnecessaryDigits(const Name & name);
int calculateAmountNecessaryDigits(const Name & name);
int calculateAmountWithoutDigits(const Name & name);
bool isThereAnyVowel(const Name & name);
bool isVowel(char source);
std::string excludeUnnecessaryVowelsStartFromSecoundVowel(const Name & name);
std::string getEverythingToFirstVowelInclusive(const Name & name);
std::string getEverythingFromOneAfterFirstVowelExcludingUnnecessaryVowels(const Name & name);
size_t getFirstVowelIndex(const Name & name);
int calculateAmountNotLeavingVowels(const Name & name);
std::string excludeFromOneBehindLast(const Name & name);
void show(const Name & name);
int main()
{
return getTestsResult();
Name name = setupShortener();
name.name = shortenToSizeMaximum(name);
show(name);
return 0;
}
Name setupShortener()
{
Name name;
std::cin >> name.sizeMaximum;
std::cin.get();
getline(std::cin, name.name);
return name;
}
std::string shortenToSizeMaximum(Name name)//transfer by value give a transformation look
{
if (isSizeMaximumExceeded(name))
{
name.name = excludeUnnecessaryOthers(name);
if (isSizeMaximumExceeded(name))
{
name.name = excludeUnnecessaryDigits(name);
if (isSizeMaximumExceeded(name))
{
name.name = excludeUnnecessaryVowelsStartFromSecoundVowel(name);
if (isSizeMaximumExceeded(name))
name.name = excludeFromOneBehindLast(name);
}
}
}
return name.name;
}
bool isSizeMaximumExceeded(const Name & name)
{
return name.name.size() > name.sizeMaximum;
}
std::string excludeUnnecessaryOthers(const Name & name)
{
std::string destination;
int amountNecessaryOthers = calculateAmountNecessaryOthers(name);
for (size_t i = 0; i < name.name.size(); i++)
{
if(!isOther(name.name[i]))
destination += name.name[i];
else if (amountNecessaryOthers > 0)
{
destination += name.name[i];
amountNecessaryOthers--;
}
}
return destination;
}
int calculateAmountNecessaryOthers(const Name & name)
{
int amountNecessaryOthers = name.sizeMaximum - calculateAmountWithoutOthers(name);
return amountNecessaryOthers;
}
int calculateAmountWithoutOthers(const Name & name)
{
int amountWithoutOthers = 0;
for (size_t i = 0; i < name.name.size(); i++)
if (!isOther(name.name[i]))
amountWithoutOthers++;
return amountWithoutOthers;
}
bool isOther(char source)
{
return !isalnum(source) && !isDollar(source);
}
bool isDollar(char source)
{
return source == '$';
}
std::string excludeUnnecessaryDigits(const Name & name)
{
std::string destination;
int amountNecessaryDigits = calculateAmountNecessaryDigits(name);
for (unsigned i = 0; i < name.name.size(); i++)
{
if(!isdigit(name.name[i]))
destination += name.name[i];
else if (amountNecessaryDigits > 0)
{
destination += name.name[i];
amountNecessaryDigits--;
}
}
return destination;
}
int calculateAmountNecessaryDigits(const Name & name)
{
int amountNecessaryDigits = name.sizeMaximum - calculateAmountWithoutDigits(name);
return amountNecessaryDigits;
}
int calculateAmountWithoutDigits(const Name & name)
{
int amountWithoutDigits = 0;
for (size_t i = 0; i < name.name.size(); i++)
if (!isdigit(name.name[i]))
amountWithoutDigits++;
return amountWithoutDigits;
}
std::string excludeUnnecessaryVowelsStartFromSecoundVowel(const Name & name)
{
if (isThereAnyVowel(name))
return getEverythingToFirstVowelInclusive(name) + getEverythingFromOneAfterFirstVowelExcludingUnnecessaryVowels(name);
else
return name.name;
}
bool isThereAnyVowel(const Name & name)
{
for (size_t i = 0; i < name.name.size(); i++)
if (isVowel(name.name[i]))
return true;
return false;
}
std::string getEverythingToFirstVowelInclusive(const Name & name)
{
std::string destination;
size_t firstVowelIndex = getFirstVowelIndex(name);
for (size_t i = 0; i <= firstVowelIndex; i++)
destination += name.name[i];
return destination;
}
std::string getEverythingFromOneAfterFirstVowelExcludingUnnecessaryVowels(const Name & name)
{
std::string destination;
int amountNotLeavingVowels = calculateAmountNotLeavingVowels(name);
const size_t oneAfterFirstVowel = getFirstVowelIndex(name) + 1;
for (size_t i = oneAfterFirstVowel; i < name.name.size(); i++)
{
if (!isVowel(name.name[i]))
destination += name.name[i];
else if (amountNotLeavingVowels > 0)
amountNotLeavingVowels--;
else
destination += name.name[i];
}
return destination;
}
int calculateAmountNotLeavingVowels(const Name & name)
{
return name.name.size() - name.sizeMaximum;
}
size_t getFirstVowelIndex(const Name & name)
{
size_t i = 0;
while (!isVowel(name.name[i]))
i++;
return i;
}
bool isVowel(char source)
{
return source == 'a' || source == 'e' || source == 'i' || source == 'o' ||
source == 'u' || source == 'y' || source == 'A' || source == 'E' ||
source == 'I' || source == 'O' || source == 'U' || source == 'Y';
}
std::string excludeFromOneBehindLast(const Name & name)
{
std::string destination;
int amountLeavingCharactersWithoutLast = name.sizeMaximum - 1;
for (int i = 0; amountLeavingCharactersWithoutLast > 0; i++)
{
destination += name.name[i];
amountLeavingCharactersWithoutLast--;
}
destination += name.name.back();
return destination;
}
void show(const Name & name)
{
std::cout << name.name << std::endl;
}
int getTestsResult()
{
if (!testNameSizeLowerThenMaximumSize())
return 1;
if (!testNameSizeEquelMaximumSize())
return 2;
if (!testTooManyAllOthers())
return 3;
if (!testTooManyPartOthers())
return 4;
if (!testTooManyAllDigits())
return 5;
if (!testTooManyPartDigits())
return 6;
if (!testTooManyAllVowels())
return 7;
if (!testTooManyPartVowels())
return 8;
if (!testTooManyAllWithoutVowel())
return 9;
if (!testTooManyAll())
return 10;
return 0;
}
bool testNameSizeLowerThenMaximumSize()
{
Name name{ "AB$ 1", 6 };
std::string expected = "AB$ 1";
name.name = shortenToSizeMaximum(name);
return name.name == expected;
}
bool testNameSizeEquelMaximumSize()
{
Name name{ "AB$ 1", 5 };
std::string expected = "AB$ 1";
name.name = shortenToSizeMaximum(name);
return name.name == expected;
}
bool testTooManyAllOthers()
{
Name name{ "A_ B$1", 4 };
std::string expected = "AB$1";
name.name = shortenToSizeMaximum(name);
return name.name == expected;
}
bool testTooManyPartOthers()
{
Name name{ "A_ __ _B$1", 6 };
std::string expected = "A_ B$1";
name.name = shortenToSizeMaximum(name);
return name.name == expected;
}
bool testTooManyAllDigits()
{
Name name{ "A1B$123456789", 3 };
std::string expected = "AB$";
name.name = shortenToSizeMaximum(name);
return name.name == expected;
}
bool testTooManyPartDigits()
{
Name name{ "3A123B456$789", 4 };
std::string expected = "3AB$";
name.name = shortenToSizeMaximum(name);
return name.name == expected;
}
bool testTooManyAllVowels()
{
Name name{ "AAEIOUY$aeioDuy", 3 };
std::string expected = "A$D";
name.name = shortenToSizeMaximum(name);
return name.name == expected;
}
bool testTooManyPartVowels()
{
Name name{ "A$aeiouyBAEIOUY", 5 };
std::string expected = "A$BUY";
name.name = shortenToSizeMaximum(name);
return name.name == expected;
}
bool testTooManyAllWithoutVowel()
{
Name name{ "B$BE", 3 };
std::string expected = "B$E";
name.name = shortenToSizeMaximum(name);
return name.name == expected;
}
bool testTooManyAll()
{
Name name{ "B$ACB", 4 };
std::string expected = "B$AB";
name.name = shortenToSizeMaximum(name);
return name.name == expected;
}