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