Wednesday, April 19, 2017

Programming Challenge 10.6 - Vowels And Consonants

/* Vowels And Consonants - This program contains a function that accepts
    a pointer to a C-string as its argument. The function counts the number
    of vowels appearing in the string and returns that number.
   
    The second function accepts a pointer to a C-string as its argument.
    It counts the number of consonants appearing in the string and returns
    that number.
   
    The functions are demonstrated by performing the following steps:

        * The user is asked to enter a string.

        * The program displays the following menu:

            * Count the number of vowels in the string
            * Count the number of consonants in the string
            * Count both the vowels and consonants in the string
            * Enter another string
            * Exit the program

        * The program performs the operation selected by the user and
          repeats until the user selects E to exit the program. */

#include "Utility.h"

/* Provides a basic menu */
int menu();

/* Allows the user to make a menu choice,
    returns the menu choice */
int menuOptions();

/* Determines whether a character is a vowel,
    returns the result */
bool vowel(char);

/* Counts the vowels in a C-string,
    returns the number of vowels found */
int countVowels(char *);

/* Counts the consonants in a C-string,
    returns the number of consonants found */
int countConsonants(char *);

int main()
{
    menu();

   pauseSystem();
   return 0;
}

/* **********************************************************
    Definition: menu

    This function provides a basic menu.
   ********************************************************** */

int menu()
{
    const int NUM_WORDS = 200;

    int         numVowels = 0,
                 numConsonants = 0,
                 menuChoice = 0;
    char         sentence[NUM_WORDS];

    cout << "\n\tVOWEL AND CONSONANT COUNT\n\n"
          << "\tEnter a sentence, " << (NUM_WORDS - 1)
          << " characters maximum in length:\n\t";
    cin.getline(sentence, NUM_WORDS);

    do
    {
        menuChoice = menuOptions();
        cin.ignore();

        switch (menuChoice)
        {
            case 1:
            {               
                cout << "\n\tYour sentence contains: "
                      << (numVowels = countVowels(sentence))
                      << " vowels.\n\n";
            }
            break;

            case 2:
            {
                cout << "\n\tYour sentence contains: "
                      << (numConsonants = countConsonants(sentence))
                      << " consonants.\n\n";
            }
            break;

            case 3:
            {
                cout << "\n\tYour sentence contains: "
                      << (numVowels = countVowels(sentence))
                      << " vowels and "
                      << (numConsonants = countConsonants(sentence))
                      << " consonants.\n\n";
            }
            break;

            case 4:
            {
                cout << "\n\tEnter another sentence:\n\t";
                cin.getline(sentence, NUM_WORDS);
            }
            break;

            case 5:
            {
                cout << "\n\tHave a nice day!\n\n";
            }
        }
    } while (menuChoice != 5);

    return 0;
}

/* **********************************************************
    Definition: displayOptions

    This function displays the main menu options.
   ********************************************************** */

int menuOptions()
{
    const int VOWEL_COUNT = 1,
                 CONSONANT_COUNT = 2,
                 VOWEL_CONSONANT_COUNT = 3,
                 AGAIN = 4,
                 EXIT = 5;

    int         menuChoice = 0;

    cout << "\n\tMain Menu\n"
          << "\t----------\n\n"
          << "\t1. Count the number of vowels in the string\n"
          << "\t2. Count the number of consonants in the string\n"
          << "\t3. Count both the vowels and consonants in the string\n"
          << "\t4. Enter another string\n"
          << "\t5. Exit\n\n"
          << "\tEnter your choice: ";
    cin >> menuChoice;

    /* Input validation */
    while (menuChoice < VOWEL_COUNT || menuChoice > EXIT)
    {
        cout << "\tEnter your choice: ";
        cin >> menuChoice;
    }

    return menuChoice;
}

/* **********************************************************
    Definition: isVowel

    This function determines if a character is a vowel. The
    result is returned.
   ********************************************************** */

bool vowel(char vowel)
{
    if (vowel == 'a' || vowel == 'i' || vowel == 'e' || vowel == 'o' ||
         vowel == 'u' || vowel == 'A' || vowel == 'I' || vowel == 'I' ||
         vowel == 'O' || vowel == 'U')
    {
        return true;
    }
    else
    {
        return false;
    }
}

