Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.09.2013, 23:30   #11
mixon-21
Я только Учусь
Форумчанин
 
Аватар для mixon-21
 
Регистрация: 06.03.2013
Сообщений: 193
По умолчанию

:conf used:
mixon-21 вне форума Ответить с цитированием
Старый 07.09.2013, 00:11   #12
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

Цитата:
тут посмотри.
http://www.doc.crossplatform.ru/qt/4...dressbook.html
правда там адресная книга, но под справочник переделать не сложно
Сложно, ТС не дружит с С++, вы ему Qt толкаете.
Кроме того, там используется QMap для хранения абонентов, но ТС надо выбирать их как по номеру, так и по имени - QMap для этого не подходит.

Цитата:
Гради Буч не предупреждал, что б не увлекались? Про ООП головного мозго ничего не писал?

Справочник - единственная сущность, необходимая для решения задачи.
угловые скобки в pair ставить не надоедает? - читабельности это тоже не добваляет. Про гибкоту говорить? - про то, что работа с абонентом размажется по всему справочнику тоже не стоит? - если не размажется - ты таки опишешь функции для сравнения (и не только) абонентов и т.п. (т.е. ты будешь думать об абоненте, а значит, это сущность)
rrrFer вне форума Ответить с цитированием
Старый 07.09.2013, 00:48   #13
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от rrrFer Посмотреть сообщение
угловые скобки в pair ставить не надоедает?
Нет. Хотя здесь они так же не нужны.

Цитата:
Сообщение от rrrFer Посмотреть сообщение
Про гибкоту говорить?
Нет. Гибкость здесь не нужна. Есть конкретная задача, которую нужно решить.

Если когда нибудь понадобится модифицировать код: простой код проще модифицировать. Код переусложненный проще переписать заново.

Цитата:
Сообщение от rrrFer Посмотреть сообщение
- про то, что работа с абонентом размажется по всему справочнику тоже не стоит?
Она в любом случае размажется по справочнику. Поскольку сущность "абонент" - есть внутренние данные, которые он обрабатывает.

PhoneBook book;
book.Add("Vasya Pupkin 1111 - 1111");

или:

PhoneBook book;
book<< "Vasya Pupkin"<< 1111 << 1111;

или

PhoneBook book;
book[name] = "Vasya Pupkin";
book[phone]= "1111 - 1111";

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

А в самом справочнике данные лучше хранить в том виде, в каком по нему проще делать выборку/добавление/удаление новых записей в базу.

С точки зрения разработчика справочника - это банальная база данных.
И ему без разницы: Вася Пупкин - это абонент, или марка автомобиля.

Ему просто нужно хранить и делать выборку.
_Bers вне форума Ответить с цитированием
Старый 07.09.2013, 11:50   #14
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Я тоже считаю, что не нужно усложнять простую задачу и делать решение "гибким" для неё.

Вижу две проблемы:

1) Как заставить пользователей вводить "нормальный" номер телефона. К примеру, "+7-917-349-99-57" или "8-917-34-99-957"

2) Хранение, выборка, сортировка данных и т.д.

Сложность первой проблемы нужно возложить на библиотеку (к примеру Qt). Нужно запретить пользователю вводить неправильный номер (только цифры и чёткий формат). Можно будет показать пример ввода пользователю:



Этот пример взят из книги "Foundation of Qt development". Просто нужно создать пустой проект, создать файл main.cpp и добавить в main.cpp следующий код:

main.cpp
Код:
#include <QApplication>

#include <QDialog>

#include <QGridLayout>

#include <QLabel>
#include <QLineEdit>
#include <QPushButton>

#include <QRegExpValidator>

class ValidationDialog : public QDialog
{
public:
    ValidationDialog()
    {
        QGridLayout *layout = new QGridLayout( this );

        QLineEdit *reEdit = new QLineEdit( "+46(0)31-445566" );
        QLabel *lblExample = new QLabel( "Example: +98(0)31-775565" );
        QPushButton *button = new QPushButton( "Close" );

        layout->addWidget( new QLabel("Phone:"), 0, 0 );
        layout->addWidget( reEdit, 0, 1 );
        layout->addWidget( lblExample, 1, 0, 1, 2 );
        layout->addWidget( button, 2, 0, 1, 2 );

        QRegExpValidator *reVal = new QRegExpValidator(
                    QRegExp("\\+\\d{1,2}\\([089]\\)\\d{2,5}\\-\\d+"),
                    this );
        reEdit->setValidator( reVal );

        connect( button, SIGNAL(clicked()), this, SLOT(accept()) );
    }
};

int main( int argc, char** argv )
{
    QApplication app( argc, argv );

    ValidationDialog w;
    w.show();

    return app.exec();
}
Советую автору темы выполнить следующие инструкции (последовательно):

- http://programmersforum.ru/showpost....33&postcount=2
- http://programmersforum.ru/showpost....35&postcount=3
- http://programmersforum.ru/showpost....36&postcount=4
- http://programmersforum.ru/showpost....37&postcount=5

Здесь уже приводился пример адресной книги на Qt. В книге "Foundation of Qt development" есть более подходящий пример:



Прикрепил файлы проекта. Их просто нужно добавить в пустой проект в Qt Creator.

Сложность второй проблемы "2) Хранение, выборка, сортировка данных и т.д." решается с помощью базы данных. К примеру, SQLitе. Для Qt есть полноценный пример для начала работы с SQLite: http://www.youtube.com/watch?v=cc06D3wuTn4
Вложения
Тип файла: zip addressbook.zip (13.7 Кб, 1 просмотров)
8Observer8 вне форума Ответить с цитированием
Старый 07.09.2013, 12:21   #15
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от 8Observer8 Посмотреть сообщение
Я тоже считаю, что не нужно усложнять
Поэтому решил припахать кутю для решения задачи человеком, который не знает даже основ с++? Всерьёз думаешь, что кутю осилит человек, который не в состоянии осилить даже каркас класса phonebook?

По-моему, ты сверх переусложнил решение.

IMHO:
Когда нибудь, кто то будет изучать кутю, загуглит твоё решение и скажет тебе спасибо.

Но автору этой темы такое решение бесполезно.
_Bers вне форума Ответить с цитированием
Старый 07.09.2013, 12:32   #16
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Я надеюсь, что автор установит Qt. Если он будет выполнять инструкции, на которые я дал ссылки и будет описывать конкретные тупики здесь... в общем, я надеюсь...

Если речь идёт о "показать что-то преподавателю, ну хотя бы и не своё, а просто объяснить, чтобы получить зачёт, пусть и не доделанное до конца, но видно, что человек искал, старался, поэтому ему можно поставить зачёт".

Я тут поупражнялся немного. Только не учёл, что искать придётся не только по имени, но и по номеру телефона. Я использовал map. В map поиск по ключу. В нашем случае, ключ - имя абонента.

main.cpp
Код:
#include <iostream>
#include "PhoneBook.h"
#include "Abonent.h"
using namespace std;

int main(int argc, char** argv) {
    PhoneBook phoneBook;
    Abonent ivanov;
    Abonent petrov;
    Abonent sidorov;
    
    ivanov.setName("Ivanov Ivan");
    ivanov.setNumber("333-333");

    petrov.setName("Petrov Petr");
    petrov.setNumber("999-333");

    sidorov.setName("Sidorov Sird");
    sidorov.setNumber("111-123");
    
    phoneBook.addAbonent(ivanov);
    phoneBook.addAbonent(petrov);
    phoneBook.addAbonent(sidorov);

    cout << phoneBook << endl;
    
    phoneBook.delAbonent(petrov);

    cout << phoneBook << endl;

    return 0;
}
Output:
Цитата:
Ivanov Ivan: 333-333
Petrov Petr: 999-333
Sidorov Sird: 111-123

Ivanov Ivan: 333-333
Sidorov Sird: 111-123
PhoneBook.h
Код:
#ifndef PHONEBOOK_H
#define	PHONEBOOK_H

#include <map>
#include <string>
#include <utility>
#include <ostream>
#include "Abonent.h"

class PhoneBook {
public:
    void addAbonent(const Abonent& abonent);
    void delAbonent(const Abonent& abonent);
    friend std::ostream& operator<<(std::ostream& stream, PhoneBook a);
private:
    std::map<std::string, std::string> base;
};

inline std::ostream& operator<<(std::ostream& stream, PhoneBook pb) {
    for (std::map<std::string, std::string>::const_iterator iter = (pb.base.begin()); 
            iter != (pb.base.end()); ++iter) {
        stream << iter->first << ": " << iter->second << std::endl;
    }
    return stream;
}

#endif	/* PHONEBOOK_H */
PhoneBook.cpp
Код:
#include "PhoneBook.h"

void PhoneBook::addAbonent(const Abonent& abonent) {
    this->base[abonent.getName()] = abonent.getNumber();
}

void PhoneBook::delAbonent(const Abonent& abonent) {
    std::map<std::string, std::string>::iterator it;
    it = base.begin();
    it = this->base.find(abonent.getName());
    base.erase(it);
}
Abonent.h
Код:
#ifndef ABONENT_H
#define	ABONENT_H

#include <string>

class Abonent {
public:
    std::string getName() const;
    std::string getNumber() const;
    void setName(std::string name);
    void setNumber(std::string number);
private:
    std::string name;
    std::string number;
};

#endif	/* ABONENT_H */
Abonent.cpp
Код:
#include "Abonent.h"

std::string Abonent::getName() const {
    return this->name;
}

std::string Abonent::getNumber() const {
    return this->number;
}

void Abonent::setName(std::string name) {
    this->name = name;
}

void Abonent::setNumber(std::string number) {
    this->number = number;
}
P.S. Дальше тупик. Это сложный для меня путь. Я не знаю, как искать по номеру телефона. Мне на Qt (с использованием SQLite) намного проще решить задачу (до достойного этапа), чем на чистом С++.

Последний раз редактировалось 8Observer8; 07.09.2013 в 12:35.
8Observer8 вне форума Ответить с цитированием
Старый 07.09.2013, 18:11   #17
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

