# Exercise 6-0

Compile, execute, and test the programs in this chapter.

# Solution

In Chapter 6 of the textbook there are 7 core concepts / programs introduced. For ease of documentation I shall dice this up into 7 parts as followings – simply click the hyperlink to drill down to see the post corresponding to the particular part.

Exercise 6-0 (Part 1 / 7): Relating to section 6.1 of the textbook (page 101-103). There are many ways to append elements from container B to container A (the base). In this post I shall implement and test out 3 known ways to do this: (1) pusb_back method, (2) insert method, and (3) copy method. The test confirms that all 3 methods produce the same results.

Exercise 6-0 (Part 2 / 7): Relating to section 6.1.1 of the textbook (page 103-105). Implement and test out an alternative way to split a line into words using the find_if utility from the <algorithm> directive. The original split function method was first introduced in S5.6/88 of the book.

Exercise 6-0 (Part 3 / 7): Relating to section 6.1.2 of the textbook (page 105). Implement and test out the home-made isPalindrome function (created using the equal utility). Note that this is a more neat / compact version to the created in my previous Solution to Exercise 5-10.

Exercise 6-0 (Part 4 / 7): Relating to section 6.1.3 of the textbook (page 105-109). Implement and test out the “Finding URLs” program. The program scans a line of input text, and automatically detect and display all the URL addresses within that line of text.

Exercise 6-0 (Part 5 / 7): Relating to section 6.2 of the textbook (page 110-116). Implement and test out the “Comparing Grading Schemes” program. This program reads in a set of student’s grades (from mid-term exam, final exam, and individual homework grades), compute the student’s final grades using the 3 grading schemes (median homework, average homework, and optimistic-median homework), split the students into two groups (did and didn’t do all homework), and for each group compute the group medians associating with the grading schemes. i.e. the end result consists of 6 total grades: medians computed using the 3 schemes for group A (students who did all homework), and medians computed using the 3 schemes for group B (students who didn’t do all homework). The exercise introduces one key idea: parsing a function as an argument to another function. From Chapter 10 we shall see this is actually facilitated by the “hidden” pointer and array mechanism.

