Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

A Simple City List Manager

4.13/5 (10 votes)
9 Oct 2014CPOL7 min read 48.3K   886  
A small program in C++. A city list manager.

Image 1

City list manager interface

Introduction

The main goal of this article is to show  to a beginner programmer some basic aspects of C++ language through a small program to manage a city list.

Background

I will tell you a small story about the scope of this program. I think that it is most interesting to know why something was created. This history is imaginary.

Lucy works in a net laundry that takes away dirty clothes and delivers clean clothes to customer homes. Each branch serves its own city and its contiguous cities. Today, people call to request the service and Lucy verifies in a book if the solicitant city is attended by some branch laundry.

To search the attended city name in the book makes the service a little slow and the customer needs to hold on. Then Lucy imagined that she could use a software to execute this search that would save some precious minutes in each call.

Lucy explained to the programmer that she needed the following features in this program:

Inclusion: this list is frequently updated because the new cities are attended and new branches are launched. So it is necessary that there is a feature that allows the user to include new cities. Name is the unique information needed.

Edition: it is needed to have an option to edit the city name because sometimes the name is incorrect and Lucy needs to execute the corrections.

Report: it is a city list in which it is possible to search a city by name or part name. This is the feature that will be used by Lucy when she receives one call and it is necessary to verify if caller city is attended.

Exclusion: it allows users to remove cities. Sometimes a branch is closed or a specific city is left to be attended.

With the information in your hand, the programmer starts to work.

Using the Code

The programmer chooses to use the C++ language and some object oriented concepts. The city list will be kept in a text file. The defined classes to solve this problem are: City, CityList, and UserInterface.

City is the class used to represent a city. It has a property to store the city name and method to show the name city using a specific format defined by Lucy.

Image 2

The City class struct

The name property is public and keeps the city name. ShowCity() prints the city name between clasps. Between the claps there will be 30 characters. To complete empty characters between these two clasps will be used a point character.

See below a simple usage of the City class:

C++
//
// City class usage sample
// 
#include "city.h"
.
.
.
City temp_city;
temp_city.name = "SAO_PAULO/SP";
temp_city.ShowCity();

The result will be:

Image 3

Use of City class

The code of the method to print a city name is:

C++
void City::ShowCity()
{
     std::cout << "["; 
     std::cout.width(32);
     std::cout.fill('.');
     std::cout << std::left << name;  
     std::cout << std::right;
     std::cout << "]" << std::endl;
}

CityList is the class responsible to manage a list of City objects.

Image 4

The CityList class struct

The CityList class properties are city_list and filter:

city_list: it is a list (STL) of pointers to City objects and it is used to keep a city list. This is a public property.

C++
list <City> city_list;

filter: it is a string property that contains the city name or part to filter the city list.

CityList class methods are:

Add(new_city): this method adds a pointer to a City object into CityList.city_list. The new_city parameter is a pointer to a City object.

C++
void CityList::Add(City *new_city)
{
     city_list.push_front(*new_city);
}

Show(): this method runs CityList.city_list and calls the method City.ShowCity() for each list item. If the filter property is not empty, the method will search by city name to verify if City.name contains CityList.filter. This method shows the city position index in the list. This index is useful to the user to refer a city to edit or exclude.

C++
void CityList::Show()
{
     list<City>::iterator i;
     int id = 1;     
     for(i = city_list.begin(); i != city_list.end(); i++)
     {
           if(i->name.find(filter) != std::string::npos)
           {
                     std::cout.width(4);
                     std::cout.fill('0');
                     std::cout << id << ".";
                     i->ShowCity();       
           }
           id++;
     }
}

Image 5

Result of CityList.Show call

Save(): this method runs CityList.city_list and saves the text in a text file called city.txt. This file is the database of this application and stays in the same folder of the program.