/* **********************************************************
   Definition: countVowels

    This function accepts a C-string object as argument. It
    counts the number of vowels and returns this number.
   ********************************************************** */

int countVowels(char *wordPtr)
{
    unsigned int index = 0,
                     vowelCount = 0;

    for (index = 0; index < strlen(wordPtr); index++)
    {   
        if (vowel(wordPtr[index])==true)
        {   
            ++vowelCount;
        }       
    }

    return vowelCount;
}

/* **********************************************************
   Definition: countConsonants

    This function accepts a C-string object as argument. It
    counts the number of consonants in a sentence and returns
    this number.
   ********************************************************** */

int countConsonants(char *wordPtr)
{
    unsigned int index = 0,
                     consonantCount = 0;
    bool             isConsonant = false;

    for (index = 0; index < strlen(wordPtr); index++)
    {
        if (vowel(wordPtr[index]) == true)
        {
            isConsonant = false;
        }

        else if (isalpha(wordPtr[index]))
        {
            isConsonant = true;
            consonantCount++;
        }   
    }

    return consonantCount;
}

Example Output:









Tuesday, April 18, 2017

Programming Challenge 10.5 - Sentence Capitalizer

/* Sentence Capitalizer - This program contains a function that accepts
   a pointer to a C-String object as an argument. It capitalizes the
   first character of each sentence in the string. For instance, if the
   string argument is:
 
      * "hello. my name is Joe. what is your name?"
    
   the function manipulates the string so it contains:
 
      * "Hello. My name is Joe. What is your name?"
 
   This function is demonstrated by asking the user to input a string,
   which is passed to the function. The modified string is displayed
   on the screen.

   Optional Exercise: This program also contains an overloaded version
   of this function that accepts a string class object as its argument. */

#include "Utility.h"

/* Capitalizes the first letter of a word at the beginning of every
   sentence */
void senCapitalizer(char *);

/* Capitalizes the first letter of a word at the beginning of every
   sentence. */
void senCapitalizer(string &);

int main()
{
   const int  NUM_CHARS = 501;
   char          sentence[NUM_CHARS];
   string      ctrlSentence = " ";
 
   cout << "\n\tSENTENCE CAPITALIZER\n\n"
        << "\tEnter a sentence, " << (NUM_CHARS - 1)
        << " characters in length:\n\t";
       cin.getline(sentence, NUM_CHARS);

       cout << "\n\tCapitalizing the letters ...\n\n";
       senCapitalizer(sentence);

       cout << "\tThis is your sentence:\n";
       cout << "\t" << sentence;

       cout << "\n\n\tNow enter another sentence:\n\t";
       getline(cin, ctrlSentence);

       cout << "\n\n\tCapitalizing the letters ...\n\n";
       senCapitalizer(ctrlSentence);

       cout << "\tThis is your sentence:\n";
       cout << "\t" << ctrlSentence;

   pauseSystem();
   return 0;
}

/* **********************************************************
   Definition: senCapitalizer

   This function accepts a pointer to a C-string object as
   argument. It capitalizes the first letter in each
   sentence.
   ********************************************************** */

void senCapitalizer(char *charPtr)
{
    unsigned int index = 0;
    bool         isDelim = false;

    for (index = 0; index < strlen(charPtr); index++)
    {
        if (charPtr[index] == '.' || charPtr[index] == '!' ||
            charPtr[index] == '?')
        {
            isDelim = false;
        }

        if (isalpha(charPtr[index]) && isDelim == false)
        {
            isDelim = true;
            charPtr[index] = toupper(charPtr[index]);
        }
    }
}

/* **********************************************************
   Definition: senCapitalizer

   This function accepts a string class object as argument.
   It capitalizes the first letter in each sentence.
   ********************************************************** */

void senCapitalizer(string &sentence)
{
    unsigned int index = 0;
    bool         isDelim = false;

    for (index = 0; index < sentence.length(); index++)
    {
        if (sentence.at(index) == '.' || sentence.at(index) == '!' ||
            sentence.at(index) == '?')
        {
            isDelim = false;
        }

        if (isalpha(sentence.at(index)) && isDelim == false)
        {
            isDelim = true;
            sentence.at(index) = toupper(sentence.at(index));
        }
    }
}

Example Output:






Thursday, April 13, 2017