Exercise 6-0 (Part 6 / 7): Relating to section 6.3.1 of the textbook (page 117-118). Implement and test out the “two-pass extract_fails” program. This program essentially split the students into two groups – failed and passed students. This version of extract_fails function uses remove_copy_if and erase from the <algorithm> directive. (Note that the original version of extract_fails function was first introduced in Chapter 5 / my Solution to Exercise 5-0.

Exercise 6-0 (Part 7 / 7): Relating to section 6.3.2 of the textbook (page 119-120). Building on the previous exercise the author introduces an even better “one-pass extract_fails” program which takes half the time to run in comparison to the “two-pass” version. This version of extract_fails function uses the stable_partition and erase from the <algorithm> directive.

# Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

# Accelerated C++ Solution to Exercise 6-0 (Part 7 / 7)

This is Part 7 of the 7-part Exercise 6-0. Click here to see the other parts.

# Exercise 6-0 (Part 7 / 7)

Relating to section 6.3.2 of the textbook (page 119-120). Building on the previous exercise the author introduces an even better “one-pass extract_fails” program which takes half the time to run in comparison to the “two-pass” version. This version of extract_fails function uses the stable_partition and erase from the <algorithm> directive.

## The Project

Note that the project for this exercise is exactly the same as the one shown in my Solution to Exercise 6-0 (Part 6 / 7). Except for one file as follows:

### extract_fails.cpp

#include <vector>             // std::vector
#include <algorithm>          // std::remove_copy_if

#include "Student_info.h"

using std::vector;

// A single-pass solution to extract the failed students
// (S6.3.2/119)
vector<Student_info> extract_fails(vector<Student_info>& students)
{
vector<Student_info>::iterator iter =

vector<Student_info> fail(iter, students.end());
students.erase(iter, students.end());

return fail;
}


## Test Program

Using the same set of student grades as per Exercise 6-0 (Part 6 / 7), the result is the same as expected.

pete 100 100 100 100 100
jon 90 90 0 0 0
mary 50 50 50 50 50
anna 40 40 0 0 0
gary 80 80 0 80 0
bob 100 100 100 0 0
ken 20 88 99 44 66
jay 99 39 40 80 0
bill 20 88 0 39 0
^Z
^Z
These students have passed.
bob (60)
ken (65.6)
pete (100)
These students have failed.
anna (24)
bill (39.2)
gary (48)
jay (51.4)
jon (54)
mary (50)


# Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

# Accelerated C++ Solution to Exercise 6-0 (Part 6 / 7)

This is Part 6 of the 7-part Exercise 6-0. Click here to see the other parts.

# Exercise 6-0 (Part 6 / 7)

Relating to section 6.3.1 of the textbook (page 117-118). Implement and test out the “two-pass extract_fails” program. This program essentially split the students into two groups – failed and passed students. This version of extract_fails function uses remove_copy_if and erase from the <algorithm> directive. (Note that the original version of extract_fails function was first introduced in Chapter 5 / my Solution to Exercise 5-0.)

## The Project

This section summarises the partitioned program in the form of C++ source and header files.

### Source Files

#### main.cpp

#include <iostream>          // std::cin, std::cout, std::endl
#include <string>            // std::string
#include <vector>            // std::vector
#include <algorithm>         // std::sort
#include "extract_fails.h"   // extract_fails

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::sort;

int main()
{
vector<Student_info> students;
Student_info record;

// read and store all the student's data.
students.push_back(record);

// Extract the failed students
vector<Student_info> students_failed = extract_fails(students);

// sort vectors
sort(students.begin(),students.end(),compare);
sort(students_failed.begin(),students_failed.end(),compare);

// Report passing students
cout << "These students have passed." << endl;
for (vector<Student_info>::const_iterator i = students.begin();
i != students.end(); ++i)
cout << i->name << " (" << grade(*i) << ")" << endl;

// Report failing students
cout << "These students have failed." << endl;
for (vector<Student_info>::const_iterator i = students_failed.begin();
i != students_failed.end(); ++i)
cout << i->name << " (" << grade(*i) << ")" << endl;

return 0;
}


#### extract_fails.cpp

#include <vector>             // std::vector
#include <algorithm>          // std::remove_copy_if

#include "Student_info.h"

using std::vector;

// A two-pass solution to extract the failed students
// (S6.3.1/117)
vector<Student_info> extract_fails(vector<Student_info>& students)
{
vector<Student_info> fail;
remove_copy_if(students.begin(), students.end(),
students.end() );
return fail;
}


#include "Student_info.h"  // Student_info

// predicate to determine whether a student failed
// (S5.1/75)
{
}


#include <stdexcept>
#include <vector>
#include "median.h"
#include "Student_info.h"

using std::domain_error;
using std::vector;

// definitions for the grade functions from S4.1/52, S4.1.2/54, S4.2.2/63

// compute a student's overall grade from midterm and final exam
double grade(double midterm, double final, double homework)
{
return 0.2 * midterm + 0.4 * final + 0.4 * homework;
}

// compute a student's overall grade from midterm and final exam grades
// and vector of homework grades.
// this function does not copy its argument, because median (function) does it for us.
// (S4.1.2/54)
double grade(double midterm, double final, const vector<double>& hw)
{
if (hw.size() == 0)
throw domain_error("student has done no homework");
}

// this function computes the final grade for a Student_info object
// (S4.2.2/63)
{
}


#### median.cpp

// source file for the median function
#include <algorithm>
#include <stdexcept>
#include <vector>

using std::domain_error;
using std::sort;
using std::vector;

// compute the median of a vector<double>
// (S4.1.1/53)
double median(vector<double> vec)
{
typedef vector<double>::size_type vec_sz;

vec_sz size = vec.size();
if (size == 0)
throw domain_error("median of an empty vector");

sort(vec.begin(),vec.end());

vec_sz mid = size/2;

return size % 2 == 0 ? (vec[mid] + vec[mid-1]) / 2 : vec[mid];
}


#include "Student_info.h"  // Student_info

// predicate to determine whether a student has passed (not failed)
// (S6.3.1/117)
{
}


#### Student_info.cpp

#include "Student_info.h"

using std::istream;
using std::vector;

// we are interested in sorting the Student_info object by the student's name
bool compare(const Student_info& x, const Student_info& y)
{
return x.name < y.name;
}

// and store into the Student_info object
// (as defined in S4.2.2/62)
{
// read and store the student's name and midterm and final exam grades
is >> s.name >> s.midterm >> s.final;

return is;
}

// (as defined in S4.1.3/57)
{
if (in)
{
// get rid of previous contents
hw.clear();

double x;
while (in >> x)
hw.push_back(x);

// clear the stream so that input will work for the next student
in.clear();
}
return in;
}


#### extract_fails.h

#ifndef GUARD_EXTRACT_FAILS_H
#define GUARD_EXTRACT_FAILS_H

// extract_fails.h

#include <vector>
#include "Student_info.h"

std::vector<Student_info> extract_fails(std::vector<Student_info>&);

#endif // GUARD_EXTRACT_FAILS_H


#ifndef GUARD_FGRADE_H

#include "Student_info.h"  // Student_info



#ifndef GUARD_GRADE_H

#include <vector>
#include "Student_info.h"



#### median.h

#ifndef GUARD_MEDIAN_H
#define GUARD_MEDIAN_H

// median.h

#include <vector>

double median(std::vector<double>);

#endif // GUARD_MEDIAN_H


#ifndef GUARD_PGRADE_H

#include "Student_info.h"  // Student_info



#### Student_info.h

#ifndef GUARD_STUDENT_INFO_H
#define GUARD_STUDENT_INFO_H

// Student_info.h

#include <iostream>
#include <string>
#include <vector>

struct Student_info
{
std::string name;
double midterm, final;
std::vector<double> homework;
};

bool compare(const Student_info&, const Student_info&);

#endif // GUARD_STUDENT_INFO_H


## Test Program

I now provide a set of student grades. The program separate the students to the pass and fail groups as expected.

pete 100 100 100 100 100
jon 90 90 0 0 0
mary 50 50 50 50 50
anna 40 40 0 0 0
gary 80 80 0 80 0
bob 100 100 100 0 0
ken 20 88 99 44 66
jay 99 39 40 80 0
bill 20 88 0 39 0
^Z
^Z
These students have passed.
bob (60)
ken (65.6)
pete (100)
These students have failed.
anna (24)
bill (39.2)
gary (48)
jay (51.4)
jon (54)
mary (50)


# Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

# Accelerated C++ Solution to Exercise 6-0 (Part 5 / 7)

This is Part 5 of the 7-part Exercise 6-0. Click here to see the other parts.

# Exercise 6-0 (Part 5 / 7)

Relating to section 6.2 of the textbook (page 110-116). Implement and test out the “Comparing Grading Schemes” program. This program reads in a set of student’s grades (from mid-term exam, final exam, and individual homework grades), compute the student’s final grades using the 3 grading schemes (median homework, average homework, and optimistic-median homework), split the students into two groups (did and didn’t do all homework), and for each group compute the group medians associating with the grading schemes. i.e. the end result consists of 6 total grades: medians computed using the 3 schemes for group A (students who did all homework), and medians computed using the 3 schemes for group B (students who didn’t do all homework). The exercise introduces one key idea: parsing a function as an argument to another function. From Chapter 10 we shall see this is actually facilitated by the “hidden” pointer and array mechanism.

## The Project

This section summarises the partitioned program in the form of C++ source and header files.

### Source Files

#### main.cpp

#include <iostream>  // cin, cout, endl
#include <vector>  // vector

#include "Student_info.h"  // Student_info
#include "did_all_hw.h"  // did_all_hw
#include "write_analysis.h"  // write_analysis

#include "median_analysis.h"  // median_analysis
#include "average_analysis.h"  // average_analysis
#include "optimistic_median_analysis.h"  // optimistic_median_analysis

using std::cin;
using std::cout;
using std::endl;
using std::vector;

// (S6.2.3/114)
int main()
{
// students who did and didn't do all their homework
vector<Student_info> did, didnt;

// read the student records and partition them
Student_info student;
if (did_all_hw(student))
did.push_back(student);
else
didnt.push_back(student);
}

// verify that the analyses will show us something
if (did.empty()) {
cout << "No student did all the homework!" << endl;
return 1;
}
if (didnt.empty()) {
cout << "No student did all the homework!" << endl;
return 1;
}

// do the analyses
write_analysis(cout, "median", median_analysis, did, didnt);
write_analysis(cout, "average", average_analysis, did, didnt);
write_analysis(cout, "median of homework turned in",
optimistic_median_analysis, did, didnt);

return 0;
}