Цитата:
Она в любом случае размажется по справочнику. Поскольку сущность "абонент" - есть внутренние данные, которые он обрабатывает.

PhoneBook book;
book.Add("Vasya Pupkin 1111 - 1111");

или:

PhoneBook book;
book<< "Vasya Pupkin"<< 1111 << 1111;

или

PhoneBook book;
book[name] = "Vasya Pupkin";
book[phone]= "1111 - 1111";

Каким бы ни был возможный дизайн, пользователя справочника не интересуют его внутренние данные.
Если пользователь вызывает book.add() - то, наверное хочет добавить абонента, а значит, абонент его интересует.

Код:
Abonent ab(...);
// может быть stream >> ab или еще что-то такое.
book.add(&ab);
ну как-то так . Это красиво, гибко, просто и ниче по справочнику не размазывается.

Цитата:
std::map<std::string, std::string> base;
почитай выше, я уже писал, что map в этой задаче не сканает
Либо ты будешь использовать структуру/класс абонента, либо хранить
list<pair<string,string> >.
Второй случай неудобный, негибкий, трудно поддерживаемый, несамодокументирующийся и все такое. Я жду от Берса другого решения (чтобы угловые скобки ставить не приходилось - он грил что знает как это сделать xD)
rrrFer вне форума Ответить с цитированием
Старый 07.09.2013, 21:01   #18
mixon-21
Я только Учусь
Форумчанин
 
Аватар для mixon-21
 
Регистрация: 06.03.2013
Сообщений: 193
По умолчанию

Спасибо задача должна решатся с помощю бинарного дерева.
mixon-21 вне форума Ответить с цитированием
Старый 08.09.2013, 02:39   #19
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от rrrFer Посмотреть сообщение
Если пользователь вызывает book.add() - то, наверное хочет добавить абонента, а значит, абонент его интересует.
Его интересует справочник, который будет уметь добавлять/удалять/делать выборку абонентов.

Phonebook book;
book.Add("Vasya Pupkin, 1111-1111");

Для пользователя строка "Vasya Pupkin, 1111-1111" - это и есть абонент, который его интересует.
Класс Абонентов пользователю не нужен.

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

И как ты это сделаешь без использования структур наподобие map?
Ты конечно можешь завелосипедить код поиска. Но вот только по итогу это и получится грубым и тормозным аналогом поиска, как в специально оптимизированных для этого деревьях.

Мне лениво решать эту задачку.

Я лишь показываю принцип, как можно быстро выполнять выборку записей по ключу:

http://codepad.org/a8lcQ1Od

Понятно, что в реальной задаче придется использовать mutlimap, либо если не устраивает скорость поиска по ключу map, можно использовать любые другие деревья ещё лучше оптимизированные для поиска.

Понятно, что в реальной задаче придется использовать несколько связанных multimap по принципу: ключ - имя столбца, значение - запись
И так со всеми столбцами:

имя - запись
фамилия - запись
номер - запись

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

А Затем отсеиваются все записи, которые не были обнаружены во всех участвовавших в поиске столбцах.

Для этого сравниваются найденные диапазоны участвовавших в поиске столбцов. И формируется самый узкий диапазон по какому либо столбцу.

Таким образом на осадке останутся только те записи, которые удовлетворяют критериям по всем столбцам.

Но ты попробуй ради эксперимента сделать выборку хотя бы по одному столбцу имени, как в ссылке выше, не используя деревья.

И сравни по скорости.

Я погляжу, как struct { string name, size_t number }; тебе поможет.

Последний раз редактировалось _Bers; 08.09.2013 в 02:41.
_Bers вне форума Ответить с цитированием
Старый 08.09.2013, 03:12   #20
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

Цитата:
нужно делать выборку записей по критериям: искать однофомильцев, чьи номера укладываются в заданный диапазон.
несколько раз прочитал первый пост, не нашел там ничего про однофамильцев. Сам придумал?

Зато нашел это:
Цитата:
Распечатка в алфавитном порядке абонентов из заданного диапазона номеров или фамилий; например, для номеров диапазон может быть: 222222 - 333333, а для фамилий: Иванаускас - Иванов (то есть Иванова в диапазон не входит).
т.е. ты видишь, что то ключем должна быть фамилия, то номер. По этому ключу должна быть произведена и упорядочена выборка. словарь нужен - но то
map<string, int>, то map<int, string>
соответственно либо при выборке все данные впихиваются в словарь, либо хранится сразу 2 словаря (с разными ключами)

Цитата:
Я погляжу, как struct { string name, size_t number }; тебе поможет.
в структуре можно перегрузить операторы сравнения типа lessByName и lessByNumber, например.

ну и я бы multiset тут использовал (там есть параметр шаблона, в который я передал бы этот lessByName).
rrrFer вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Телефонный справочник Денис999 Помощь студентам 2 26.02.2011 18:41
Телефонный справочник vladxxl Общие вопросы C/C++ 1 15.12.2010 20:28
Телефонный справочник schtefan Фриланс 8 16.11.2010 21:53
Телефонный справочник Krechet Софт 5 10.08.2009 15:51
Телефонный справочник на TC Qai Фриланс 5 25.05.2008 01:02