Programming Challenge 10.4 - Average Number Of Letters

/* Average Number Of Letters - This program is a modification of
   Programming Challenge 10.3 It displays the average number of
   letters in each word. */

#include "Utility.h"

   /* Counts the letters and words contained in the string, returns
      the number of words*/
int countWords(char *, double &);

/* Overloaded function: Counts the letters and words in the string
   class object, returns the number of words */
int countWords(string, double &);

int main()
{
   const int NUM_WORDS = 501;
   int         numWords = 0;
   double     letterCount = 0.0,
             ctrlLetters = 0.0,
             average = 0.0;
   char         sentence[NUM_WORDS];
   string     ctrlSentence = " ";

   cout << "\n\tWORD COUNT - AVERAGE NUMBER OF LETTERS\n\n"
        << "\tEnter a sentence, " << (NUM_WORDS - 1)
        << " characters in length:\n\t";
   cin.getline(sentence, NUM_WORDS);

   cout << "\n\tYour sentence contains: "
        << (numWords = countWords(sentence, letterCount))
        << " words.";

   cout << fixed << setprecision(2);
   cout << "\n\tThe average number of characters is: "
      << (average = letterCount / numWords - 1) << "\n";

   cout << "\n\tEnter another sentence:\n\t";
   getline(cin, ctrlSentence);

   cout << "\n\tThis sentence contains: "
      << (numWords = countWords(ctrlSentence, ctrlLetters))
      << " words.";

   cout << "\n\tThe average number of characters is: "
        << (average = ctrlLetters / numWords);

   pauseSystem();
   return 0;
}

/* **********************************************************
   Definition: countWords

   This function accepts a pointer to a C-string as argument.
   It determines the number of letters and stores this value
   in letterCount. It also counts the words contained in the
   sentence passed to the function and returns this number.
   ********************************************************** */

int countWords(char *wordPtr, double &letterCount)
{
   int            wordCount = 0;
   char            delimList[] = "\" ´-.()*=_!?~<<>>:,\t\n";
   char           *next_word = NULL;
   double        avg = 0.0;
   unsigned int count = 0;
  
   /* Get the letter count */
   while (count != strlen(wordPtr + 1))
   {
      if (!isascii(*wordPtr) && *delimList)
      {
         ++count;
      }
      else
      {
         ++letterCount;
      }
      count++;
   }

   wordPtr = strtok_s(wordPtr, delimList, &next_word);

   while (wordPtr != NULL)
   {     
       if (wordPtr != NULL)
      {     
          wordPtr = strtok_s(NULL, delimList, &next_word);
         ++wordCount;
      }
   }   

   return wordCount;
}

/* **********************************************************
   Definition: countWords

   This overloaded function accepts a string class object as
   argument. It counts the letters, the value is stored in
   letterCount. It also counts the number of words, which
   number is returned from the function.
   ********************************************************** */

int countWords(string ctrlString, double &letterCount)
{
   size_t wordCount = 0,
          numDelims = 0,
          count = 0;

   bool isDelim = true;

   for (size_t index = 0; index < ctrlString.length(); ++index)
   {
      /* If a delimiter or whitespace is found, numDelim increments,
      and isDelim(iter) gets true. Else a word is found, and
      wordCount increments. */
      if (isspace(ctrlString[index]) || ispunct(ctrlString[index]))
      {
         numDelims++;
         isDelim = true;
      }
      else if (isDelim && !ispunct(ctrlString[index + 1]))
      {
         isDelim = false;
         ++wordCount;
      }
   }

   /* Counts the number of letters */
   while (count < ctrlString.length())
   {
      if (isalpha(ctrlString[count]))
         ++letterCount;

      count++;
   }

   return wordCount;
}

Example Output:




Tuesday, April 11, 2017

Programming Challenge 10.3 - Word Counter

/* Word Counter - This program contains a function that accepts a
   pointer to a C-string as an argument, that returns the number
   of words contained in the string. For instance, if the string
   argument is "Four score and seven years ago" the function returns
   the number 6.
  
   The program asks the user to input a string and then passes it to
   the function. The number of words in the string is displayed on
   the screen.
  
   Optional Exercise: This program also contains an overloaded version
   of this function that accepts a string class object as its argument. */

#include "Utility.h"