#### average.cpp

#include <vector>  // vector
#include <numeric>  // numeric

using std::vector;
using std::accumulate;

// Compute average of elements
// (S6.2.3/115)
double average(const vector<double>& v)
{
return accumulate(v.begin(), v.end(), 0.0) / v.size();
}


#### average_analysis.cpp

#include <vector>  // vector
#include <algorithm>  // transform
#include "Student_info.h"  // Student_info
#include "median.h"  // median

using std::vector;
using std::transform;

// Perform average analysis
// (S6.2.3/115)
double average_analysis(const vector<Student_info>& students)
{
transform(students.begin(), students.end(),
}


#include "Student_info.h"  // Student_info
#include "average.h"  // average

// Compute the final grade using average of homework
// (S6.2.3/115)
{
}


#### did_all_hw.cpp

#include <algorithm>  // find
#include "Student_info.h"  // Student_info

// Has the student done all the homework?
// (S6.2.1/110)
bool did_all_hw(const Student_info& s)
{
return ((find(s.homework.begin(), s.homework.end(), 0)) == s.homework.end());
}


#include <stdexcept>
#include <vector>
#include "median.h"
#include "Student_info.h"

using std::domain_error;
using std::vector;

// definitions for the grade functions from S4.1/52, S4.1.2/54, S4.2.2/63

// compute a student's overall grade from midterm and final exam
double grade(double midterm, double final, double homework)
{
return 0.2 * midterm + 0.4 * final + 0.4 * homework;
}

// compute a student's overall grade from midterm and final exam grades
// and vector of homework grades.
// this function does not copy its argument, because median (function) does it for us.
// (S4.1.2/54)
double grade(double midterm, double final, const vector<double>& hw)
{
if (hw.size() == 0)
throw domain_error("student has done no homework");
}

// this function computes the final grade for a Student_info object
// (S4.2.2/63)
{
}


#include "Student_info.h"  // Student_info
#include <stdexcept>  // domain_error

using std::domain_error;

// Auxiliary function to be parsed as argument to a function
// (S6.2.2/113)
{
try {
} catch (domain_error) {
}
}


#### median.cpp

// source file for the median function
#include <algorithm>
#include <stdexcept>
#include <vector>

using std::domain_error;
using std::sort;
using std::vector;

// compute the median of a vector<double>
double median(vector<double> vec)
{
typedef vector<double>::size_type vec_sz;

vec_sz size = vec.size();
if (size == 0)
throw domain_error("median of an empty vector");

sort(vec.begin(),vec.end());

vec_sz mid = size/2;

return size % 2 == 0 ? (vec[mid] + vec[mid-1]) / 2 : vec[mid];
}


#### median_analysis.cpp

#include <vector>  // vector
#include <algorithm>  // transform
#include "Student_info.h"  // Student_info
#include "median.h"  // median

using std::vector;
using std::transform;

// S6.2.2/112
double median_analysis(const vector<Student_info>& students)
{
}


#### optimistic_median.cpp

#include <vector>  // vector
#include <algorithm>  // remove_copy, back_inserter
#include "Student_info.h"  // Student_info
#include "median.h"  // median

using std::vector;

// median of the nonzero elements of s.homework, or 0 if no such elements exist
double optimistic_median(const Student_info& s)
{
vector<double> nonzero;
remove_copy(s.homework.begin(), s.homework.end(),
back_inserter(nonzero), 0);
if (nonzero.empty())
else
}


#### optimistic_median_analysis.cpp

#include <vector>  // vector
#include <algorithm>  // transform
#include "Student_info.h"  // Student_info
#include "optimistic_median.h" // optimistic_median
#include "median.h"  // median

using std::vector;
using std::transform;

// Auxiliary function
double optimistic_median_analysis(const vector<Student_info>& students)
{
transform(students.begin(), students.end(),
}


#### Student_info.cpp

#include "Student_info.h"

using std::istream;
using std::vector;

// we are interested in sorting the Student_info object by the student's name
bool compare(const Student_info& x, const Student_info& y)
{
return x.name < y.name;
}

// and store into the Student_info object
// (as defined in S4.2.2/62)
{
// read and store the student's name and midterm and final exam grades
is >> s.name >> s.midterm >> s.final;

return is;
}

// (as defined in S4.1.3/57)
{
if (in)
{
// get rid of previous contents
hw.clear();

double x;
while (in >> x)
hw.push_back(x);

// clear the stream so that input will work for the next student
in.clear();
}
return in;
}


#### write_analysis.cpp

#include <iostream>  // ostream, endl;
#include <vector>  // vector
#include <string>  // string
#include "Student_info.h"  // Student_info

using std::ostream;
using std::endl;
using std::string;
using std::vector;

// Output result to compare the two groups of students who did and
// who didn't do all of their homework.
// (S6.2.3/113)
void write_analysis(ostream& out,
const string& name,
double analysis(const vector<Student_info>&),
const vector<Student_info>& did,
const vector<Student_info>& didnt)
{
out << name << ": median(did) = " << analysis(did) <<
": median(didnt) = " << analysis(didnt) << endl;
return;
}


#### average.h

#ifndef GUARD_AVERAGE_H
#define GUARD_AVERAGE_H

// average.h
#include <vector>

double average(const std::vector<double>&);

#endif // GUARD_AVERAGE_H


#### average_analysis.h

#ifndef GUARD_AVERAGE_ANALYSIS_H
#define GUARD_AVERAGE_ANALYSIS_H

// average_analysis.h

#include <vector>

double average_analysis(const std::vector<Student_info>&);

#endif // GUARD_AVERAGE_ANALYSIS_H


#ifndef GUARD_AVERAGE_GRADE_H

#include "Student_info.h"  // Student_info



#### did_all_hw.h

#ifndef GUARD_DID_ALL_HW_H
#define GUARD_DID_ALL_HW_H

// did_all_hw.h
#include "Student_info.h"  // Student_info

bool did_all_hw(const Student_info&);

#endif // GUARD_DID_ALL_HW_H


#ifndef GUARD_GRADE_H

#include <vector>
#include "Student_info.h"



#ifndef GUARD_GRADE_AUX_H

#include "Student_info.h"  // Student_info



#### median.h

#ifndef GUARD_MEDIAN_H
#define GUARD_MEDIAN_H

// median.h
#include <vector>
double median(std::vector<double>);

#endif // GUARD_MEDIAN_H


#### median_analysis.h

#ifndef GUARD_MEDIAN_ANALYSIS_H
#define GUARD_MEDIAN_ANALYSIS_H

// median_analysis.h
#include <vector>
#include "Student_info.h"  // Student_info

double median_analysis(const std::vector<Student_info>&);

#endif // GUARD_MEDIAN_ANALYSIS_H


#### optimistic_median.h

#ifndef GUARD_OPTIMISTIC_MEDIAN_H
#define GUARD_OPTIMISTIC_MEDIAN_H

// optimistic_median.h

#include "Student_info.h"  // Student_info

double optimistic_median(const Student_info&);

#endif // GUARD_OPTIMISTIC_MEDIAN_H


#### optimistic_median_analysis.h

#ifndef GUARD_OPTIMISTIC_MEDIAN_ANALYSIS_H
#define GUARD_OPTIMISTIC_MEDIAN_ANALYSIS_H

// optimistic_median_analysis.h

#include <vector>

double optimistic_median_analysis(const std::vector<Student_info>&);

#endif // GUARD_OPTIMISTIC_MEDIAN_ANALYSIS_H


#### Student_info.h

#ifndef GUARD_STUDENT_INFO_H
#define GUARD_STUDENT_INFO_H

// Student_info.h
#include <iostream>
#include <string>
#include <vector>

struct Student_info
{
std::string name;
double midterm, final;
std::vector<double> homework;
};

bool compare(const Student_info&, const Student_info&);

#endif // GUARD_STUDENT_INFO_H


#### write_analysis.h

#ifndef GUARD_WRITE_ANALYSIS_H
#define GUARD_WRITE_ANALYSIS_H

// write_analysis.h

#include <iostream>  // ostream;
#include <vector>  // vector
#include <string>  // string
#include "Student_info.h"  // Student_info

void write_analysis(std::ostream&,
const std::string&,
double analysis(const std::vector<Student_info>&),
const std::vector<Student_info>&,
const std::vector<Student_info>&);

#endif // GUARD_WRITE_ANALYSIS_H


## Test Program

I now submit a set of hypyethetical student grades. As expected, the optimistic scheme (3rd one), gives higher median grades for the students who didn’t do all the homework.

pete 100 100 100 100 100
jon 90 90 0 0 0
mary 50 50 50 50 50
anna 40 40 0 0 0
gary 80 80 0 80 0
bob 100 100 100 0 0
ken 20 88 99 44 66
jay 99 39 40 80 0
bill 20 88 0 39 0
^Z
^Z
median: median(did) = 65.6: median(didnt) = 49.7
average: median(did) = 67.0667: median(didnt) = 52.7
median of homework turned in: median(did) = 65.6: median(didnt) = 57.1


# Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

# Accelerated C++ Solution to Exercise 6-0 (Part 4 / 7)

This is Part 4 of the 7-part Exercise 6-0. Click here to see the other parts.

# Exercise 6-0 (Part 4 / 7)

Relating to section 6.1.3 of the textbook (page 105-109). Implement and test out the “Finding URLs” program. The program scans a line of input text, and automatically detect and display all the URL addresses within that line of text.

## The Project

This section summarises the partitioned program in the form of C++ source and header files.

### Source Files

#### main.cpp

#include <iostream>  // cin, cout, endl
#include <string>  // string
#include <vector>  // vector
#include "find_urls.h"  // find_url
#include "vcout.h"  // vcout

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
cout << "Enter a line. This program automatically find URLs..." << endl;

// Read a line of input, then find and display URLs.
string line;
vector<string> urls;
while (getline(cin, line)) {
vector<string> urls = find_urls(line);
vcout(urls);
}

return 0;
}


#### find_urls.cpp

#include <string>  // string
#include <vector>  // vector
#include "url_beg.h"  // url_beg
#include "url_end.h"  // url_end

using std::string;
using std::vector;

vector<string> find_urls(const string& s)
{
vector<string> ret;
typedef string::const_iterator iter;
iter b = s.begin(), e = s.end();

// look through the entire input
while (b != e) {

// look for one or more letters followed by ://
b = url_beg(b, e);

// if we found it
if (b != e) {
// get the rest of the URL
iter after = url_end(b, e);

// remember the URL
ret.push_back(string(b, after));

// advance b and check for more URLs on this line
b = after;
}
}
return ret;
}


#### not_url_char.cpp

<br />#include <string>          // string, isalnum
#include <algorithm>       // find

using std::string;

bool not_url_char(char c)
{
// characters, in addition to alphanumerics, that can appear in a URL
static const string url_ch = "~;/?:@=&\$-_.+!*'(),";

// see whether c can appear in a URL and return the negative
return !(isalnum(c) || find(url_ch.begin(), url_ch.end(), c) != url_ch.end() );
}



#### url_beg.cpp

#include <string>  // string, isalpha
#include <algorithm>  // search
#include "not_url_char.h"  // not_url_char

using std::string;

string::const_iterator
url_beg(string::const_iterator b, string::const_iterator e)
{
static const string sep = "://";
typedef string::const_iterator iter;

// i marks where the separator was found
iter i = b;

while ((i = search(i, e, sep.begin(), sep.end() )) != e) {

// make sure the separator isn't at the beginning or end of the line
if (i != b && i + sep.size() != e) {

// beg marks the beginning of the protocol-name
iter beg = i;
while (beg != b && isalpha(beg[-1]))
--beg;

// is there at least one appropriate character before and after the separator?
if (beg != i && !not_url_char(i[sep.size()]))
return beg;
}

// the separator we found wasn't part of a URL; advance i past this separator
i += sep.size();
}
return e;
}


#### url_end.cpp

#include <string>  // string
#include <vector>  // vector
#include <algorithm>  // find_if
#include "not_url_char.h"  // not_url_char

using std::string;

string::const_iterator
url_end(string::const_iterator b, string::const_iterator e)
{
return find_if(b, e, not_url_char);
}


#### vcout.cpp

#include <iostream>
#include <string>    // string
#include <vector>    // vector

using std::cout;
using std::endl;
using std::string;
using std::vector;

int vcout(const vector<string>& v)
{
for (vector<string>::const_iterator i = v.begin(); i != v.end(); ++i)
cout << (*i) << endl;

return 0;
}


#### find_urls.h

#ifndef GUARD_FIND_URLS_H
#define GUARD_FIND_URLS_H

#include <vector>
#include <string>

std::vector<std::string> find_urls(const std::string&);

#endif // GUARD_FIND_URLS_H


#### not_url_char.h

#ifndef GUARD_NOT_URL_CHAR_H
#define GUARD_NOT_URL_CHAR_H

bool not_url_char(char);

#endif // GUARD_NOT_URL_CHAR_H


#### url_beg.h

#ifndef GUARD_URL_BEG_H
#define GUARD_URL_BEG_H

std::string::const_iterator
url_beg(std::string::const_iterator, std::string::const_iterator);

#endif // GUARD_URL_BEG_H


#### url_end.h

#ifndef GUARD_URL_END_H
#define GUARD_URL_END_H

#include <string>

std::string::const_iterator
url_end(std::string::const_iterator, std::string::const_iterator);

#endif // GUARD_URL_END_H


#### vcout.h

#ifndef GUARD_VCOUT_H
#define GUARD_VCOUT_H

#include <string>
#include <vector>

int vcout(const std::vector<std::string>&);

#endif // GUARD_VCOUT_H


## Test program

Let’s do some simple tests:

• Submitting the line “Have you tried http://google.co.uk and http://bbc.co.uk ?”, the program should return: “http://google.co.uk” and “http://bbc.co.uk”.
• Submitting the line “Have you tried http:// or google.co.uk or http://google.co.uk ?”, the program should return: “http://google.co.uk”.
• Submitting the line “Have you tried http or :// or http://bbc.co.uk ?”, the program should return: “http://bbc.co.uk “.

# Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

# Accelerated C++ Solution to Exercise 6-0 (Part 3 / 7)

This is Part 3 of the 7-part Exercise 6-0. Click here to see the other parts.

# Exercise 6-0 (Part 3 / 7)

Relating to section 6.1.2 of the textbook (page 105). Implement and test out the home-made isPalindrome function (created using the equal utility). Note that this is a more neat / compact version to the created in my previous Solution to Exercise 5-10.

## The Project

This section summarises the partitioned program in the form of C++ source and header files.

### Source Files

#### main.cpp

#include <iostream>  // cin, cout, endl
#include <string>  // string
#include <vector>  // vector
#include "vcout.h"  // vcout
#include "isPalindrome.h"   // isPalindrome

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
string word;
vector<string> words;
vector<string> palindromes;

// Populate vector
while (cin >> word) {
if (isPalindrome(word))
palindromes.push_back(word);
}

// Print palindrome
cout << "\nThese are the palindromes identified: " << endl;
vcout(palindromes);

return 0;
}


