2014-10-12 2 views
0

У меня есть два вопроса. 1. Я использую самый эффективный контейнер для хранения [double, object *]? 2. Если Map - это выбор, который я должен использовать, как в мире я могу получить доступ к объекту, который указывает тоже, как только он находится на карте? Я пытаюсь распечатать карту в функции printMap() без всякой удачи. Пробовал несколько вариантов.Контейнер для двойника и указатель C++?

void printMap() { //How do i verify what's in my map??!!!!!!!!!!!!!!!!!!!!!!!! 
      for (it = cDatabase.begin(); it != cDatabase.end(); it++) 
      { 
       double temp = 0; 
       temp = it->first; 
       cout << "Key: " << it->first << endl; 
       cout << cDatabase[it->first]->getFirstName(); 
      } 
     } 

Заранее спасибо

Эрик

PS: Я включил весь файл .cpp.

//Erik Plachta 
//Purpose: Creating a Customer Relations Management system. Should be able to create employees and customers that can we stored within a database. 

#include<fstream>  //for customer database 
#include<map>   //for customer database 
#include<sstream>  //for customer database 
#include<stdlib.h>  //for customer database 

#include <iostream> 
using namespace std; 

/////////////////////////////////////////////////////////////////////////////// 
/////EMPLOYEE///////////EMPLOYEE////////////EMPLOYEE/////////EMPLOYEE////////// 
/////////////////////////////////////////////////////////////////////////////// 
class Employee { 

    string firstName, lastName, password, username; //used to create unique sessions for each user. Login info 
    bool manager; //If manager, will have spec privlages within the app. 
    int sessionTime; //used to record login/logoff time. 

    public: 
     Employee(string FN, string LN, string pass, string userN) { //first name, last name and pass 
      setName(FN, LN); 
      setPassword(pass); 
      setUsername(userN); 
     } 

     string getName() { 
      string fullName = firstName + " " + lastName; 
      return fullName; 
     } 

     bool confirmPassword(string pass) { //used to test if true or false without giving program the password back. 
      bool status = false; 
      if (pass == password) { 
       status = true; 
      } 
      return status; 
     } 

     bool confirmUsername(string userN) { 
      bool status = false; 
      if (userN == username) { 
       status = true; 
      } 
      return status; 
     } 

    private: 
     void setName(string FN, string LN) { 
      firstName = FN; 
      lastName = LN;} 

     void setPassword (string pass) { 
      password = pass; 
     } 

     void setUsername(string userN) { 
      username = userN; 
     } 
}; 


void printEmployee(Employee employee) { //this is confirming the password entered was the same in the database. there will be a private database holding user login info 
    bool status; 
    cout <<"Name: " << employee.getName() << endl; 
    status = employee.confirmPassword("123456"); 
    cout << "Password test: " << status << endl; 
    status = employee.confirmUsername("EPlachta"); 
    cout << "Username test: " << status << endl; 
} 

/////////////////////////////////////////////////////////////////////////////// 
///CUSTOMER////////////CUSTOMER/////////CUSTOMER/////CUSTOMER//////CUSTOMER//// 
/////////////////////////////////////////////////////////////////////////////// 
class Customer { 
    string firstName, lastName, phoneNumber, eMail; 
    double customerNumber; 
    public: 
     Customer (string FN, string LN, string phoneN, string EM, double customerNum) { 
      setName(FN, LN); 
      setPhoneNumber(phoneN); 
      setEmail(EM); 
      setCustomerNumber(customerNum); 
     } 

     string getFirstName() { 
      return firstName; 
     } 

     string getLastName() { 
      return lastName; 
     } 

     string getPhoneNumber() { 
      return phoneNumber; 
     } 

     string getEmailAddress(){ 
      return eMail; 
     } 

     double getCustomerNumber() { 
      return customerNumber; 
     } 

     void printCustomer() { 
      cout << "First Name: " << getFirstName() << endl; 
      cout << "lastName: " << getLastName() << endl; 
      cout << "Email: " << getEmailAddress() << endl; 
      cout << "PhoneNumber: " << getPhoneNumber() << endl; 
      cout <<"CustomerNumber: "<< getCustomerNumber() << endl; 
     } 

    private: 
     void setName(string FN, string LN) { 
      firstName = FN; 
      lastName = LN; 
     } 

     void setPhoneNumber(string phoneN) { 
      phoneNumber = phoneN; 
     } 

     void setEmail(string EM) { 
      eMail = EM; 
     } 

     void setCustomerNumber(double customerNum) { 
      customerNumber = customerNum; 
     } 
} ; 

//print customer is uptop here for now. Will be put into it's own class 