/* Counts the words contained in the string, returns the number of words*/
int countWords(char *);

/* Overloaded function: Counts words in the string class object, returns
the number of words */
int countWords(string);

int main()
{
   const int NUM_WORDS = 501;
   int         numWords = 0;
   char         sentence[NUM_WORDS];
   string     ctrlSentence = " ";

   cout << "\n\t\tWORD COUNT\n\n"
        << "\tEnter a sentence, " << (NUM_WORDS - 1)
        << " characters in length:\n\t";
   cin.getline(sentence, NUM_WORDS);

   cout << "\n\tYour sentence contains: " << (numWords = countWords(sentence))
      << " words.\n";

   cout << "\n\tEnter another sentence:\n\t";
   getline(cin, ctrlSentence);

   cout << "\n\tThis sentence contains: " << (numWords = countWords(ctrlSentence))
      << " words.\n";

   pauseSystem();
   return 0;
}

/* **********************************************************
   Definition: countWords

   This function accepts a pointer to a C-string as argument.
   It counts the words contained in the sentence passed to
   the function and returns this number.
   ********************************************************** */

int countWords(char *wordPtr)
{
   int  wordCount = 0;
   char delimList[] = "\" ´-.()*=_!?~<<>>:,\t\n";
   char *next_word = NULL;

   wordPtr = strtok_s(wordPtr, delimList, &next_word);

   while (wordPtr != NULL)
   {
      if (wordPtr != NULL)
      {
         wordPtr = strtok_s(NULL, delimList, &next_word);

         ++wordCount;
      }
   }

   return wordCount;
}

/* **********************************************************
   Definition: countWords

   This overloaded version of the function countWords accepts
   a string class object as argument. It counts the words in
   the string and returns the count.
   ********************************************************** */

int countWords(string ctrlString)
{
   size_t wordCount = 0,
          numDelims = 0;

   bool isDelim = true;

   for (size_t index = 0; index < ctrlString.length(); ++index)
   {
      /* If a delimiter or whitespace is found, numDelim increments,
         and isDelim(iter) gets true. Else a word is found, and
         wordCount increments. */
      if (isspace(ctrlString[index]) || ispunct(ctrlString[index]))
      {
        numDelims++;
           isDelim = true;
      }
      else if (isDelim && !ispunct(ctrlString[index + 1]))
      {
         isDelim = false;
         ++wordCount;
      }
   }

   return wordCount;
}

Example Output:






Thursday, April 6, 2017

Programming Challenge 10.2 - Backward String

/* Backward String - This program contains a funtion that accepts a
   pointer to a C-string as an argument. It displays the contents
   backward. For instance, if the string argument is "Gravity", the
   function displays "ytivarG". This function is demonstrated by
   asking the user to input a string that is passed to the function. */

#include "Utility.h"

/* Reverses a string entered by the user and displays it */
void reverseString(char *);

int main()
{
   const int NUM_CHARS = 51;

   /* Array to hold the word(s) */
   char *word = new char[NUM_CHARS]();

   char again = ' ';

   do
   {
      cout << "\n\tBACKWARD STRING - GNIRTS DRAWKCAB\n\n"
           << "\tEnter a word of up to " << (NUM_CHARS - 1)
           << " characters and I will reverse it: ";
      cin.getline(word, NUM_CHARS);

      reverseString(word);

      /* Ask the user if he or she wishes to enter another word */
      cout << "\n\tDo you wish to enter another word? ";
      cin.get(again);

      /* Input validation */
      while (toupper(again) != 'Y' && toupper(again) != 'N')
      {
         cout << "\n\tEnter 'Y' or 'N': ";
         cin.ignore();
         cin.get(again);
      }

      if (toupper(again) == 'Y')
      {
         cin.getline(word, NUM_CHARS);

      }
      else
      {
         cout << "\n\t!yeB dooG\n\n";
      }
   } while (toupper(again) == 'Y');

   /* Frees the memory */
   delete[] word;
   word = nullptr;

   pauseSystem();
   return 0;
}

/* **********************************************************
   Definition: reverseString

   This function accepts a pointer to a C-string as argument.
   After the string is reversed, using the swap function, the
   word is displayed backwards.
   ********************************************************** */