#### isPalindrome.cpp

#include <string>

using std::string;

bool isPalindrome(const string& s)
{
return equal(s.begin(), s.end(), s.rbegin() );
}


#### vcout.cpp

#include <iostream>
#include <string>    // string
#include <vector>    // vector

using std::cout;
using std::endl;
using std::string;
using std::vector;

int vcout(const vector<string>& v)
{
for (vector<string>::const_iterator i = v.begin(); i != v.end(); ++i)
cout << (*i) << endl;

return 0;
}


#### isPalindrome.h

#ifndef GUARD_ISPALINDROME_H
#define GUARD_ISPALINDROME_H

#include <string>

bool isPalindrome(const std::string&);

#endif // GUARD_ISPALINDROME_H


#### vcout.h

#ifndef GUARD_VCOUT_H
#define GUARD_VCOUT_H

#include <string>
#include <vector>

int vcout(const std::vector<std::string>&);

#endif // GUARD_VCOUT_H


## Test Program

I know enter a list of words. The program should automatically identify and display the palindrome. Note that for simplicity sake the program is case sensitive – in this test I shall strictly stick to lower case letters. I shall type in the following lines:

• good morning bob
• lol what a beautiful moon
• eeeeeeeee aaaaaaa banana

The the program should identify these words as palindromes (as they spell the same in both directions): bob, lol, a, eeeeeeeee, aaaaaaa