/////////////////////////////////////////////////////////////////////////////// 
///CUSTOMER DATABASE///////////////CUSTOMER DATABASE///////CUSTOMER DATABASE/// 
/////////////////////////////////////////////////////////////////////////////// 

class CustomerDatabase { 
    double customerNumbers; // used to increment from 100000 - 99999. An easy way to give out new numbers and to prevent duplicates. 
    map <double, Customer*> cDatabase; 
    map <double, Customer*>:: iterator it; 

    public: 
     CustomerDatabase() { 
      customerNumbers = 100000; 
      loadCustomers(); 
     } 
     void printMap() { //How do i verify what's in my map??!!!!!!!!!!!!!!!!!!!!!!!! 
      for (it = cDatabase.begin(); it != cDatabase.end(); it++) 
      { 
       double temp = 0; 
       temp = it->first; 
       cout << "Key: " << it->first << endl; 
       cout << cDatabase[it->first]->getFirstName(); 
      } 
     } 
     double newCustomerNumber() { // Used to generate unique customer IDs easily. 
      double customerNumberHolder = customerNumbers; 
      customerNumbers++; 
      return customerNumberHolder; 
     }  

     bool saveCustomer(double customerN, Customer *c) { //saves customer to database once created **NOT WORKING YET 
      addCustomer(customerN, c); 
      ofstream databaseFile; //filestream local for output 
      bool saveCustomer = false; 
      if (checkForCustomerNumber(customerN) != false) { // if the customer isn't in the database 
       ostringstream stream; // USED TO MAKE AN INT INTO A STRING. Local stream to keep clear 
       stream << c->getCustomerNumber(); 
       databaseFile.open ("database/databaseFile.csv", ios::app); 
       string customerHolder = c->getFirstName() + "," + c->getLastName() + "," + c->getPhoneNumber() + "," + c->getEmailAddress() + "," + stream.str() + "\n" ; 
       databaseFile << customerHolder; 
       databaseFile.close(); 
       saveCustomer = true; 
      } 
      cout << "Customer saved Status: " << saveCustomer << endl; 
      return saveCustomer; 
     }   

     bool addCustomer(double customerN, Customer *c) { 
      bool addCustomer = false; 
      cDatabase[customerN] = c; 
      return addCustomer; 

     } 

    private: 

     bool loadCustomers() { 
      string firstN, lastN, phoneN, emailA; 
      double customerN; 
      const int FIRSTNAME = 0; 
      const int LASTNAME = 1; 
      const int PHONENUMBER = 2; 
      const int EMAIL = 3; 
      const int CUSTOMERNUMBER = 4; 
      //skipped 5 because every new line also runs through the while loop. 
      const int ADDTODATABASE = 5; 
      ifstream databaseFile; //file-stream local for input 
      databaseFile.open ("database/databaseFile.csv", ios::in); 
      string line = ""; 
      int i = 0; 
      double loadedCustomers = 0; //used to keep track of customer loaded. 
      while(getline(databaseFile, line, ',')) { 
       if (i == FIRSTNAME) { 
        firstN = line; 
        i++; 
       } else if (i == LASTNAME) { 
        lastN = line; 
        i++; 
       } else if (i == PHONENUMBER) { 
        phoneN = line; 
        i++; 
       } else if (i == EMAIL) { 
        emailA = line; 
        i++; 
       } else if (i == CUSTOMERNUMBER) { 
        double customerNumb = atoi(line.c_str()); 
        customerN = customerNumb; 
        Customer c(firstN, lastN, phoneN, emailA, customerN); 
        Customer *holder; 
        holder = &c; 
        addCustomer(c.getCustomerNumber(), holder); 
        i = 0; //resetting for next line. 
       } 
//this is how i was saving a customer to the database. I dont' need to save when loading customers. saving code incase needed//    saveCustomer(c.getCustomerNumber(), c);  
      } 
      databaseFile.close(); 
     } 

     bool checkForCustomerNumber(double customerN) { //If ID # is within the database, it will return a true that the ID exists 
      bool customerNumberMatch = false; 
      if((cDatabase.find(customerN)) != (cDatabase.end())) { //if the customer number is the key for the map, it will not reach the end. therein the customer is already in the database 
       customerNumberMatch = true; 
       customerNumbers++; 
      } 
      cout << "C. Number Match Satus: " << customerNumberMatch << endl; 
      return customerNumberMatch; 
     } 
}; 


/////////////////////////////////////////////////////////////////////////////// 
//MAIN////////////////MAIN/////////////MAIN////////////////MAIN/////////MAIN/// 
/////////////////////////////////////////////////////////////////////////////// 

