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

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

Вернуться   Форум программистов > C/C++ программирование > Qt и кроссплатформенное программирование С/С++
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 17.10.2016, 10:55   #1
stasJun
Пользователь
 
Регистрация: 17.10.2016
Сообщений: 95
По умолчанию Поиск слов в файле в Qt

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

Я сделал в виде виджета, додал прогрес бар и т.д. Но наткнулся на проблему:
1) Выдает ошибку, но делал как в книжке: Професиональное програмирование Макс Шлее(стр 551) но в моему случаи не пашет. Тема:Обмен сообщениями, потоки и слоты, сигналы.
Какую мне выдает ошибку:
FindWordInFileThread.obj:-1: error: LNK2019: unresolved external symbol "public: void __cdecl FindWordInFileThread::complited(int )" (?complited@FindWordInFileThread@@Q EAAXH@Z) referenced in function "public: virtual void __cdecl FindWordInFileThread::run(void)" (?run@FindWordInFileThread@@UEAAXXZ )
та
debug\FindFilesWidget.exe:-1: error: LNK1120: 1 unresolved externals
я думаю оно кричит через этот код(но в книге работает), подскажите как решить проблему:
Код:
for (size_t index = 0; index < mThreads.size(); ++index)
            connect(mThreads[index], SIGNAL(complited(int)), mProgressBar, SLOT(progressChanged(int)));
_________________________________________________
emit complited(QFileInfo(mFilePath[index]).size());
код где это используется:
Код:
void FindFilesWidget::startClicked()
{
    if(mActionState == ActionState::STOPPED)
    {
        mActionState == ActionState::RUNNING;
        mStartButton->setText("&Cancel");
        const int idealThreadCount = QThread::idealThreadCount();
        mThreads.reserve(idealThreadCount);
 
        QDirIterator dirIt(mSearchDirectoryLine->text(), QDirIterator::Subdirectories);
        std::vector<QString> paths;
        while (dirIt.hasNext())
        {
            dirIt.next();
            if (QFileInfo(dirIt.filePath()).isFile())
            {
                if (QFileInfo(dirIt.filePath()).suffix() == "txt")
                    paths.push_back(dirIt.filePath());
            }
        }
        for (int  index = 0; index < paths.size(); ++index)
        {
            QFileInfo fileInfo(paths[index]);
            mFileSize += fileInfo.size();
        }
        const std::vector<Range> ranges = GenerateRanges(idealThreadCount, paths.size());
        std::vector<QString> foundFiles;
 
        for (size_t index = 0; index < idealThreadCount; ++index)
            mThreads.push_back(new FindWordInFileThread(paths, mSearchWordLine->text(), ranges[index].mStart, ranges[index].mLength, foundFiles));
 
        for (size_t index = 0; index < mThreads.size(); ++index)
            connect(mThreads[index], SIGNAL(complited(int)), mProgressBar, SLOT(progressChanged(int)));
 
        for (size_t index = 0; index < idealThreadCount; ++index)
            mThreads[index]->start();
        for (size_t index = 0; index < idealThreadCount; ++index)
            mThreads[index]->wait();
 
        std::sort(foundFiles.begin(), foundFiles.end());
 
        for (size_t index = 0; index < idealThreadCount; ++index)
            delete mThreads[index];
 
        mFoundFilesList->clear();
        for (size_t index = 0; index < foundFiles.size(); ++index)
            mFoundFilesList->addItem(foundFiles[index]);
    }
    else
    {
        mActionState = ActionState::STOPPED;
        mStartButton->setText("&Start");
        for (size_t index = 0; index < mThreads.size(); ++index)
            mThreads[index]->exit();
    }
 
}
Код:
void FindWordInFileThread::run()
{
    for (size_t index = mStartIndex; index < mStartIndex + mNumElements; ++index)
    {
        QFile file(mFilePath[index]);
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
            return;
 
        QTextStream textStream(&file);
        while (!textStream.atEnd())
        {
            QString line = textStream.readLine();
            if (line.contains(mWord, Qt::CaseInsensitive))
            {
                mFoundFiles.push_back(QFileInfo(mFilePath[index]).filePath());
                break;
            }
        }
        emit complited(QFileInfo(mFilePath[index]).size());
        file.close();
    }
}