good morning bob
lol what a beautiful moon
eeeeeeeee aaaaaaa banana
^Z

These are the palindromes identified:
bob
lol
a
eeeeeeeee
aaaaaaa


# Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

# Accelerated C++ Solution to Exercise 6-0 (Part 2 / 7)

This is Part 2 of the 7-part Exercise 6-0. Click here to see the other parts.

# Exercise 6-0 (Part 2 / 7)

Relating to section 6.1.1 of the textbook (page 103-105). Implement and test out an alternative way to split a line into words using the find_if utility from the <algorithm> directive. The original split function method was first introduced in S5.6/88 of the book.

## The Project

This section summarises the partitioned program in the form of C++ source and header files.

### Source Files

#### main.cpp

</p>

<h1>include &lt;iostream&gt;</h1>

<h1>include &lt;string&gt;</h1>

<h1>include &lt;vector&gt;</h1>

<h1>include &quot;vcout.h&quot;</h1>

<h1>include &quot;split.h&quot;</h1>

<p>using std::string;
using std::vector;
using std::cin;
using std::cout;
using std::endl;</p>

<p>int main()
{
// Read a line of input, split into words, and display
string line;
vector&lt;string&gt; words;
while (getline(cin, line)) {
vector&lt;string&gt; words = split(line);
vcout(words);
}</p>

<pre><code>return 0;
</code></pre>

<p>}</p>

