Форум программистов, компьютерный форум CyberForum.ru

Работа с сетью, работа с БД и парсинг информации. Разделение потоков - C++

Восстановить пароль Регистрация
 
MDK_17R
Заблокирован
24.04.2014, 20:25     Работа с сетью, работа с БД и парсинг информации. Разделение потоков #1
Возникла проблема разграничения потоков. То есть в конечном файле реализованы алгоритмы: работа с сетью, работа с БД и парсинг информации. Преподаватель сказал, что категорически запрещается, чтобы всё это работало в одном потоке. Необходимо сделать в разных. Помогите, пожалуйста кто чем сможет, очень срочно, до субботы(26.04) нужно сделать.
Это код главного файла MainWindow:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
#include "mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
    QWidget(parent)
{
    search = new QLineEdit;
 
    reload = new QPushButton(this->style()->standardIcon(QStyle::SP_BrowserReload),"");
    reload->setFixedSize(50,50);
 
    results = new QListWidget;
    results->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
    results->verticalScrollBar()->setStyleSheet("QScrollBar:vertical{"
                                                "width: 40px; "
                                                "} "
                                                );
 
    add = new additionaly;
 
    tabs = new QTabWidget;
    QTabBar* tabBar = tabs->findChild<QTabBar*>();
    tabBar->hide();
    tabs->addTab(results,"Main");
    tabs->addTab(add,"Add");
 
    manager = new QNetworkAccessManager;
 
    QHBoxLayout* hlayo = new QHBoxLayout;
    hlayo->setMargin(0);
    hlayo->setSpacing(5);
    hlayo->addWidget(search);
    hlayo->addWidget(reload);
 
    QVBoxLayout* vlayo = new QVBoxLayout;
    vlayo->setMargin(5);
    vlayo->setSpacing(5);
    vlayo->addLayout(hlayo);
    vlayo->addWidget(tabs);
 
    this->setLayout(vlayo);
 
    connect(reload,SIGNAL(clicked()),this,SLOT(updateBase()));
    connect(search,SIGNAL(textChanged(QString)),this,SLOT(parseBase(QString)));
    connect(add,SIGNAL(back()),this,SLOT(toBack()));
 
    createConnection();
    createStationTables();
    parseBase("");
 
    dialog = new QLabel("<h3>Обновление базы!</h3>");
    dialog->setFixedSize(800,480);
}
 
bool MainWindow::createConnection()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); // Используется БД SQLite
    db.setDatabaseName("BusStation");
 
    db.setUserName("Anonymous");
    db.setHostName("localhost");
    db.setPassword("Anonymous");
 
    if(!db.open())
    {
        qDebug() << db.lastError();
        return false;
    }
 
    query = new QSqlQueryModel;
    add->table->setModel(query);
 
    return true;
}
 
bool MainWindow::createStationTables()
{
    query->setQuery("CREATE TABLE IF NOT EXISTS stations (" // Таблица основных данных
                    "id INTEGER PRIMARY KEY ASC, "
                    "number INTEGER UNSIGNED, "
                    "time VARCHAR(80), "
                    "title VARCHAR(45));");
    if(!logError(query)) return false;
    query->setQuery("CREATE TABLE IF NOT EXISTS output (" // Таблица дополнительных данных
                    "id INTEGER PRIMARY KEY ASC, "
                    "context VARCHAR(100), "
                    "title VARCHAR(45), "
                    "time VARCHAR(45), "
                    "id_station INTEGER, "
                    "FOREIGN KEY (id_station) "
                    "REFERENCES stations(id) "
                    "ON DELETE CASCADE "
                    "ON UPDATE CASCADE);");
    logError(query);
    if(!logError(query)) return false;
    return true;
}
 
bool MainWindow::logError(QSqlQueryModel* query)
{
    if(query->lastError().isValid())
    {
        qDebug() << query->lastError(); // Вывод в консоль отладки
        return false;
    }
    return true;
}
 
void MainWindow::updateBase()
{
    dialog->show();
    tabs->setCurrentIndex(0);
    QNetworkReply* reply = manager->get(QNetworkRequest(QUrl("http://avtovokzal.tomsk.ru"))); // получение содержания сайта
    connect(reply,SIGNAL(finished()),this,SLOT(mainReply()));
    connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(error(QNetworkReply::NetworkError)));
}
 
void MainWindow::error(QNetworkReply::NetworkError)
{
    qDebug() << ((QNetworkReply*)sender())->errorString();
    dialog->hide();
}
 