void reverseString(char *revPtr)
{
   int forward = 0,
       backward = strlen(revPtr);

   while (forward < backward)
   {
      --backward;

      swap(*(revPtr + forward), *(revPtr + backward));

      forward++;
   }

   cout << "\tThis is your word backwards: " << revPtr << "\n";
}

Example Output:



Programming Challenge 10.1 - String Length

/* String Length - This program contains a function that returns an
   integer and accepts a pointer to a C-string as an argument. The
   function counts the number of characters in the string and returns
   that number. The user is asked to input a string, which is passed
   to the function, and then displays the function's return value. */

#include "Utility.h"

/* Counts characters in a C-string, returns the character count. */
int countChars(const char *);

int main()
{
   const int NUM_CHARS = 100;

   /* Char array to hold a sentence */
   char *sentence = new char[NUM_CHARS]();

   char again = ' ';
   int  letterCount = 0;

   do
   {
      /* Get a sentence from the user */
      cout << "\n\t\t\tCHARACTER COUNTER\n\n"
           << "\tEnter a sentence of up to " << (NUM_CHARS - 1)
           << " characters: ";
      cin.getline(sentence, NUM_CHARS);

      /* Display the number of characters in the string */
      cout << "\n\tThis sentence contains "
           << (letterCount = countChars(sentence))
           << " characters.\n";

      /* Ask if the user wishes to enter another sentence */
      cout << "\n\tDo you wish to enter another sentence ('Y' or 'N')? ";
      cin.get(again);

      /* Input validation */
      while (toupper(again) != 'Y' && toupper(again) != 'N')
      {
         cout << "\n\tEnter 'Y' or 'N' to enter another sentence: ";
         cin.ignore();
         cin.get(again);
      }

      /* If again is 'y', another sentence may be entered. */
      if (toupper(again) == 'Y')
      {
         cin.getline(sentence, NUM_CHARS);
      }
      else
      {
         cout << "\n\tGood bye!\n\n";
      }

   } while (toupper(again) == 'Y');

   /* Frees the memory */
   delete[] sentence;
   sentence = nullptr;

   pauseSystem();
   return 0;
}

/* **********************************************************
   Definition: countChars

   This function contains chrPtr, pointing to the C-string
   containing a sentence the user entered. It counts the
   characters and returns this number as an integer value.
   ********************************************************** */

int countChars(const char *chrPtr)
{
   int numChars = 0;

   while (*chrPtr != '\0')
   {
       numChars++;
      *chrPtr++;
   }

   return numChars;
}

Example Output:



Monday, April 3, 2017

Half Way

It is time to celebrate! Today, I officially reached the half-way point, meaning to be half way through the book, after about 6 months. Last year in September I started my journey, this blog followed about a month, and 3 chapters, later. So instead of writing about my experiences with this chapter, I will tell you about my past experience with programming and programming languages. 

I started out with the Basic language, back in the day on a Commodore 64. I never got very far into it, mostly typing in long listings, then enjoying some game or other. Around 2005 another programming language entered my life, Visual Basic this time. It and I haven't been compatible to each other. Quite frankly, I didn't understand the language, the syntax, I didn't like it, yet had to learn it. I failed, and since I wouldn't need it anyway, simply gave up on it. Yet I always wanted to write my own game someday, and this would most likely require to learn a language to realize it. 

2015 was the year of experimenting around with some programming languages. I tried Java, didn't like it, C# - which I tried once before, and seemed a good choice, then Perl and finally Monoscript. It is part of Unity, so I did some tutorials the company had to offer, and bought a book or two. Eventually I managed to finish the tutorials, but when it came to realize something on my own, I could not. It was the lack of knowledge about pointers, arrays, classes, you name it. Sticking to the approach of taking a shortcut ended in the realization that without solid knowledge of at least one language, my dream will remain to be just that, and as I'm not the person to give up on anything, no matter how long it takes me to get there, this was no option.

Last year, then, closing the circle, I found the book Starting Out With C++ and bought it. It wasn't cheap, but good things come with a price-tag attached to it, so I said to myself - Here goes nothing! bought it, and finally found not only a resource I could work with, but also the language most compatible to my style. (For lack of any better word). To sum it up, despite having knowledge of html, css, melscript, some basic, close to no knowledge of VB and some other languages, I was - and still consider myself to be, a newbie. 