<p>

#### split.cpp

</p>

<h1>include &lt;string&gt;    // string</h1>

<h1>include &lt;vector&gt;    // vector</h1>

<h1>include &lt;cctype&gt;    // isspace</h1>

<h1>include &lt;algorithm&gt;  // find_if</h1>

<p>using std::vector;
using std::string;
using std::isspace;
using std::find_if;</p>

<p>// true if the argument is whitespace, false otherwise
// (S6.1.1/103)
bool space(char c)
{
return isspace(c);
}</p>

<p>// false if the argument is whitespace, true otherwise
// (S6.1.1/103)
bool not_space(char c)
{
return !isspace(c);
}</p>

<p>// Scan a line and split into words. Return a vector that contains these words.
// (S6.1.1/103)
vector&lt;string&gt; split(const string&amp; str)
{
typedef string::const_iterator iter;
vector&lt;string&gt; ret;</p>

<p>iter i = str.begin();
while (i != str.end()) {</p>

i = find_if(i, str.end(), not_space);

// Find end of next word
iter j = find_if(i, str.end(), space);

// Copy the characters in ([i, j)
if (i != str.end())
ret.push_back(string(i, j));

// Re-initialize
i = j;
</code></pre>

<p>}
return ret;
}</p>

<p>

#### vcout.cpp