C++
void CityList::Save()
{
     std::ofstream s("city.txt", std::ios::trunc);
     
     list<City>::iterator i;

     
     for(i = city_list.begin(); i != city_list.end(); i++)
     {     
           s << i->name << std::endl;       
           
     };
     
     s.close();
}

Image 6

File saved by class CityList

Load(): this method scans the text file lines and creates City objects and adds to CityList using the method CityList.Add(). This method is used when the program is started to load initial city list.

C++
void CityList::Load()
{
     std::ifstream s("city.txt");

     std::string aux = "";
    
     s >> aux;           
     while(!s.eof()) 
     {
         City *city = new City();
         city->name = aux;
         Add(city);            
         s >> aux;           
     };
     
     s.close();
}

Del(del_pos): it removes an element from CityList.city_list using the position provided by the del_pos parameter. The user views a city position, showed by CityList.Show(), considering the first list index as 1 (one) (but the initial list index is zero). The CityList.Del method is responsible for deleting the right index.

C++
void CityList::Del(int del_pos)
{   
     list<City>::iterator i;
     i = city_list.begin();
     int aux = 0;
     
     while(i != city_list.end() && aux < del_pos - 1)
     {     
           i++;
           aux++;
           
     };
     
     city_list.erase(i);
}

Edit(edit_pos, new_name): it changes the City object name at the edit_pos parameter position in the list. In the same way that the user chooses the city to be excluded, the user could cause the city to be updated. The user also needs to inform the new name through the new_name parameter.

C++
void CityList::Edit(int edit_pos, std::string new_name)
{   
     list<City>::iterator i;
     i = city_list.begin();
     int aux = 0;
     
     while(i != city_list.end() && aux < edit_pos - 1)
     {     
           i++;
           aux++;
           
     };
     
     i->name = new_name;
}

The UserInterface class makes the communication with the user, presenting the screens and inputs to the user to execute actions on the city list.

Image 7

The UserInterface class struct

Header(): this method is used to show a header in the screens where there is an interaction with the user. This method allows that any change in the header could reflect in all system, by changing at one point.

C++
void UserInterface::Header()
{
     std::cout << "City" << std::endl;
     std::cout << "----" << std::endl << std::endl;     
}

MainMenu(CityList): it receives a CityList pointer that is used during program execution to keep the city list updated. This method presents the main menu and it is responsible for a loop that waits for user commands. The command options are:

  • [1] New City: include a new city;
  • [2] Report: show city list;
  • [6] Exit: close the program.

Image 8

The main menu
C++
void UserInterface::MainMenu(CityList *c)
{
 int option = 0;
 
 while(option != 6)
 {
     system("cls");
     Header();
     std::cout << "[1] New city" << std::endl;
     std::cout << "[2] Report" << std::endl;
     std::cout << "[6] Exit" << std::endl << std::endl;
     std::cout << "Enter 1-6 option:";
    
      std::cin >> option;
      switch(option)
      {
       case 1:
            frmNew(c);
            option = 0;
            break;
       case 2:
            frmReport(c);
            option = 0;
            break;
      }
 };
};

frmNew(CityList): It is the method used to show the interface with the user and it is used by the user to input a new city name.

 

Image 9

The new city interface
C++
void UserInterface::frmNew(CityList *c)
{
     system("cls");     
     std::string cityName = "";
     Header();
     std::cout << "City name: ";
     std::cin >> cityName;     
     
     City *city = new City();
     city->name = cityName;
     c->Add(city);
     std::cout << std::endl;
     system("pause");    
};

frmReport(CityList): this method shows the city list according to the current filter. (CityList.filter – city that contains this text in its name). This method executes a loop to wait a user command.

Image 10

City report

The frmReport method shows the city position in the list to the user indicating what city will receive the command: edition (option 2) or exclusion (option 3). Option 1 is used to clear the current filter.

Image 11

City edition interface