void MainWindow::mainReply()
{
    query->setQuery("DELETE FROM stations;");
    query->setQuery("DELETE FROM output;");
 
    QNetworkReply* reply = (QNetworkReply*)sender(); // результат полученного сайта
    QString str = reply->readAll();
    if(str=="")
    {
        dialog->hide();
        return;
    }
    // Убираем лишнее в в контексте и получаем таблицу
    QString table_f = "<div id=\"main_content\">";
    str = str.mid(str.indexOf(table_f)+table_f.count());
    table_f = "</table>";
    QString table = str.left(str.indexOf(table_f));
    table = table.replace(" class=\'white\'","");
    table = table.replace(" class=\'blue\'","");
    table = table.replace(" class=\'head\'","");
    table = table.replace(" class=\'c1\'","");
    table = table.replace(" class=\'c2\'","");
    table = table.replace(" class=\'c3\'","");
    table = table.replace(" class=\'c4\'","");
    table = table.replace(" class=\'c5\'","");
 
    int n = 0;
    // парсинг кадой строки за исключением заголовка
    while(table.count()>0)
    {
        QString tr_f = "<tr>";
        QString tr = table.mid(table.indexOf(tr_f)+tr_f.count());
        tr_f = "</tr>";
        tr = tr.left(tr.indexOf(tr_f));
 
        table = table.mid(table.indexOf(tr_f)+tr_f.count());
 
        if(n==0)
        {
            ++n;
            continue;
        }
 
        QString number = "";
        QString title = "";
        // парсинг колонок строки
        for(int i=0;i<5;++i)
        {
            QString td_f = "<td>";
            QString td = tr.mid(tr.indexOf(td_f)+td_f.count());
            td_f = "</td>";
            td = td.left(td.indexOf(td_f));
 
            if(i==0)
            {
                number = td;
            }
 
            if(i==1)
            {
                QString h3_f = "</h3>";
                td = td.mid(td.indexOf(h3_f)+h3_f.count());
                title = td;
            }
 
            if(i==2)
            {
                QString div_f = "<div>";
                td = td.left(td.indexOf(div_f));
                QString temp = "";
                while(td.indexOf("\'>")!=-1)
                {
                    temp+=td.mid(td.indexOf("\'>")+2,5);
                    td=td.mid(td.indexOf("a>")+2);
                    if(td!="") temp+=", ";
                }
 
                query->setQuery("INSERT INTO stations (number, time, title) VALUES (\'"+number+"\', \'"+temp+"\', \'"+title+"\');");
 
                //-----------
 
                query->setQuery("SELECT id FROM stations ORDER BY id DESC LIMIT 1;");
 
                QString id_number = query->data(query->index(0,0)).toString();
 
                toDoBase(title,number);
                query->setQuery("UPDATE output SET id_station=\'"+id_number+"\' WHERE id_station=\'-1\';");
            }
 
            tr = tr.mid(tr.indexOf(td_f)+td_f.count());
        }
        QApplication::processEvents();
        ++n;
    }
    dialog->hide();
    parseBase("");
}
 
void MainWindow::otherReply()
{
    QNetworkReply* reply = (QNetworkReply*)sender();
    QString str = reply->readAll();
 
    QString div_f = "<div class=\"Ttrip\">";
    QString div = str.mid(str.indexOf(div_f)+div_f.count()+1);
    div_f = "<table class=\'vtl\'>";
    div = div.left(div.indexOf(div_f));
    div = div.replace("<div >","");
    div = div.replace("</div>","|");
 
    QString table_f = "<table class=\"vtl\">";
    str = str.mid(str.indexOf(table_f)+table_f.count());
    table_f = "</table>";
    QString table = str.left(str.indexOf(table_f));
    table = table.replace(" class=\'white\'","");
    table = table.replace(" class=\'blue\'","");
    table = table.replace(" class=\'head\'","");
    table = table.replace(" class=\'c1\'","");
    table = table.replace(" class=\'c2\'","");
    table = table.replace(" class=\'c3\'","");
    table = table.replace(" class=\'c4\'","");
    table = table.replace(" class=\'c5\'","");
 
    int n = 0;
    while(table.count()>0)
    {
        QString tr_f = "<tr>";
        QString tr = table.mid(table.indexOf(tr_f)+tr_f.count());
        tr_f = "</tr>";
        tr = tr.left(tr.indexOf(tr_f));
 
        table = table.mid(table.indexOf(tr_f)+tr_f.count());
 
        if(n==0)
        {
            ++n;
            continue;
        }
 
        QString time = "";
        QString title = "";
        for(int i=0;i<3;++i)
        {
            QString td_f = "<td>";
            QString td = tr.mid(tr.indexOf(td_f)+td_f.count());
            td_f = "</td>";
            td = td.left(td.indexOf(td_f));
 
            if(i==0)
            {
                title = td;
            }
 
            if(i==1)
            {
                time = td;
                query->setQuery("INSERT INTO output (context, title, time, id_station) VALUES (\'"+div+"\', \'"+title+"\', \'"+time+"\', \'-1\');");
            }
 
            tr = tr.mid(tr.indexOf(td_f)+td_f.count());
        }
 
        ++n;
    }
}
 
