Expert Answer
#include <iostream>
#include <string>
#include <cassert>
#include <cctype>
using namespace std;
//Declares methods to prevent compilation errors
bool hasWord(string text);
string getFirstWord(string text);
string getLastWord(string text);
string extractWord(string& text);
bool isUppercase(string text);
string makeUppercase(string text);
bool hasMultipleExclamations(string text);
bool isGibberishWord(string text);
void doUnitTests();
int main()
{
//Turns unit testing on or off
const bool unitTesting = false;
if(unitTesting)
{
doUnitTests();
return 0;
}
const double SUBJECT_UPPER_THRESHOLD = 90;
const int SUBJECT_UPPER_SPAM_SCORE_INCREASE = 30;
const int SUBJECT_GIBBERISH_SPAM_SCORE_INCREASE = 40;
const int SUBJECT_EXCLAMATION_SPAM_SCORE_INCREASE = 20;
const int BODY_SPECIAL_WORD_SPAM_SCORE_INCRASE = 5;
const double BODY_UPPER_THRESHOLD = 50;
const int BODY_MINIMUM_WORD_COUNT = 1;
const int BODY_UPPER_SPAM_SCORE_INCREASE = 40;
const int SPAM_SCORE_THRESHOLD = 100;
//Initialize counters for spam and legitimate e-mails
int spamCounter = 0;
int legitCounter = 0;
//Tracks if the spam program should be repeated
bool repeat = true;
while(repeat)
{
//Takes in the subject line
cout << “Enter the subject line of the email: “;
string s;
getline(cin,s);
const string subject = s;
//Takes in the body of the e-mail and puts it all into one string (n placed after input to account for getline function removing n)
cout << “Enter the body of the email. Press Enter on an empty line to finish.” << endl;
string b = “”;
string t = “”;
do
{
getline(cin,t);
b += (t + “n”);
}while(t!=””);
const string body = b;
//Subject and body input complete
/*cerr << “Subject: ” << subject << endl;*/
int spamScore = 0;
double sWordCount = 0;
double sUpperCount = 0;
//Holds the remainder of subject after extractWord function is invoked
string remainingSubject = subject;
//Holds the returned value of function extractWord
string sWord = extractWord(remainingSubject);
//Calculates number of words and uppercase words in subject
while(sWord!=””)
{
sWordCount++;
if(isUppercase(sWord))
{
sUpperCount++;
}
sWord = extractWord(remainingSubject);
}
//Calculates percentage of uppercase words in subject, changing spamScore as needed
double sPercentUpper = 0;
if(sWordCount>=1)
sPercentUpper = 100 * (sUpperCount / sWordCount);
if(sPercentUpper > SUBJECT_UPPER_THRESHOLD)
{
spamScore += SUBJECT_UPPER_SPAM_SCORE_INCREASE;
}
/*cerr << “Spam score (subject upper check): ” << spamScore << endl;*/
//Changes spamScore as needed for gibberish word rule
if(isGibberishWord(getLastWord(subject)))
{
spamScore += SUBJECT_GIBBERISH_SPAM_SCORE_INCREASE;
}
/*cerr << “Spam score (subject gibberish check): ” << spamScore << endl;*/
//Changes spamScore as needed for exclamation rule
if(hasMultipleExclamations(subject))
{
spamScore += SUBJECT_EXCLAMATION_SPAM_SCORE_INCREASE;
}
/*cerr << “Spam score (subject exclamation check): ” << spamScore << endl;
//Output for accuracy
cerr << “Number of words: ” << sWordCount << endl;
cerr << “Number of upper: ” << sUpperCount << endl;
cerr << “Percent of upper: ” << sPercentUpper << endl;
cerr << “Spam score (subject line checks): ” << spamScore << endl <<endl;
//Outputs body for readability
cerr << “Body: ” << body << endl;*/
double bWordCount = 0;
double bUpperCount = 0;
//Holds remainder of the string after extractWord function is invoked
string remainingBody = body;
//Holds the results of extractWord on remainingBody string
string bWord = extractWord(remainingBody);
//Counts number of words and number of uppercase words
while(bWord!=””)
{
bWordCount++;
if(isUppercase(bWord))
{
bUpperCount++;
}
//Detects presence of special spam words and changes spamScore as needed
string ss = makeUppercase(bWord);
if(ss==”BUY” || ss==”CHEAP” || ss==”CLICK” || ss==”DIPLOMA”
|| ss==”ENLARGE” || ss==”FREE” || ss==”LONELY” || ss==”MONEY”
|| ss==”NOW” || ss==”OFFER” || ss==”ONLY” || ss==”PILLS” || ss==”SEX”)
{
spamScore += BODY_SPECIAL_WORD_SPAM_SCORE_INCRASE;
}
bWord = extractWord(remainingBody);
}
/*cerr << “Spam score (body word check): ” << spamScore << endl;*/
//Calculates percent of uppercase words if the body has at least 1 word
//Changes the spamScore accordingly
double bPercentUpper = 0;
if(bWordCount>=BODY_MINIMUM_WORD_COUNT)
{
bPercentUpper = 100 * (bUpperCount / bWordCount);
if(bPercentUpper > BODY_UPPER_THRESHOLD)
{
spamScore += BODY_UPPER_SPAM_SCORE_INCREASE;
}
}
//Outputs for accuracy
/*cerr << “Spam score (body upper check): ” << spamScore << endl;
cerr << “Number of words: ” << bWordCount << endl;
cerr << “Number of upper: ” << bUpperCount << endl;
cerr << “Percent of upper: ” << bPercentUpper << endl;
cerr << “Spam score(total): ” << spamScore << endl;*/
//Categorizes the message based upon the spamScore
if(spamScore>SPAM_SCORE_THRESHOLD)
{
cout << “This email is classified as spam, because its spam score is ” << spamScore << “.” << endl;
spamCounter++;
}
else
{
cout << “This email is classified as legitimate, because its spam score is ” << spamScore << “.” << endl;
legitCounter++;
}
//Detects whether the user wants to use the program for another message
bool validResponse = false;
while(!validResponse)
{
cout << “Would you like to classify another email (y or n)? “;
string response = “”;
getline(cin,response);
if(response==”y”)
{
//The user has input a valid response, ending this while loop
//boolean repeat is still true, leading to another iteration of the program
validResponse = true;
}
else if(response==”n”)
{
cout << endl;
cout << “Number of spam messages: ” << spamCounter << endl;
cout << “Number of legitimate messages: ” << legitCounter << endl;
//User has input a valid response ending this while loop
//The program will not repeat
validResponse = true;
repeat = false;
}
else
{
//The user has failed to input a valid response
//validResponse is still false and the loop repeats
cout << “Please enter y or n.” << endl;
}
}
}
}
//Checks to see if the string text has a word (series of contiguous letters)
//Returns true if there is a word
bool hasWord(string text)
{
for(size_t i=0; i<text.size(); i++)
{
if(isalpha(text[i]))
{
return true;
}
}
return false;
}
//Returns the first word in the string text
//If there is no word, the function returns an empty string
string getFirstWord(string text)
{
if(!hasWord(text))
{
return “”;
}
//Removes all non-letters before first letter in the string
for(size_t i=0; i<text.size(); i++)
{
if(isalpha(text[i]))
{
text = text.substr(i,text.size()-i);
i = text.size();
}
}
//Adds letters to string s until a non-letter is reached
string s = “”;
for(size_t j = 0; j<text.size(); j++)
{
if(isalpha(text[j]))
{
s += text[j];
}
else
{
j = text.size();
}
}
return s;
}
//Returns the last word in string text
//If there is no word, returns an empty string
string getLastWord(string text)
{
if(!hasWord(text))
{
return “”;
}
//Removes all non-letters after the last letter in the string
size_t i = text.size();
do
{
i–;
if(isalpha(text[i]))
{
text = text.substr(0,i+1);
i = 0;
}
}while(i>0);
//Puts letters from text into the string “reversed” from the end of the string until the first non-letter character
//Characters are in reversed order
i = text.size();
string reversed = “”;
do
{
i–;
if(isalpha(text[i]))
{
reversed += text[i];
}
else
{
i = 0;
}
}while(i>0);
//Takes the reversed string and puts the characters into string “forward” in the correct order
i = reversed.size();
string forward = “”;
do
{
i–;
forward += reversed[i];
}while(i>0);
return forward;
}
//Returns the first word in string text
//All characters before and including the first word are removed from string text
string extractWord(string& text)
{
//If there is no word in text, text is set to the empty string and an empty string is returned
if(!hasWord(text))
{
text = “”;
return “”;
}
string firstWord = getFirstWord(text);
for(size_t i = 0; i<text.size(); i++)
{
//When the text substring is the same as the firstWord string
if(text.substr(i,firstWord.size())==firstWord)
{
//The text string becomes equal to the substring beginning one position after the firstWord string until the end of the string.
text = text.substr(i+firstWord.size(), text.size() – (i+firstWord.size()) );
i = text.size();
}
}
return firstWord;
}
//Checks to see if all letters in string text are uppercase
//Returns true if all letters are uppercase
bool isUppercase(string text)
{
for(size_t i = 0; i < text.size(); i++)
{
if(isalpha(text[i]) && islower(text[i]))
{
return false;
}
}
return true;
}
//Returns string text with all lowercase letters converted to their respective uppercase letters
string makeUppercase(string text)
{
for(size_t i=0; i<text.size(); i++)
{
text[i] = toupper(text[i]);
}
return text;
}
//Returns true if string text has “!!!”
bool hasMultipleExclamations(string text)
{
const int MULTIPLE_EXCLAMATION_THRESHOLD = 3;
if(text.size()<MULTIPLE_EXCLAMATION_THRESHOLD)
{
return false;
}
string exclam = “”;
for(int j = 0; j<MULTIPLE_EXCLAMATION_THRESHOLD; j++)
{
exclam += “!”;
}
for(size_t i = 0; i<text.size()-MULTIPLE_EXCLAMATION_THRESHOLD+1; i++)
{
if(text.substr(i,MULTIPLE_EXCLAMATION_THRESHOLD)==exclam)
{
return true;
}
}
return false;
}
//Returns false if char a is a letter or a vowel
bool isConsonant(char a)
{
char b = tolower(a);
if( !isalpha(b) || (b==’a’||b==’e’||b==’i’||b==’o’||b==’u’) )
{
return false;
}
return true;
}
//Returns true if text contains 4 consonants in a row
bool isGibberishWord(string text)
{
const double GIBBERISH_THRESHOLD = 4;
if(text.size()<GIBBERISH_THRESHOLD)
{
return false;
}
for(size_t i=0; i<text.size()-GIBBERISH_THRESHOLD+1; i++)
{
bool allConsonant = true; //Resets to true after each iteration
for(size_t j=0; j<GIBBERISH_THRESHOLD; j++)
{
if(!isConsonant(text[i+j])) //If there is never a non-consonant, allConsonant remains true and the function returns true
{
allConsonant = false;
}
}
if(allConsonant)
{
return true;
}
}
return false;
}
//Used to test individual functions
void doUnitTests()
{
//assert(boolean expression);
//if the expression is true -> program continues to run
//if the expression is false -> program writes diagnostic message of text and location of failure
assert(!hasWord(” “));
assert(hasWord(“h”));
assert(hasWord(“h ell o”));
assert(!hasWord(“9 84 57348″));
assert(hasWord(” h h”));
assert(!hasWord(” 9 5 45 42″));
assert(!hasWord(” ^%&*^ (*& (*& (* ^*^ %& $”));
assert(getFirstWord(“”)==””);
assert(getFirstWord(“k”)==”k”);
assert(getFirstWord(“h4r “)==”h”);
assert(getFirstWord(“hello”)==”hello”);
assert(getFirstWord(“hello hello”)==”hello”);
assert(getFirstWord(“@#!#!%#%hello”)==”hello”);
assert(getFirstWord(“2348723648@!$#@!$#!hello, bob”)==”hello”);
assert(getFirstWord(” 8768#hello, bob”)==”hello”);
assert(getFirstWord(“876987698768324762984763298467 hello kjhfa8937492837&(*^*%^$^467 “)==”hello”);
assert(getFirstWord(“898798 465 4658″)==””);
assert(getFirstWord(“3498537happy98347923874*&^%#&%#& 8&^*&^* 768762384 876idaskufh 87″)==”happy”);
assert(getFirstWord(” t 209837492 jfdkjsah 8 9823yiuhkg hgiu87236r8iegfhjh”)==”t”);
assert(getFirstWord(“9″)==””);
assert(getLastWord(“h4r”)==”r”);
assert(getLastWord(“h”)==”h”);
assert(getLastWord(“Hello”)==”Hello”);
assert(getLastWord(“Hello Hello”)==”Hello”);
assert(getLastWord(“Happy Sad”)==”Sad”);
assert(getLastWord(“93279324879kjashdkfjh983279482743h”)==”h”);
assert(getLastWord(“eioau84t984u98u49uooiaodhfakjdsbnfiauwe4ygiauwhvjksdbflkajhewfoaihgf9328y92u938247298392yfjh”)==”yfjh”);
assert(getLastWord(“APPLE!!!!”)==”APPLE”);
assert(getLastWord(“(*&^*&&*^*^*876842376823746836742876*&^*&^*768aaa98237492837(*&&^(^&^%&*^%*&%786868 876876 6%&5″)==”aaa”);
assert(getLastWord(“”)==””);
assert(getLastWord(“9″)==””);
assert(getLastWord(“MAKE MONEY FAST!!!”)==”FAST”);
assert(getLastWord(“MAKE MONEY FAST!!!”)!=” FAST”);
string test = “9834793847589734”;
assert(extractWord(test)==””);
assert(test==””);
test = “*&^*^*^*98374923798379*&^$^%^%98794 98734 8397 &^%&5 98 (*&( 657″;
assert(extractWord(test)==””);
assert(test==””);
test = “hello”;
assert(extractWord(test)==”hello”);
assert(test==””);
test = ” hello “;
assert(extractWord(test)==”hello”);
assert(test==” “);
test = “239847932(*&(*&765happy birthd ay98734(*&”;
assert(extractWord(test)==”happy”);
assert(test==” birthd ay98734(*&”);
test = “QTYHY564dg”;
assert(extractWord(test)==”QTYHY”);
assert(test==”564dg”);
test = “hello hello”;
assert(extractWord(test)==”hello”);
assert(test==” hello”);
string s = “***AMAZING!*** Do it, now!!”;
string w = extractWord(s);
assert(w==”AMAZING”);
assert(s==”!*** Do it, now!!”);
w = extractWord(s);
assert(w==”Do”);
assert(s==” it, now!!”);
w = extractWord(s);
assert(w==”it”);
assert(s==”, now!!”);
w = extractWord(s);
assert(w==”now”);
assert(s==”!!”);
w = extractWord(s);
assert(w==””);
assert(s==””);
s=”happy birthday”;
w = extractWord(s);
assert(w!=”happy “);
assert(s!=”happy birthday”);
assert(isUppercase(“”));
assert(isUppercase(” “));
assert(isUppercase(“LKSDFJLSDKJFLDSKJF”));
assert(isUppercase(” LKJDF L KJL LKJ ASDFHY 98 OIHLHF HY9F8Y9UFHKWEFNSK 98E7Y”));
assert(!isUppercase(“LKDJ LKJDLF LKDJF 899 98u9fs 89879K HKJDHF 9879”));
assert(makeUppercase(“happy”)==”HAPPY”);
assert(makeUppercase(“LKSDJFLKJL 98798797 *&^*&^*( hh 897987 (*&(*&^%& JKSHKDFHSD”)==”LKSDJFLKJL 98798797 *&^*&^*( HH 897987 (*&(*&^%& JKSHKDFHSD”);
assert(makeUppercase(“ART”)==”ART”);
assert(makeUppercase(“Earn *big* MONEY at home!!”)==”EARN *BIG* MONEY AT HOME!!”);
assert(!hasMultipleExclamations(“h”));
assert(!hasMultipleExclamations(“”));
assert(!hasMultipleExclamations(“hh”));
assert(hasMultipleExclamations(“Wow!!!”));
assert(hasMultipleExclamations(“Congrats!!!! YOU ARE GREAT!”));
assert(!hasMultipleExclamations(“W!I!N!”));
assert(!hasMultipleExclamations(“!! !”));
assert(!isGibberishWord(“”));
assert(!isGibberishWord(“h”));
assert(!isGibberishWord(“h4h”));
assert(isGibberishWord(“xxxz”));
assert(!isGibberishWord(“oooooooooxxoooooo”));
assert(isGibberishWord(“happy birthday”));
assert(isGibberishWord(“AGPQrxab”));
assert(isGibberishWord(“xxxxozzzz”));
assert(!isGibberishWord(“mortgage”));
assert(!isGibberishWord(“discount prescriptions”));
assert(!isGibberishWord(” “));
assert(!isGibberishWord(“$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$4”));
assert(isGibberishWord(“FJGHFJGHFJGHFJGHFJHFJHFGFJGHFGJHFKJFHGJFHGJFHG”));
assert(isGibberishWord(“ooooooooooooooookjgfoooooooooooooo”));
assert(isGibberishWord(“ooabcdf”));
cerr << “All tests succeeded” << endl;
}