Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Hey guys, I am studying the problems solving with C++ book. However, I am stuck

ID: 3557839 • Letter: H

Question

Hey guys,

I am studying the problems solving with C++ book. However, I am stuck in one of the book's projects and I need some help please. Basically I have a file which is called address.xmi. This file contains some information.( I will copy and paste the file in here). However this project has two parts; the first one is to write a small program outputting the names and address of everyone in Palmdale(a city in the address file). The second part is to write a small program that reads in the file address.xmi and output the name and address of everyone whose zip code falls within the range 90210 through 90214.

the file

<?xml version="1.0"?>
<address_book>
<contact>
<name>George Clooney</name>
<street>1042 El Camino Real</street>
<city>Beverly Hills</city>
<state>CA</state>
<zip>90214</zip>
</contact>
<contact>
<name>Cathy Pearl</name>
<street>405 A St.</street>
<city>Palmdale</city>
<state>CA</state>
<zip>93352</zip>
</contact>
<contact>
<name>Paris Hilton</name>
<street>200 S. Elm St.</street>
<city>Beverly Hills</city>
<state>CA</state>
<zip>90212</zip>
</contact>
<contact>
<name>Wendy Jones</name>
<street>982 Boundary Ave.</street>
<city>Palmdale</city>
<state>CA</state>
<zip>93354</zip>
</contact>
</address_book>

in case you have the book it is chapter 8 project 14 page 491.

This is my first question, thus I am sorry for any mistakes.

I will appreciate any help :)

thanks a lot

Explanation / Answer

#include <fstream>

#include <iostream>

#include <string>

using namespace std;

// Reads the next contact record, returning true if found or false if no

// more records are available

bool read_next_contact(ifstream &in, string &name, string &street,

       string &city, string &state, string &zip);

// Prints the given contact

void print_contact(string &name, string &street,

  string &city, string &state, string &zip);

// Prints all of the addresses with the given city

void find_city(char file_name[], char city[]);

// Prints all of the addresses in the given range of zip codes (inclusive)

void find_in_zip_range(char file_name[], int zip1, int zip2);

// Returns true if tofind is a substring of str. Will return false if

// tofind is empty.  This is equivalent to:

//

//      (str.find(tofind) != string::npos)

//

bool contains(string str, string tofind);

int main()

{

    // Look for addresses in Palmdale

    cout << "Addresses in Palmdale: " << endl << endl;

find_city("address.xml", "Palmdale");

    // Then look for addresses with zip codes between 90210 and 90214

    cout << endl << "Addresses with zip codes between 90210 and 90214: "  

<< endl << endl;

    find_in_zip_range("address.xml", 90210, 90214);

    return 0;

}

// Prints all of the addresses with the given city

void find_city(char file_name[], char city_to_find[])

{

    ifstream in;

    string name, street, city, state, zip;

    in.open(file_name);

    if (in.fail())

    {

cout << "Could not open input file" << endl;

exit(1);

    }

    while (read_next_contact(in, name, street, city, state, zip))

    {

if (city == city_to_find)

{

    print_contact(name, street, city, state, zip);

}

    }

    in.close();

}

// Prints all of the addresses in the given range of zip codes (inclusive)

void find_in_zip_range(char file_name[], int zip1, int zip2)

{

    ifstream in;

    string name, street, city, state, zip;

    in.open(file_name);

    if (in.fail())

    {

cout << "Could not open input file" << endl;

exit(1);

    }

    while (read_next_contact(in, name, street, city, state, zip))

    {

int zipInt = atoi(zip.c_str());

if ((zipInt >= zip1) && (zipInt <= zip2))

{

    print_contact(name, street, city, state, zip);

}

    }

    in.close();

}

// Reads the next contact record, returning true if found or false if no

// more records are available

bool read_next_contact(ifstream &in, string &name, string &street,

       string &city, string &state, string &zip)

{

    string line;

    bool result = false;

    // Clear the strings

    name.erase(0, name.length());

    street.erase(0, street.length());

    city.erase(0, city.length());

    state.erase(0, state.length());

    zip.erase(0, zip.length());

    // Find the next contact record, or the end of the file

    getline(in, line);

    while ((! contains(line, "contact")) &&  

   (! contains(line, "/address_book")))  

    {

        getline(in, line);

    }

    if (! contains(line, "/address_book"))

    {

// Keep going until we hit the </contact> tag

        getline(in, line);

        while (! contains(line, "/contact"))

{

    int tagStart = line.find("<");

    int tagEnd = line.find(">");

    if (contains(line, "<"))

    {

string tag = line.substr(tagStart + 1, tagEnd - tagStart - 1);

int closeTag = line.find("</");

string value = line.substr(tagEnd + 1, closeTag - tagEnd - 1);

if (tag == "name")

    name = value;

else if (tag == "street")

    street = value;

else if (tag == "city")

    city = value;

else if (tag == "state")

    state = value;

else if (tag == "zip")

    zip = value;  

    }

            getline(in, line);

}  

result = true;

    }

    return result;

}

void print_contact(string &name, string &street,

  string &city, string &state, string &zip)

{

    cout << name << endl;

    cout << street << endl;

cout << city << ", " << state << " " << zip << endl << endl;

}

// Returns true if tofind is a substring of str. Will return false if

// tofind is empty.  

bool contains(string str, string tofind)

{

    // The string class provides an easier way of doing this, but it

    // is not discussed in the text. The standard str.find(tofind)

    // member function will return a value between 0 and one less than

    // the length of the string if tofind is a substring of str. Otherwise,

    // find will return the special value string::npos. Hence this

    // function could be implemented in a single line as:

    //

    //    return (str.find(tofind) != string::npos);

    bool found = false;

    int lastPosToCheck = str.length() - tofind.length();

    if (tofind.length() > 0)

    {

        for (int i = 0; (i <= lastPosToCheck) && (! found); i++)  

{

    // See if we can find a match for the first character

    if (str[i] == tofind[0])

    {

// Then iterate through any remaining characters

// in tofind

bool ok = true;

for (int j = 1; (j < tofind.length()) && ok; j++)

{

    ok = (str[i + j] == tofind[j]);

}

found = ok;

    }

}

    }

    return found;

}