int main() { 
    //CUSTOMER DATABASE CREATION 
    CustomerDatabase customerDatabase; //creating database 
    ////CUSTOMER 
    Customer JT("Johnny", "Tester", "989-123-4567", "[email protected]", customerDatabase.newCustomerNumber()); // used to create a test customer 

    Customer Test ("This", "is", "a", "test", 100000); 
    Customer TT("Timmy", "Tester", "989-989-9898", "[email protected]", customerDatabase.newCustomerNumber()); 
    //CUSTOMER DATABASE USED 
    Customer *holder; 
    holder = &JT; 
    customerDatabase.saveCustomer(holder->getCustomerNumber(), holder); 
    holder = &TT; 
    customerDatabase.saveCustomer(holder->getCustomerNumber(), holder); 
    holder = &Test; 
    customerDatabase.saveCustomer(holder->getCustomerNumber(), holder); 
    customerDatabase.printMap(); 
    //EMPLOYEE 
    Employee EP ("Erik", "Plachta", "123456", "EPlachta");      //creating test employee 
    // printEmployee(EP);               //making sure employee can login/was created correctly.  

    cin.get(); 
    return 0; 
} 

//Customer class looks at database for an ID it wants to use, 
+0

Вы можете использовать: 'it-> second-> getFirstName()'. Имейте в виду, что если вы попытаетесь воссоздать «ключ» с использованием математики, неточность типа данных сделает многие ключи практически невоспроизводимыми посредством вычисления. Итерация прекрасна, так как выполняется поиск диапазонов (меньше). – Galik

+1

Почему в мире вы используете 'double' для номеров клиентов? – o11c

+0

Хорошо. Спасибо, Галик. Не уверен o11c. –

ответ

0

Прежде чем приступить к выбору контейнеров, я хотел бы затронуть выбор типа данных для идентификационных номеров. Вы используете double, который является числом с плавающей запятой, но вам нужны только целые значения, поэтому было бы гораздо разумнее использовать целочисленный тип.

Выбор контейнера зависит от того, как вы планируете доступ к данным и их изменение в контейнере. К числу основных характеристик следует отнести следующие:

  1. Нужно ли иметь доступ к элементам в контейнере в случайной последовательности? То есть. искать элементы по ID? Контейнеры, которые хороши для этого, - карта, unordered_map, vector. Списки плохо для этого, потому что вам нужно будет пройти список, чтобы найти нужный элемент.

  2. Нужно ли выполнять итерирование значений в определенном порядке (например, порядок клавиш)? Контейнеры, которые подходят для этого, - это карта, вектор, различные типы списков.

  3. Нужно ли вставлять элементы в любом положении? Или достаточно вставить только в конце? Если прежний, то map, unordered_map, список хорош. Если последний, то вектор хорош.

  4. Какой тип ключа используется для поиска ценностей? Вы можете искать записи в векторе по целочисленному числу, но если у вас есть, например, строка, то вам нужно будет использовать карту или unordered_map.

  5. Если ключ является числовым - список разрежен? То есть. будут ли большие пробелы в последовательности? Если да, то вектор менее привлекателен, потому что может быть большое количество потерянной памяти.

характеристики для вас кажется:

  1. Вы должны быть в состоянии искать клиент по ID
  2. Вы должны быть в состоянии перебрать список, чтобы распечатать базу данных , Я не уверен, что это требование сделать это по порядку, но давайте предположим, что это так.
  3. Похоже, что вы добавляете новые записи в конце списка.
  4. Ключи являются целыми числами
  5. Я не уверен, что список будет разреженным. Если вы удалите много клиентов из середины, тогда могут быть пробелы.

Если бы не последняя точка, вектор мог бы быть лучшим выбором, чем карта. Векторы дешевы и имеют высокую производительность для большинства операций, которые вы будете использовать.

В любом случае, если вы решите, что карта лучше всего основана на том, что вы знаете о своем приложении, то, когда вы итерации по карте, итератор указывает на value_type контейнера, который в случае карты типа std :: pair, где K - тип ключа, а V - тип значения. Этот тип значения хранит ключ и значение, к которому вы обращаетесь, используя «первый» и «второй» члены.

for (it = cDatabase.begin(); it != cDatabase.end(); it++) { 
    cout << "Key: " << it->first << endl; 
    cout << it->second->getFirstName() << endl; 
} 
+0

Красивые. Изменил его на int, использовал код, который вы мне отправили, и он работает. Спасибо, Хармич. Не уверен, почему я выбрал двойным, чтобы быть честным. Просто подумал, если бы у меня было 10 000 клиентов, которых мне пришлось бы переписать программу. Ваши предположения были правильными в отношении моих намерений с программой. Похоже, что карта - лучший вариант для того, что я делаю. –

Смежные вопросы