</p>

<h1>include &lt;iostream&gt;</h1>

<h1>include &lt;string&gt;    // string</h1>

<h1>include &lt;vector&gt;    // vector</h1>

<p>using std::cout;
using std::endl;
using std::string;
using std::vector;</p>

<p>int vcout(const vector&lt;string&gt;&amp; v)
{
for (vector&lt;string&gt;::const_iterator i = v.begin(); i != v.end(); ++i)
cout &lt;&lt; (*i) &lt;&lt; endl;</p>

<p>return 0;
}</p>

<p>

#### split.h

</p>

<h1>ifndef GUARD_SPLIT_H</h1>

<h1>define GUARD_SPLIT_H</h1>

<h1>include &lt;vector&gt;</h1>

<h1>include &lt;string&gt;</h1>

<p>std::vector&lt;std::string&gt; split(const std::string&amp;);</p>

<h1>endif // GUARD_SPLIT_H</h1>

<p>

#### vcout.h

</p>

<h1>ifndef GUARD_VCOUT_H</h1>

<h1>define GUARD_VCOUT_H</h1>

<h1>include &lt;string&gt;</h1>

<h1>include &lt;vector&gt;</h1>

<p>int vcout(const std::vector&lt;std::string&gt;&amp;);</p>

<h1>endif // GUARD_VCOUT_H</h1>