Option 4 allows the user to type a text to be used as a filter. For example, if the user types “PIRA”, cities as “PIRACICABA” and “ITAPIRA” will be showed. Finally, option 6 takes you back to the main menu.

C++
void UserInterface::frmReport(CityList *c)
{
     int option = 0;
     int aux = -1;
     std::string new_name = "";

     while (option != 6)
     {
          system("cls");     
          Header();
          c->Show();
          std::cout << std::endl;
          std::cout << std::endl << "[1] Clear Filter ";
          std::cout << std::endl << "[2] Edit ";
          std::cout << std::endl << "[3] Delete ";
          std::cout << std::endl << "[4] Search ";
          std::cout << std::endl << "[6] Exit" << std::endl << std::endl;
          std::cout << "Enter 1-6 option:";

           std::cin >> option;     

           switch(option)
           {
               case 1:
                    c->filter = "";
                    break;
               case 2:
                    std::cout << std::endl <<  "Type city pos to be update: ";
                    std::cin >> aux;                    
                    std::cout << std::endl <<  "Type new city name: ";
                    std::cin >> new_name;
                    
                    c->Edit(aux, new_name);
                    c->Save();                         
                    std::cout << std::endl << "Updated successfully!" << std::endl;
                    system("PAUSE");
                    break;           
               case 3:
                    std::cout << std::endl <<  "Type city pos to be removed: ";
                    std::cin >> aux;
                    if(Util::Confirm("Confirm this exclusion operation?"))
                    {
                         c->Del(aux);
                         c->Save();                         
                         std::cout << std::endl << "Removed successfully!" << std::endl;
                         system("PAUSE");
                    };
                    break;      
                case 4:
                    std::cout << std::endl <<  "Type city name or part to be searched: ";
                    std::cin >> c->filter;
                    break;      
           };    
     };
};

Points of Interest

This article could be extended much more but the main goals were achieved:

  1. Complete (start and finish) a C++ program. Perhaps not in an elegant way as the programmer would desire, but the program is ready in his favourite language.
  2. Write this article that describes the program. Experienced programmers could think of this article as a joke, but perhaps for a beginner programmer this article could be an inspiration.
  3. Other important points of this work were to learn small things about C++:
    C++
    std::cout.width(3);
    std::cout << "12345";

    If my first theory was correct, the result presented by this code would be: “123”. But the result was “12345”. The idea of cout.width is to say the maximum quantity of output characters but in the case of text output greater than determined characters quantity, the text is shown completely. Together with cout.fill, it is possible to inform what character is going to complete the text right or left. Remember that cout.width and cout.fill affects only the next cout output.

    C++
    //Define the width to next text output
    std::cout.width(10);           
    //Define completation character
    std::cout.fill('-');           
    //Completation orientation (left) and text output
    std::cout << left <<"12345";   
    std::cout << std::endl;        
    std::cout.width(10);        
    std::cout.fill('*');    
    //Text to be affected "ABCDE" 
    //Text does not affected by width and fill
    std::cout << right <<"ABCDE" << "XGGG"; 
    std::cout << std::endl;

    The output for example above is:

    Image 12

    cout example

    These features were used to obtain a better visual effect on the city list, presenting them in an aligned way.

    • - cout.width and cout.fill: At a glance the method cout.width would be used to define the quantity of characters to be showed on the output. But this theory was wrong. Consider the code below:
    • - std::npos: in std::string, there is a method called find that searches a text in a string and in case it finds the method return the position of text found. Sometimes the text is not found. To check this condition, text not found, the find method returns std::npos that represents a value that can change depending on implementation. std::npos represents the max size of t_size.
    • - list.erase: the erase method allows to exclude a list element from an iterator or a pair of iterators. In a different way, remove method uses a value to delete a list item.
  4. Ah! Lucy is happy too. The program is being used by her and a meeting is scheduled to discuss improvements. Perhaps we will have material for a new article after this meeting.

History

First version completed: Jul 6, 2012.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)