Russian Qt Forum
Ноябрь 22, 2024, 21:00 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Почему метод QString::count(QRegExp) не находит строки типа "(текст", "текст)"?  (Прочитано 1881 раз)
billy4685
Крякер
****
Offline Offline

Сообщений: 306


Просмотр профиля
« : Июль 12, 2021, 15:04 »

Добрый день.

Когда-то был реализовал поиск текста по справке. Пользовался регулярными (QRegExp) выражениями:
   QRegExp("\\bтекст\\b") для поиска типа "только слова целиком";
   QRegExp("текст")  если не учитывая слова целиком.

Чтобы учитывать регистр использовал метод QRegExp::setCaseSensitivity(Qt::CaseSensitivity cs).
Поиск по тексту проводил методом QString::count(const QRegularExpression &re) const.

На днях заметил, что текст типа "(текст" или "текст)" моя программа не находит. В то же время, текст типа "(текст)" находит.
Регулярные выражения использовал лишь из-за того, чтобы можно было искать текст учитывая поиск "только слова целиком".
Понимаю, что проблема в регулярном выражении. Но вот понять как правильно составить регулярное выражение для поиска всевозможного
текста не могу понять.

Ниже прикрепляю небольшой пример. Может кто-то уже решал подобную проблему. Буду рад любым советам.

Исходники программы:
FindSubstring.pro
Код:
QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = FindSubstring
TEMPLATE = app

SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

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

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();

return app.exec();
}

mainwindow.h
Код:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

protected:
void changeEvent(QEvent *e);

public slots:
void substring_search();

private:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp
Код:
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
ui->setupUi(this);

ui->source_text->setFont(QFont("Times New Roman", 12, QFont::Normal));
ui->source_text->setText("Беспилотный летательный аппарат (БЛА, БПЛА; в разговорной речи также «беспилотник» или «дрон», от англ. drone — трутень) — "
"летательный аппарат без экипажа на борту."
"БПЛА могут обладать разной степенью автономности — от управляемых дистанционно до полностью автоматических, а также различаться "
"по конструкции, назначению и множеству других параметров. Управление БПЛА может осуществляться эпизодической подачей команд или "
"непрерывно — в последнем случае БПЛА называют дистанционно-пилотируемым летательным аппаратом (ДПЛА). БПЛА могут решать разведывательные "
"задачи (на сегодня это основное их предназначение), применяться для нанесения ударов по наземным и морским целям, перехвата воздушных целей, "
"осуществлять постановку радиопомех, управления огнём и целеуказания, ретрансляции сообщений и данных, доставки грузов.");


QFont standart_font(QFont("Arial", 9, QFont::Normal));
ui->case_sensitive_ch->setFont(standart_font);
ui->whole_words_ch->setFont(standart_font);
ui->find_but->setFont(standart_font);
ui->result_find_lb->setFont(standart_font);
ui->find_edit->setFont(standart_font);

connect(ui->find_but, SIGNAL(clicked(bool)), this, SLOT(substring_search()));

}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
  case QEvent::LanguageChange:
    ui->retranslateUi(this);
    break;
  default:
    break;
  }
}

void MainWindow::substring_search()
{
  ui->result_find_lb->setText("");

  if(ui->find_edit->text() == "")
    {
      ui->result_find_lb->setText("Введите текст для поиска!");
    }
  else
    {
      QString find_text;

      if(ui->whole_words_ch->isChecked() == true)
find_text = QString("\\b%1\\b").arg(ui->find_edit->text());
      else
find_text = QString("%1").arg(ui->find_edit->text());

      QRegExp reg_find_text(find_text);

      if(ui->case_sensitive_ch->isChecked() == true)
reg_find_text.setCaseSensitivity(Qt::CaseSensitive);
      else
reg_find_text.setCaseSensitivity(Qt::CaseInsensitive);

      reg_find_text.setMinimal(true);

      int count_find = ui->source_text->document()->toPlainText().count(reg_find_text);

      if(count_find == 0)
ui->result_find_lb->setText("В данном тексте нет такой подстроки.");
      else
ui->result_find_lb->setText(QString("В данном тексте введенная вами строка "
   "встречается %1 раз.").arg(count_find));
    }
}

Скрин програмки и архив:
« Последнее редактирование: Июль 12, 2021, 15:07 от billy4685 » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #1 : Июль 12, 2021, 17:52 »

потому что скобка — это спецсимвол регулярок (один из), обозначающий «захватывающую группу». скобки должны быть сбалансированы для того, чтобы регулярка была валидная.

для включения литеральной скобки (и прочих особых символов) в искомое выражение, необходимо ее экранировать с помощью обратной косой черты: \(. (в С++ строке саму обратную косую черту также надо экранировать: "\\(")

чтобы не возиться с ручным экранированием, есть удобный метод QRegularExpression::escape(): https://doc.qt.io/qt-5/qregularexpression.html#escape
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
billy4685
Крякер
****
Offline Offline

Сообщений: 306


Просмотр профиля
« Ответ #2 : Июль 13, 2021, 13:10 »

kambala, благодарю за ответ.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.064 секунд. Запросов: 23.