It started out easy, "Hello World!", and, looking back, hasn't gotten any more difficult since then. Sounds strange to say, when looking at some of my most recent struggles, particularly the one concerning the discovery of mode(s) in an array of integers. That is to say that most of the time it wasn't coming up with a way to write code for the challenges, but rather to understand the nature of the problem, and to find a way to solve it. 

Here is an example. The median function I have written for one of the challenges. Below you find part of the code that does all the work: 

   int      middleElem = numels / 2,
             midLower = 0,
             midUpper = 0;

   numels % 2 == 0 ? midLower = *(numList + middleElem - 1),
                                  midUpper = *(numList + middleElem),
                                  median = (midUpper + midLower) / 2 :
                                  median = *(numList + middleElem);

But how did I come up with this ternary, or rather this particular solution? At first I thought that I would use the subtle hint given in the problem statement in my code somehow: 

"If the set contains an even number of values, the median is the mean or average, of the two middle values."

It was clear that if there is an even number, there has to be an odd number, and to find it would necessitate to use the modulo operator, to find out whether the number of elements is odd or even. To find a mode in an odd-numbered set would be straightforward, so my first thought was to implement a binary-search, which would find the middle-value. I tried, then reconsidered. 

What would a binary-search actually do? It would solve one half of the problem, but how would this look like? Should I call this function to do the search if a number is odd, and then call another function if it isn't? No, there must be a more straightforward solution to this, revolving around the central idea of odd and even numbers. I sat back, thinking, and taking a closer look at a different part of my code:

  *(numList + startScan) = minEl;

This line is part of the sorting function. And seeing how startScan is used there, and how it is used in the search function, I started seeing a connection to my problem, and how I can solve it. I knew that it is about odd and even numbers, and that an even-numbered array would contain two middle values, one in the upper, one in the lower half. So why don't I use this, initialize middleElem to calculate the halfs, reverse the condition by assigning to variables the numbers in the upper half and in the lower half? This is what I did, and it worked. All because I found this connection between the line of code I so often used to perform a sort on numbers, I found the key to solve the problem, by combining everything in a single ternary operator. 

Ternary, in my opinion, is a misnomer. In or around chapters 7 and 8 I found out that it is very well possible to chain ternaries, there is practically no limit. You only have to replace the : with another condition. condition ? condition1 ? condition2 ? condition 3? x : y. I tried in one of my programs, but refrained from actually using the piece of code, even though it worked. Because something works doesn't mean you should use it, as it would guarantee to make it nigh impossible to read, as well as difficult to understand for others what the piece of code actually does. Ternary being a mighty tool making for short, yet still readable code, if done right. This is why I so like it, as in the above example, one line of code does it all. 

Back to this line of code once more:

*(numList + startScan) = minEl;

To discover that it holds the key to solve the above mentioned problem also was key to solve the Reverse Array, Array Expander and Element Shifter challenges. The only challenge has been to figure out the counters, as in one challenge the counter had to count up, the other down in one challenge, and in one of the others both had to count up. This took a while to find out, but was no major hurdle, just a matter of switching the counter variables around several times. And again the key has been a line of code from the sorting function:

*(numList + minIndex) = *(numList + startScan);

to come up with this one line in the Array Expander challenge:
 
*(expanded + count) = *(numbers + count); 

But what about pointers, since this chapter has been all about it, and I haven't yet lost a single word on them? Well, at first I felt a little intimidated and insecure in the early challenges, always thinking: Am I doing things right? Luckily the first couple of challenges fostered some confidence. This was quickly destroyed by the mode challenge. 3 weeks, the longest time it has taken to finish a challenge! And it wasn't even the pointers, but enough of this one, I will not wish to be reminded of it - ever - period. Summarily I can say that I feel rather comfortable working with pointers now, and that I very much like what I can do with them, as well as the pointer notation. I like it more than array notation, so I think you will see more of it in the near future. 

For now I deserve some rest, before I dive into the 10th chapter. This one will be about C-Strings, Characters and the string Class, which I do not yet know I will like, the topics, that is. But as it is a part of the book, I will make the best of it. Rest assured that I will be back soon with more code. Until then I wish my fellow learners that they be soon finished with this chapter, and that they be able to make such important discoveries as i did. To my readers, regular or otherwise, thanks for your visit!