2009-07-18 2 views
0

Я пытаюсь ввести форму проверки данных, в которой, когда пользователь вводит номер ISBN книги, если он уже был сохранен, тогда он выдает сообщение об ошибке. Однако у меня возникают проблемы с этим. Я не уверен, правильно ли я перегружал оператор ==, и я не уверен, как сравнивать векторные значения в функции store_ISBN().Сравнение значений, вводимых в значения в векторе

Вот код:

#include "std_lib_facilities.h" 

// Classes --------------------------------------------------------------------- 

class Book{ 
public: 
     vector<Book> books; // stores book information 
     Book() {}; // constructor 
     friend ostream& operator<<(ostream& out, const Book& b); 
     bool operator==(const Book& d); 
     string what_title(); 
     string what_author(); 
     int what_copyright(); 
     void store_ISBN(); 
     void is_checkout(); 
private: 
     char check; 
     int ISBNfirst, ISBNsecond, ISBNthird; 
     char ISBNlast; 
     string title; 
     string author; 
     int copyright; 
}; 

// Class Functions ------------------------------------------------------------- 

string Book::what_title() 
{ 
     cout << "Title: "; 
     getline(cin,title); 
     cout << endl; 
     return title; 
} 

string Book::what_author() 
{ 
     cout << "Author: "; 
     getline(cin,author); 
     cout << endl; 
     return author; 
} 

int Book::what_copyright() 
{ 
    cout << "Copyright Year: "; 
    cin >> copyright; 
    cout << endl; 
    return copyright; 
} 

void Book::store_ISBN() 
{ 
    bool test = false; 
    cout << "Enter ISBN number separated by spaces: "; 
    while(!test){ 
    cin >> ISBNfirst >> ISBNsecond >> ISBNthird >> ISBNlast; 
    for(int i = 0; i < books.size(); ++i) 
      if(ISBNfirst == books[i]) cout << "test"; // no idea how to implement this line    
    if((ISBNfirst<0 || ISBNfirst>9) || (ISBNsecond<0 || ISBNsecond>9) || (ISBNthird<0 || ISBNthird>9)) 
        error("Invalid entry."); 
    else if(!isdigit(ISBNlast) && !isalpha(ISBNlast)) 
      error("Invalid entry."); 
    else test = true;}  
    cout << endl; 
} 

void Book::is_checkout() 
{ 
    bool test = false; 
    cout << "Checked out?(Y or N): "; 
    while(!test){ 
    cin >> check; 
    if(check == 'Y') test = true; 
    else if(check == 'N') test = true;         
    else error("Invalid value.");} 
    cout << endl; 
} 

// Operator Overloading -------------------------------------------------------- 

bool Book::operator==(const Book& d){ // is this right??? 
    if((ISBNfirst == d.ISBNfirst) && (ISBNsecond == d.ISBNsecond) 
      && (ISBNthird == d.ISBNthird) && (ISBNlast == d.ISBNlast)) return true; 
    else return false; 
} 

ostream& operator<<(ostream& out, const Book& b){ 
     out << "Title: " << b.title << endl; 
     out << "Author: " << b.author << endl; 
     out << "ISBN: " << b.ISBNfirst << "-" << b.ISBNsecond << "-" << b.ISBNthird << "-" << b.ISBNlast << endl; 
     out << endl; 
     return out; 
} 

// Main ------------------------------------------------------------------------  

int main() 
{ 
    Book store; 
    string question; 
    while(true){ 
     store.what_title(); 
     store.what_author(); 
     store.what_copyright(); 
     store.store_ISBN(); 
     store.is_checkout(); 
     store.books.push_back(store); 
     cout << "Are you finished?(Y or N): "; 
     cin >> question; 
     if(question == "Y") break; 
     else if(question == "N"){ 
       cout << endl; 
       cin.ignore();} 
     else error("Invalid value."); 
     } 
    cout << endl; 
    cout << "Books stored -\n" << endl; 
    for(int i = 0; i < store.books.size(); ++i) 
      cout << store.books[i]; 
    keep_window_open(); 
} 

Обратите внимание, что в функции store_ISBN я только Тестам для одной переменной, так как я не хочу, чтобы впечатать все это, прежде чем я понять, как это сделать Это.

Как вы можете видеть каждый раз, когда книга проходит через петлю в основном, данные для этой книги хранятся. Затем я могу выводить все данные после цикла, перегружая оператор < < для печати Title, Author и ISBN. Поэтому я думаю, что я должен иметь доступ к этим отдельным данным в векторе для сравнения с пользователем ISBN, но я не знаю, как это сделать. Части, которые меня путают, были прокомментированы как таковые.

+0

Обратите внимание, что ваш цикл while является плохим; пожалуйста, используйте while (question! = "Y") вместо while (true). – jkeys

+0

также не используют «какие» префиксы, просто используйте имя переменной. Общее соглашение диктует, что каждый элемент данных отслеживает «_» (например, string title_;), а затем используйте имя без подчеркивания для доступа к этой переменной. – jkeys

