Qt C ++ QTextEdit在输入时计算单词

时间:2013-04-06 13:28:08

标签: c++ qt

我需要在Qt C ++中实现方法,该方法在用户类型时计算QTextEdit中的单词数。此外,当用户键入多个空格时,不应将它们视为单词。我知道如何在已打字的文本上执行此操作,但我需要一直更新单词的总数。 你能帮我解决这个问题。

5 个答案:

答案 0 :(得分:1)

我建议你连接void QTextEdit::textChanged () [signal]并使用类似的东西:

void onTextChanged()
{
    int wordCount = textEdit->toPlainText().split(QRegExp("(\\s|\\n|\\r)+")
                                                  , QString::SkipEmptyParts).count();
}

答案 1 :(得分:0)

你几乎不得不自己解析它,用一个分割器拆分字符串对于生产来说不是一个好的解决方案。这是我前段时间写过的一个简单的解析器,它正是这样做的:

void processChar(const QChar &ch)
{
    // if char is not separator
    if (!sp[ch.unicode()]){
        if (!isWord){ // set where word begins
            wordBegin = counter;
            isWord = 1;
        }
        ++textChar;
    }
    // if char is separator
    else{
        // if there is a current word
        if (isWord){
            QString tempWord(text.mid(wordBegin, counter - wordBegin));
            tempWord = tempWord.toLower();
            // if word does not exist add with value one
            if (!words.contains(tempWord)){
                words.insert(tempWord, 1);
                ++uniqueWords;
            }
            // if word exists find its value and increment by one
            else {
                words.insert(tempWord, words.value(tempWord) + 1);
            }
            ++totalWords;
            isWord = 0;
        }
        // else skip
        ++sepChar;
    }
}

您为文字的每个字符致电processChar()

它非常快,它使用包含所有字符的查找表(字符数组)sp并标记分隔符。以下是从所有分隔符的QString填充表的方法。

void indexChars()
{
    // zero everything
    for (unsigned i = 0; i < 65536; ++i) sp[i] = 0;

    // set every separator index to 1
    for (int i = 0; i < separators.length(); ++i) {
        sp[separators.at(i).unicode()] = 1;
    }
}

该表非常大,因为我希望能够处理16位字符。

它有多快 - 尽管做了额外的工作,它比MS Word的字数快20倍,而且它实际上创建了文本中每个唯一字的列表加上存储在QMap中的出现次数words。它会跟踪文字字符textChar,分隔符sepChar,总字数和唯一字词。

功能可能有点矫枉过正,但如果你不需要所有额外的东西,你可以将其剥离。如果删除不需要的内容,它会更快。

您可以使用这些代码段,并使用计时器定期计算自上次计数后文本已更改的单词,这是替代方案中更好的解决方案 - 依靠文本字段的每个类型字符。

答案 2 :(得分:0)

编辑:
我以为我记得QTextDocument是如何工作的(我认为在实际更改之前调用了contentsChange(int position, int charsRemoved, int charsAdded))。我错了,或者新版本的行为可能已经改变了。无论如何使用当前版本(5.0.1)我没有看到如何计算字数的校正。看起来这是不可能的。至少我没有办法计算删除了多少个单词。

收听来自QTextDocument的两个信号:contentsChange(int position, int charsRemoved, int charsAdded)contentsChanged()。 首先是在文档修改之前触发,然后是第二次。使用此信息:position,charsRemoved,charsAdded;计算对单词总数的修正。

答案 3 :(得分:0)

如果您想从头开始计算文档包含的单词数,那么最佳解决方案是:

void MainWindow::docChanged()
{
    QTextDocument *doc = qobject_cast<QTextDocument *>(sender());
    QRegExp re("\\b\\w+\\b");
    int wordCount = 0;
    QTextCursor c = doc->find(re);
    while (!c.isNull()) {
        wordCount++;
        c = doc->find(re, c);
    }
    ui->labelWordCount->setText(QString::number(wordCount));
}

答案 4 :(得分:0)

我就是这样做的,我在这个帖子上做了一些答案的组合。我注意到这个解决方案非常快,如果不需要它也不会浪费资源。它只在您键入时检查部分文本,只有粘贴文本然后检查整个文本。我希望有人检查此代码并发布一些反馈。这是代码:

size = 0;
counter = 0;
start = 0;
end = 0;
void MainWindow::count()
{
    text = ui->textEdit->toPlainText();
    if(text.length()-size == 1){
    if(text.length() == 1){
    if(!text.at(0).isSpace()){
        counter++;
        ui->label_2->setText(QString::number(counter));
    }}

    if(text.length()>2){
    start = text.length()-1;
    end = text.length();
    if(text.at(start-1).isSpace() && !text.at(end-1).isSpace()){
        counter++;
        ui->label_2->setText(QString::number(counter));
    }}}
    else if(text.length()-size > 1){
    counter = 0;
    if(!text.at(0).isSpace()) counter++;
        for(int i = 1; i<text.length();i++){
            if(!text.at(i).isSpace() && text.at(i-1).isSpace())
                counter++;

        }
        ui->label_2->setText(QString::number(counter));
    }
    size = text.length();
}