Последний раз редактировалось stasJun; 17.10.2016 в 10:59.
stasJun вне форума Ответить с цитированием
Старый 17.10.2016, 10:55   #2
stasJun
Пользователь
 
Регистрация: 17.10.2016
Сообщений: 95
По умолчанию

CPP файли:
Код:
#include "FindWordInFileThread.h"
 
#include <QFile>
#include <QTextStream>
#include <QFileInfo>
 
FindWordInFileThread::FindWordInFileThread(const std::vector<QString>& filePath, const QString& word, size_t startIndex, size_t numElements, std::vector<QString>& foundFiles)
    : mFilePath(filePath)
    , mWord(word)
    , mStartIndex(startIndex)
    , mNumElements(numElements)
    , mFoundFiles(foundFiles)
{}
 
void FindWordInFileThread::run()
{
    for (size_t index = mStartIndex; index < mStartIndex + mNumElements; ++index)
    {
        QFile file(mFilePath[index]);
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
            return;
 
        QTextStream textStream(&file);
        while (!textStream.atEnd())
        {
            QString line = textStream.readLine();
            if (line.contains(mWord, Qt::CaseInsensitive))
            {
                mFoundFiles.push_back(QFileInfo(mFilePath[index]).filePath());
                break;
            }
        }
        emit complited(QFileInfo(mFilePath[index]).size());
        file.close();
    }
}
Код:
#include "FindFilesWidget.h"
#include "FindWordInFileThread.h"
#include <QDebug>
 
struct Range
{
    Range(size_t start, size_t length);
 
    size_t mStart;
    size_t mLength;
};
 
Range::Range(size_t start, size_t length)
    : mStart(start)
    , mLength(length)
{}
 
std::vector<Range> GenerateRanges(size_t numRanges, size_t numFiles)
{
    std::vector<Range> ranges;
    ranges.reserve(numRanges);
 
    const size_t minLength = numFiles / numRanges;
    const size_t modulo = numFiles % numRanges;
 
    for (size_t index = 0; index < modulo; ++index)
        ranges.push_back(Range(0, minLength + 1));
 
    for (size_t index = modulo; index < numRanges; ++index)
        ranges.push_back(Range(0, minLength));
 
    for (size_t index = 1; index < numRanges; ++index)
        ranges[index].mStart = ranges[index - 1].mStart + ranges[index - 1].mLength;
 
    return ranges;
}
 
FindFilesWidget::FindFilesWidget(QWidget *parent)
    : QWidget(parent)
    , mActionState(ActionState::STOPPED)
    , mFileSize(0)
{
    setWindowTitle("Search Files");
 
    QVBoxLayout* vLayout = new QVBoxLayout(this);
    vLayout->setSpacing(6);
    vLayout->setContentsMargins(11, 11, 11, 11);
    vLayout->addWidget(createSelectDirectoryGroup());
    vLayout->addWidget(createSearchWordGroup());
    vLayout->addWidget(createProgressBarGroup());
    vLayout->addWidget(createFoundFilesGroup());
    setLayout(vLayout);
 
    resize(600, 600);
}
 