ответ

4

Я не уверен, что пользователь должен ввести тип ISBN.

Чтение из потока в int будет считывать цифры до пробела и преобразовывать результат в int (если все будет хорошо, во всяком случае). Чтение в символ хранит значение char. Поэтому на данный момент вы проверяете, чем ISBN выглядит как три одиночные цифры (0-9), а затем следующий символ. Это не то, что я думаю, похоже на ISBN.

Ваш operator== выглядит нормально, хотя отмечают, что для возвращаемого значения BOOL,

if (X) return true; 
else return false; 

можно заменить

return X; 

потому условными уже типа BOOL.

После настройки значения ISBN (и любые другие поля, которые вы планируете использовать в operator==, если он еще не закончен), способ искать соответствия книги в магазине:

for(int i = 0; i < books.size(); ++i) 
    if(*this == books[i]) cout << "test"; 

В других слова, ищите книгу, равную этой книге. Или вы можете использовать std::find от <algorithms>, хотя в этом случае это не было бы более кратким.

Кстати, необычно использовать один и тот же класс (Книга) для представления как одной книги, так и всего магазина. Тем не менее, разворачивание это довольно сложный набор изменений и решений, поэтому я просто скажу, что класс должен представлять один вид вещи, а объект класса представляет собой пример такого рода. Так что обычно Book and Bookstore - это разные вещи. Вектор в книге - это переменная экземпляра, означающая, что каждая книга имеет свой собственный вектор Книги. Это не имеет смысла.

+0

Ну все данные для каждой книги хранятся для каждого векторного элемента. Я думал, что это будет лучше, чем создание отдельных книг для каждой книги. Но я вижу, как это сбивает с толку человек, который не писал код. – trikker

+0

Подождите, вы пытаетесь сравнить книги или ints? Вы можете сравнить книгу с книгой и int с int или Book-> int с int. – jkeys

+0

Это всего лишь упражнение, а не настоящая программа, поэтому я не собираюсь заниматься реалистичным ISBN, я просто разработал его, поскольку книга попросила меня (3 одиночных цифры, а затем письмо или цифру).Я собираюсь попробовать ваше решение прямо сейчас. – trikker

1

книги относятся к вектору класса книги. Вы сравниваете Book с целым числом, которое является неопределенным поведением. Вам необходимо разыменовать объект книги, прежде чем вы сможете получить доступ к своим членам данных.

Во-первых, не обращайтесь к векторам, используя нижний индекс []. Он неэффективен и затрудняет жизнь. Используйте итератора (что-то вроде, не уверен в том, как вы хотели бы реализовать):

for (std::vector::iterator it = books.begin(); it != books.end(); ++it) 
{ 
} 

это не ваша проблема, однако. Вы используете оператор -> для разыменования объектов для доступа к своим членам. Вы сделали члены вашей частной, однако, так что вам нужно будет либо функцию ПОЛУЧИТЬ как

ISBNf() { return ISBNfirst; } 

Или сделать ваши члены общественности, но это плохая идея (люди могут обмануть с вашими данными). Однако, для простоты предположим, что они являются общедоступными, это то, что вы хотите:

for (std::vector::iterator it = books.begin(); it != books.end(); ++it) 
{ 
    if (*this == *it) cout << "test"; 
} 

Там нет хорошего решения, здесь, потому что я понятия не имею, что вы пытаетесь достичь. Я думаю, вы пытаетесь сравнить количество цифр на целое число, но это не так, как это можно достичь. Если вы просто пытаетесь убедиться, что правильно назначаете ISBNfirst, позвольте мне успокоить ум: вы. . Тем не менее, вы не доступ к ним правильно, что где -> оператор приходит в

Далее, этот код является излишеством:

else if(!isdigit(ISBNlast) && !isalpha(ISBNlast) 

вместо этого, используйте функцию isalphnum():

else if (!isalphnum(ISBNlast)); 

Размещено; Я отредактирую свой пост, чтобы указать на все недостатки вашего кода.

+1

"не имеют доступа к вектору, используя индексный индекс []. Это неэффективно". Миф. Доступ к индексам вряд ли будет значительно медленнее в подобной ситуации и значительно более кратким, чем код итератора. –

+0

Не могли бы вы рассказать мне об этом? Я хотел бы иметь некоторые доказательства, прежде чем перестать использовать итераторы. Кроме того, я считаю, что оператор разыменования намного яснее и чище. – jkeys

+0

Кроме того, вы заметили, что store_ISBN является функцией-членом книги? Таким образом, нет необходимости в аксессуарах или публичных членах, или ->, для доступа к переменным-членам. Не то, чтобы я одобрял дизайн, но я думаю, что вы требуете синтаксических проблем, которых не существует. Обратите внимание, что это '(* it) -> ISBNFirst' не будет работать, потому что это вектор книги, а не' Book * '. Поэтому '(* it)' является Книгой и '(* it) .ISBNFirst - это правильный путь доступа к своим полям. –