<p>

## Test Program

By entering a text line, say, “The quick brown fox jumped over the fence”, the program should be able to dice in into words and display accordingly.

The quick brown fox jumped over the fence
The
quick
brown
fox
jumped
over
the
fence
^Z


# Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

# Accelerated C++ Solution to Exercise 6-0 (Part 1 / 7)

This is Part 1 of the 7-part Exercise 6-0. Click here to see the other parts.

# Exercise 6-0 (Part 1 / 7)

Relating to section 6.1 of the textbook (page 101-103). There are many ways to append elements from container B to container A (the base). In this post I shall implement and test out 3 known ways to do this: (1) pusb_back method, (2) insert method, and (3) copy method. The test confirms that all 3 methods produce the same results.

## The Project

This section summarises the partitioned program in the form of C++ source and header files.

### Source Files

#### main.cpp

#include <iostream>     // cin, cout, endl
#include <string>       // string
#include <vector>       // vector
#include <algorithm>    // copy
#include "vcout.h"      // vcout

using std::string;
using std::vector;
using std::cin;
using std::cout;
using std::endl;

int main()
{
string word;               // a word

vector<string> wordCollectionA;    // a collection of words
cout << "Define vector<string> wordCollectionA below..." << endl;
// Populate wordCollectionA.
while (cin >> word)
wordCollectionA.push_back(word);
cin.clear();

vector<string> wordCollectionB;    // another collection of words
cout << "Define vector<string> wordCollectionB below..." << endl;
// Populate wordCollectionB.
while (cin >> word)
wordCollectionB.push_back(word);
cin.clear();

// Test appending using the push_back method
vector<string> baseForPushBack = wordCollectionA;
for (vector<string>::const_iterator i = wordCollectionB.begin();
i != wordCollectionB.end(); ++i)
baseForPushBack.push_back(*i);

// Test appending using the insert method
vector<string> baseForInsert = wordCollectionA;
baseForInsert.insert(baseForInsert.end(), wordCollectionB.begin(), wordCollectionB.end());

// Test appending using the copy method
vector<string> baseForCopy = wordCollectionA;
copy(wordCollectionB.begin(), wordCollectionB.end(),
back_inserter(baseForCopy) );

// Display results
cout << "Append wordCollectionB to wordCollectionA with push_back method..."
<< endl;
vcout(baseForPushBack);
cout << "Append wordCollectionB to wordCollectionA with insert method..."
<< endl;
vcout(baseForInsert);
cout << "Append wordCollectionB to wordCollectionA with copy method..."
<< endl;
vcout(baseForCopy);

return 0;
}


#### vcout.cpp

#include <iostream>
#include <string>    // string
#include <vector>    // vector

using std::cout;
using std::endl;
using std::string;
using std::vector;

int vcout(const vector<string>& v)
{
for (vector<string>::const_iterator i = v.begin(); i != v.end(); ++i)
cout << (*i) << endl;

return 0;
}


#### vcout.h

#ifndef GUARD_VCOUT_H
#define GUARD_VCOUT_H

#include <string>
#include <vector>

int vcout(const std::vector<std::string>&);

#endif // GUARD_VCOUT_H


## Result

The test demonstrates that all 3 methods are equivalent – they produce the same result and serve the same purpose. i.e. appending elements to the base container.

Imagine:

• We have a vector<string> wordCollectionA container that contains the string elements “Item0” and “Item1”.
• We have a vector<string> wordCollectionB container that contains the string elements “Item2”, “Item3” and “Item4”.
• Appending the elements in wordCollectionB to the (base) wordCollectionA should result in A containing “Item0”, “Item1”, “Item2”, “Item3” and “Item4”.
Define vector<string> wordCollectionA below...
Item0
Item1
^Z
Define vector<string> wordCollectionB below...
Item2
Item3
Item4
^Z
Append wordCollectionB to wordCollectionA with push_back method...
Item0
Item1
Item2
Item3
Item4
Append wordCollectionB to wordCollectionA with insert method...
Item0
Item1
Item2
Item3
Item4
Append wordCollectionB to wordCollectionA with copy method...
Item0
Item1
Item2
Item3
Item4


# Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000