void FindFilesWidget::startClicked()
{
    if(mActionState == ActionState::STOPPED)
    {
        mActionState == ActionState::RUNNING;
        mStartButton->setText("&Cancel");
        const int idealThreadCount = QThread::idealThreadCount();
        mThreads.reserve(idealThreadCount);
 
        QDirIterator dirIt(mSearchDirectoryLine->text(), QDirIterator::Subdirectories);
        std::vector<QString> paths;
        while (dirIt.hasNext())
        {
            dirIt.next();
            if (QFileInfo(dirIt.filePath()).isFile())
            {
                if (QFileInfo(dirIt.filePath()).suffix() == "txt")
                    paths.push_back(dirIt.filePath());
            }
        }
        for (int  index = 0; index < paths.size(); ++index)
        {
            QFileInfo fileInfo(paths[index]);
            mFileSize += fileInfo.size();
        }
        const std::vector<Range> ranges = GenerateRanges(idealThreadCount, paths.size());
        std::vector<QString> foundFiles;
 
        for (size_t index = 0; index < idealThreadCount; ++index)
            mThreads.push_back(new FindWordInFileThread(paths, mSearchWordLine->text(), ranges[index].mStart, ranges[index].mLength, foundFiles));
 
        for (size_t index = 0; index < mThreads.size(); ++index)
            connect(mThreads[index], SIGNAL(complited(int)), mProgressBar, SLOT(progressChanged(int)));
 
        for (size_t index = 0; index < idealThreadCount; ++index)
            mThreads[index]->start();
        for (size_t index = 0; index < idealThreadCount; ++index)
            mThreads[index]->wait();
 
        std::sort(foundFiles.begin(), foundFiles.end());
 
        for (size_t index = 0; index < idealThreadCount; ++index)
            delete mThreads[index];
 
        mFoundFilesList->clear();
        for (size_t index = 0; index < foundFiles.size(); ++index)
            mFoundFilesList->addItem(foundFiles[index]);
    }
    else
    {
        mActionState = ActionState::STOPPED;
        mStartButton->setText("&Start");
        for (size_t index = 0; index < mThreads.size(); ++index)
            mThreads[index]->exit();
    }
 
}
 
void FindFilesWidget::progressChanged(int number)
{
    mProgressBar->setValue(mProgressBar->value() + ((number / mFileSize)* 100));
}
 