void MainWindow::toDoBase(QString title, QString number)
{
    // выполнение php скрипта найденного в исходниках JavaScript сайта
    QNetworkReply* reply = manager->get(QNetworkRequest(QUrl("http://avtovokzal.tomsk.ru/ajax/tripinfo.php?name="+title+"&number="+number)));
 
    connect(reply,SIGNAL(finished()),this,SLOT(otherReply()));
    connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(error(QNetworkReply::NetworkError)));
 
    while(!reply->isFinished())
    {
        QApplication::processEvents();
    }
}
 
void MainWindow::parseBase(QString str)
{
    tabs->setCurrentIndex(0);
    // отображение маршрутов по названию или номеру маршрута
    query->setQuery("SELECT * FROM stations WHERE (UPPER(number) LIKE \'%"+str.toUpper()+"%\') OR (UPPER(title) LIKE \'%"+str.toUpper()+"%\');");
 
    results->clear();
 
    // генерирование результата
    for(int i=0;i<query->rowCount();++i)
    {
        QListWidgetItem* item = new QListWidgetItem;
        item->setSizeHint(QSize(0,80));
        header* widget = new header;
        connect(widget,SIGNAL(showAdd(QString,QString,QString)),this,SLOT(toAdd(QString,QString,QString)));
        connect(results,SIGNAL(clicked(QModelIndex)),this,SLOT(clickWidget(QModelIndex)));
        widget->number->setText(query->data(query->index(i,1)).toString());
        widget->time->setText(query->data(query->index(i,2)).toString());
        widget->title->setText(query->data(query->index(i,3)).toString());
        widget->id = query->data(query->index(i,0)).toString();
        results->addItem(item);
        results->setItemWidget(item,widget);
    }
}
 
void MainWindow::toAdd(QString id, QString title, QString number)
{
    add->head->setText("<h3>Маршрут №"+number+"\nТомск - "+title+"</h3>");
    query->setQuery("SELECT context FROM output WHERE id_station=\'"+id+"\' LIMIT 1;");
    for(int i=0;i<query->rowCount();++i)
    {
        QString str = query->data(query->index(0,0)).toString().replace("|","\n");
        add->title->setText(str);
    }
    query->setQuery("SELECT id as `№`, title AS `Маршрут`, time AS `Время в пути` FROM output WHERE id_station=\'"+id+"\';");
    add->table->resizeColumnsToContents();
    add->table->hideColumn(0);
    tabs->setCurrentIndex(1);
}
 
void MainWindow::toBack()
{
    tabs->setCurrentIndex(0);
    search->setVisible(true);
    reload->setVisible(true);
}
 
void MainWindow::clickWidget(QModelIndex index)
{
    header* hed = (header*)results->itemWidget(results->item(index.row()));
    hed->onClick();
    search->setVisible(false);
    reload->setVisible(false);
}
заголовочный файл mainwindow.h:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include "header.h"
#include <QtNetwork>
#include <QtSql>
 
class MainWindow : public QWidget // виджет главного окна
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
 
    QLineEdit* search; // строка отображения
 
    QPushButton* reload; // кнопка обновления базы
 
    QListWidget* results; // виджет отображения результатов
 
    QTabWidget* tabs; // виджет управления окнами
 
    additionaly* add; // виджет дополнительного содержания
 
    QLabel* dialog; // информация об обновлении
 
    //---------------------------
 
    QNetworkAccessManager* manager; // сетевой менеджер для парсинга сайта
 
    QSqlQueryModel* query; // модель доступа к БД
 
    bool createConnection(); // функция подключения к БД
    bool createStationTables(); // функция создания таблиц БД
    bool logError(QSqlQueryModel* query); // функция логирования ошибок
signals:
 
public slots:
    void updateBase(); // метод обновления базы данных
    void toDoBase(QString title, QString number); // метод парсинга дополнительных ссылок
    void mainReply(); // парсинг основной ссылки
    void otherReply(); // парсинг дополнительный ссылок
    void error(QNetworkReply::NetworkError); // обработка ошибок
    void parseBase(QString str); // метод отображения элементов списка БД
    void toAdd(QString id, QString title, QString number); // метод отображения дополнительной информации
    void toBack(); // метод отображения главного окна
    void clickWidget(QModelIndex index); // метод обработки выбора элемента списка для отобрадения дополнительной информации
 
};
 
#endif // MAINWINDOW_H
Если потребуется код из остальных файлов или полная реализация, сообщите, залью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.04.2014, 20:25     Работа с сетью, работа с БД и парсинг информации. Разделение потоков
Посмотрите здесь:

C++ Реализация 2х потоков, работа с буфером, механизм семафоров
Разделение потоков C++
Работа с файлами. Считывание информации из файла в массив C++
C++ Создание и завершение процессов и потоков. Приоритеты выполнения потоков
C++ Работа с двоичными файлами, организация ввода-вывода структурированной информации/
C++ Нужны материалы на тему "С++ и работа с сетью"
C++ Зависание потоков. Работа с файлами
C++ C++ - Ввод информации в структуру и поиск элемента по информации, находящейся в этом же элементе

Искать еще темы с ответами

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

Текущее время: 06:49. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru