Thread: Exercise 3-3 in Accelerated C++

  1. #1
    Registered User
    Join Date
    Aug 2013
    Posts
    2

    Exercise 3-3 in Accelerated C++

    Hi, I am just beginning programming and I picked up the book Accelerated C++ because of all the recommendations and great reviews.

    It's supposed to be a good beginner book but I am on chapter 3 and I am already beginning to struggle.


    I got stuck on exercise 3-3 but was able to find the solution on Chapter 3 – Working with Batches of Data « Parks Computing

    Unfortunately even while combing through the code and trying to review while retyping in codeblocks I am still confused and not quite understanding how the program worked successfully in the end.

    The exercise asks you to write a program to count how many times each distinct word appears in its input.

    This is the code provided on parkscomputing.com

    Code:
    
    #include <algorithm>#include <iostream>#include <string>#include <vector>using std::cin;using std::cout;using std::endl;using std::sort;using std::string;using std::vector;int main(){   // Ask for and read the words   cout << "Please enter a few words, followed by end-of-file: ";   vector<string> words;   string word;   // Invariant: words contains all of the words read so far   while (cin >> word)      words.push_back(word);   *1   typedef vector<string>::size_type vec_sz;   vec_sz size = words.size();   1*   // Check that the user entered some words   if (size == 0)   {      cout << endl << "You didn't enter any words. "         "Please try again." << endl;      return 1;   }   *2   // sort the words   sort(words.begin(), words.end());   2*   string current_word;   int count;   // Set the initial word to the first word in the vector   current_word = words[0];   // Set the initial count for the first word   count = 1;   *3   // Invariant: we have counted current_index of the total words   // in the vector   for (vec_sz current_index = 1; current_index < size; ++current_index)   {      // Report the count for the current word if it does not match      // the word at the current index in the vector, and reset the      // count to zero so that it will one when the variable is      // incremented outside the if statement.      if (current_word != words[current_index])      {         cout << "The word \"" << current_word << "\" appears "            << count << " times." << endl;         current_word = words[current_index];         count = 0;      }      *3      ++count;   }   *4   // Report the count for the final word   cout << "The word \"" << current_word << "\" appears "      << count << " times." << endl;   4*   // We have reported the count of all the words in the vector, so exit.   return 0;}
    I put an * on the pieces I have a question about.

    *1 - I understand what typedef does but I don't understand the piece of code it shortens. (vector<string>::size_type) Why exactly do I need to create vec_sz size = words.size()? And how is it used later in the program?

    *2 - Is it possible to call these .begin() and .end() values for output or a statement or do I must first put them in something a type string or type int if it were a number?


    *3 - is where I completely got lost. I really don't understand the logic behind all of this.

    *4 - Why is this last part separate from *3? In all the other for/if/while implementations so far in the book we haven't needed to use a different piece of code for the last output.


    Thanks for the help!

  2. #2
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Huh, so that's how a compiler looks at code O_o

  3. #3
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Okay, so I looked at the solution which is what I'm assuming you looked at. I'm actually reading this book too and I didn't even know they had full solutions. Talk about a useful reference lol.

    Anyway, this code,
    Code:
    typedef vector<string>::size_type vec_sz;
    vec_sz size = words.size();
    simply redefines "vector<string>::size_type" to the declaration "vec_sz". Look at this link, vector - C++ Reference and you'll see that the member size_type is usually the same as size_t but instead of being applicable to anything, it's specifically made for vectors. I'm actually not sure how this part really works because you could just use the sizeof() operator but w/e. Basically, size_type seems to be the unit size of each element of the vector.

    Idk what your second question is asking. But the .begin() and .end() member functions return iterators to the beginning and end of the vector.

    Now, as for the program itself. When you sort a vector of strings, the library was written to automatically sort by alphabetical order. So, what this code does is, it points to the first element of the vector and then begins examining every element but that one. If the next element is not the exact same then we know for sure that the word was only repeated once. So it then resets the iterator to the next element and then continues checking every element after.

    Code:
    for (vec_sz current_index = 1; current_index < size; ++current_index)
       { 
          if (current_word != words[current_index])
          {
             cout << "The word \"" << current_word << "\" appears "
                << count << " times." << endl;
    
    
             current_word = words[current_index];
             count = 0;
          }
    
    
          ++count;
       }

    Here you can see that our first current_word is words[0]. It's redundant to compare this to words[0] so we start off at index 1 and we will iterate over the range less than size. So, if current_word is not equal to next index then we know it is not repeated so we print out some useful information and reset the counter. If the next word is the same then we simply add 1 to the count and then check the following indices.

    Here's what words would look like sorted, ( Na, goodbye, hey, hey, na, na, na ).

    The loop starts off at Na and compares it to goodbye. They are not the same so we print and then reset the current_word to the next word in the vector. Now we start off at goodbye. The next word is "hey" which is not the same so print and reset current_word to the first "hey". We point at "hey" and the next word is "hey" so we increase the count and check the index after the second "hey". Note that it is the first "hey" that is being compared to the first "na" as current_word was NOT updated. current_word is only changed in the if-block.

    So we find that "hey" is not "na" so we reset current_word to the position where the inequality was found (at the first "na") and continue looking from there. Note that it's the same here, the first "na" is compared to the last two "na"s and our loop finally breaks when the current_index exceeds the length of the vector.

    I hope this helped.

    Edit: And the last part is a safe-guard against the breaking condition of the loop occurring before the inequality within the loop happens. Notice that the loop ends before the code has a chance to get to an index where the first "na" does not equal some other element of it so the external print is simply a safe guard against that and will print w/e was left over from the loop.
    Last edited by MutantJohn; 08-27-2013 at 12:58 AM.

  4. #4
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    I'm actually not sure how this part really works because you could just use the sizeof() operator but w/e. Basically, size_type seems to be the unit size of each element of the vector.
    size_type is a typedef present in all STL containers, it is supposed to represent the type best used to keep track of the size of said container. Usually it is simply a size_t but you should prefer to use the typedef in case this changes in the future.

    *2 - Is it possible to call these .begin() and .end() values for output or a statement or do I must first put them in something a type string or type int if it were a number?
    begin() and end() return iterators to the beginning and end of the container, if you need to access the elements at these positions you must first dereference the iterators like so:

    Code:
    std::cout << *(vec.begin()) << std::endl;
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

  5. #5
    Registered User
    Join Date
    Aug 2013
    Posts
    2
    MutantJohn, Thanks that actually helped a lot. Breaking it down made me realize what I should have caught earlier. I was confused because I thought the code was comparing current_word with all the words in the vector but in reality, all it does is compare itself with the next word. So if your input was "goodbye hello hello goodbye" The output would say "goodbye was counted once, hello twice, goodbye once" I thought the program was supposed to say "good by twice, hello twice"
    Last edited by quarks; 08-28-2013 at 03:07 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Question exercise 3.5 Accelerated C++
    By roelof in forum C++ Programming
    Replies: 16
    Last Post: 06-19-2010, 05:02 AM
  2. help with a exercise of Accelerated C++
    By roelof in forum C++ Programming
    Replies: 14
    Last Post: 06-11-2010, 09:45 AM
  3. Exercise 5.10 (ACCELERATED C++)
    By pantera in forum C++ Programming
    Replies: 2
    Last Post: 05-10-2010, 08:46 AM
  4. Replies: 2
    Last Post: 05-02-2010, 01:49 AM
  5. Help with Accelerated C++ exercise
    By s_siouris in forum C++ Programming
    Replies: 5
    Last Post: 01-24-2010, 03:10 PM