void FindFilesWidget::selectDirectoryClicked()
{
    QString selectedDirectory = QFileDialog::getExistingDirectory(this, tr("Open Directory"), mSearchDirectoryLine->text(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    mSearchDirectoryLine->setText(selectedDirectory);
}
 
QGroupBox* FindFilesWidget::createSelectDirectoryGroup()
{
    QGroupBox* selectDirectoryGroup = new QGroupBox("&Select directory:");
    QPushButton* selectDirectoryButton = new QPushButton("Select", selectDirectoryGroup);
    mSearchDirectoryLine = new QLineEdit(tr("D:/"), selectDirectoryGroup);
 
    QHBoxLayout* hLayout = new QHBoxLayout();
    hLayout->setSpacing(6);
    hLayout->addWidget(mSearchDirectoryLine);
    hLayout->addWidget(selectDirectoryButton);
 
    connect(selectDirectoryButton, SIGNAL(clicked()), SLOT(selectDirectoryClicked()));
 
    selectDirectoryGroup->setLayout(hLayout);
    return selectDirectoryGroup;
}
 
QGroupBox* FindFilesWidget::createSearchWordGroup()
{
    QGroupBox* searchWordGroup = new QGroupBox("&Search word:");
    mSearchWordLine = new QLineEdit(searchWordGroup);
    mStartButton = new QPushButton("&Start");
 
    QHBoxLayout* hLayout = new QHBoxLayout();
    hLayout->setSpacing(6);
    hLayout->setContentsMargins(11, 11, 11, 11);
    hLayout->addWidget(mSearchWordLine);
    hLayout->addWidget(mStartButton);
 
    connect(mStartButton, SIGNAL(clicked()), SLOT(startClicked()));
 
    searchWordGroup->setLayout(hLayout);
    return searchWordGroup;
}
 
QGroupBox* FindFilesWidget::createProgressBarGroup()
{
    QGroupBox* progressBarGroup = new QGroupBox("&Progress Bar:");
    mProgressBar = new QProgressBar(progressBarGroup);
 
    QHBoxLayout* hLayout = new QHBoxLayout();
    hLayout->setSpacing(6);
    hLayout->setContentsMargins(11, 11, 11, 11);
    hLayout->addWidget(mProgressBar);
    mProgressBar->setMaximum(100);
    mProgressBar->setMinimumWidth(500);
    mProgressBar->setAlignment(Qt::AlignCenter);
 
    progressBarGroup->setLayout(hLayout);
    return progressBarGroup;
}
 
QGroupBox* FindFilesWidget::createFoundFilesGroup()
{
    QGroupBox* foundFilesGroup = new QGroupBox("&Found files:");
    mFoundFilesList = new QListWidget(foundFilesGroup);
 
    QHBoxLayout* hLayout = new QHBoxLayout();
    hLayout->setSpacing(6);
    hLayout->setContentsMargins(11, 11, 11, 11);
    hLayout->addWidget(mFoundFilesList);
 
    foundFilesGroup->setLayout(hLayout);
    return foundFilesGroup;
}
stasJun вне форума Ответить с цитированием
Старый 17.10.2016, 10:56   #3
stasJun
Пользователь
 
Регистрация: 17.10.2016
Сообщений: 95
По умолчанию

Скрин програмы
Изображения
Тип файла: png вывывывы.png (5.0 Кб, 132 просмотров)
stasJun вне форума Ответить с цитированием
Старый 17.10.2016, 11:09   #4
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Что в FindWordInFileThread.h?
Может быть вы сигнал complited объявили не в секции signals.

Кстати, правильно это слово пишется как completed.

И в Qt5 есть более удобный и безопасный (выдаст ошибку компиляции если указано неправильное имя и т.п.) способ подписки на сигналы.
https://wiki.qt.io/New_Signal_Slot_Syntax
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 17.10.2016, 15:02   #5
stasJun
Пользователь
 
Регистрация: 17.10.2016
Сообщений: 95
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Что в FindWordInFileThread.h?
Может быть вы сигнал complited объявили не в секции signals.

Кстати, правильно это слово пишется как completed.

И в Qt5 есть более удобный и безопасный (выдаст ошибку компиляции если указано неправильное имя и т.п.) способ подписки на сигналы.
https://wiki.qt.io/New_Signal_Slot_Syntax
Нет , обявил там где нужно
Код:
#ifndef FINDFILESWIDGET_H
#define FINDFILESWIDGET_H

#include <QtWidgets>

class FindFilesWidget : public QWidget
{
    Q_OBJECT

public:
    enum ActionState
    {
        RUNNING,
        STOPPED,
    };
    FindFilesWidget(QWidget* parent = 0);

public slots:
    void startClicked();
    void selectDirectoryClicked();
    void progressChanged(int);

private:
    QGroupBox* createSelectDirectoryGroup();
    QGroupBox* createSearchWordGroup();
    QGroupBox* createProgressBarGroup();
    QGroupBox* createFoundFilesGroup();

    QLineEdit* mSearchDirectoryLine;
    QListWidget* mFoundFilesList;
    QLineEdit* mSearchWordLine;
    QPushButton* mStartButton;
    QProgressBar* mProgressBar;
    ActionState mActionState;
    std::vector<QThread*> mThreads;
    size_t mFileSize;
};

#endif // FINDFILESWIDGET_H
Код:
#ifndef FIND_WORD_IN_FILE_THREAD_H
#define FIND_WORD_IN_FILE_THREAD_H

#include <QThread>
#include <QString>
#include <QtDebug>

class FindWordInFileThread : public QThread
{
public:
    FindWordInFileThread(const std::vector<QString>& filePath, const QString& word, size_t startIndex, size_t numElements, std::vector<QString>& foundFiles);
    virtual void run();
signals:
    void complited(int);
private:
    const std::vector<QString>& mFilePath;
    const QString mWord;
    size_t mStartIndex;
    size_t mNumElements;
    std::vector<QString>& mFoundFiles;
};

#endif // FIND_WORD_IN_FILE_THREAD_H
stasJun вне форума Ответить с цитированием
Старый 17.10.2016, 15:05   #6
stasJun
Пользователь
 
Регистрация: 17.10.2016
Сообщений: 95
По умолчанию

Архив проекта
Вложения
Тип файла: zip FindFilesWidget.zip (6.5 Кб, 13 просмотров)
stasJun вне форума Ответить с цитированием
Старый 17.10.2016, 15:41   #7
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Q_OBJECT надо добавить.

Еще QFileInfo size возвращает int64 (qint64), а не int.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 17.10.2016, 15:46   #8
stasJun
Пользователь
 
Регистрация: 17.10.2016
Сообщений: 95
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Q_OBJECT надо добавить.

Еще QFileInfo size возвращает int64 (qint64), а не int.
int64 (qint64) и как это исправить?

Последний раз редактировалось stasJun; 17.10.2016 в 15:53.
stasJun вне форума Ответить с цитированием
Старый 17.10.2016, 15:52   #9
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от stasJun Посмотреть сообщение
куда именно добавить?
куда и всегда, в начало класса.


Цитата:
Сообщение от stasJun Посмотреть сообщение
int64 (qint64) и как это исправить?
в completed заменить тип данных на qint64
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 17.10.2016, 15:54   #10
stasJun
Пользователь
 
Регистрация: 17.10.2016
Сообщений: 95
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
куда и всегда, в начало класса.



в completed заменить тип данных на qint64
уже програма работает, но прогрем бар не работает((
и этот код походу тоже не работает(который названия кнопки изменяет (отмета и старт)):
Кричит: QObject::connect: No such slot QProgressBar:rogressChanged(int) in
Код:
void FindFilesWidget::startClicked()
{
    if(mActionState == ActionState::STOPPED)
    {
        mActionState == ActionState::RUNNING;
        mStartButton->setText("&Cancel");
        const int idealThreadCount = QThread::idealThreadCount();
        mThreads.reserve(idealThreadCount);

        QDirIterator dirIt(mSearchDirectoryLine->text(), QDirIterator::Subdirectories);
        std::vector<QString> paths;
        while (dirIt.hasNext())
        {
            dirIt.next();
            if (QFileInfo(dirIt.filePath()).isFile())
            {
                if (QFileInfo(dirIt.filePath()).suffix() == "txt")
                    paths.push_back(dirIt.filePath());
            }
        }
        for (int  index = 0; index < paths.size(); ++index)
        {
            QFileInfo fileInfo(paths[index]);
            mFileSize += fileInfo.size();
        }
        const std::vector<Range> ranges = GenerateRanges(idealThreadCount, paths.size());
        std::vector<QString> foundFiles;

        for (size_t index = 0; index < idealThreadCount; ++index)
            mThreads.push_back(new FindWordInFileThread(paths, mSearchWordLine->text(), ranges[index].mStart, ranges[index].mLength, foundFiles));

        for (size_t index = 0; index < mThreads.size(); ++index)
            connect(mThreads[index], SIGNAL(completed(qint64)), mProgressBar, SLOT(progressChanged(int)));

        for (size_t index = 0; index < idealThreadCount; ++index)
            mThreads[index]->start();
        for (size_t index = 0; index < idealThreadCount; ++index)
            mThreads[index]->wait();

        std::sort(foundFiles.begin(), foundFiles.end());

        for (size_t index = 0; index < idealThreadCount; ++index)
            delete mThreads[index];

        mFoundFilesList->clear();
        for (size_t index = 0; index < foundFiles.size(); ++index)
            mFoundFilesList->addItem(foundFiles[index]);
    }
    else
    {
        mActionState = ActionState::STOPPED;
        mStartButton->setText("&Start");
        for (size_t index = 0; index < mThreads.size(); ++index)
            mThreads[index]->exit();
    }

}

Последний раз редактировалось stasJun; 17.10.2016 в 16:00.
stasJun вне форума Ответить с цитированием
Ответ


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

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Поиск слов в файле Stepan_P Linux (Ubuntu, Debian, Red Hat, CentOS, Mint) 0 25.12.2015 14:14
Поиск слов в текстовом файле slipkos Помощь студентам 4 02.06.2013 19:18
Поиск симметричных слов в файле Almost Паскаль, Turbo Pascal, PascalABC.NET 1 10.01.2013 08:53
Поиск слов в файле сушка Общие вопросы по программированию, компьютерный форум 1 08.04.2012 12:44
Поиск слов в текстовом файле svt Помощь студентам 8 07.11.2009 19:56