2016-08-08 65 views
0

我正在研究文本標記器。 ICU是具有此功能的極少數C++庫之一,並且可能是維護最好的一個,所以我想使用它。 我發現了有關BreakIterator的文檔,但有一個問題:如何將標點符號排除?將文本拆分爲與ICU的單詞列表

#include "unicode/brkiter.h" 

#include <QFile> 

#include <vector> 

std::vector<QString> listWordBoundaries(const UnicodeString& s) 
{ 
    UErrorCode status = U_ZERO_ERROR; 
    BreakIterator* bi = BreakIterator::createWordInstance(Locale::getUS(), status); 

    std::vector<QString> words; 

    bi->setText(s); 
    for (int32_t p = bi->first(), prevBoundary = 0; p != BreakIterator::DONE; prevBoundary = p, p = bi->next()) 
    { 
     const auto word = s.tempSubStringBetween(prevBoundary, p); 
     char buffer [16384]; 
     word.toUTF8(CheckedArrayByteSink(buffer, 16384)); 
     words.emplace_back(QString::fromUtf8(buffer)); 
    } 

    delete bi; 

    return words; 
} 

int main(int /*argc*/, char * /*argv*/ []) 
{ 
    QFile f("E:\\words.TXT"); 
    f.open(QFile::ReadOnly); 

    QFile result("E:\\words.TXT"); 
    result.open(QFile::WriteOnly); 

    const QByteArray strData = f.readAll(); 
    for (const QString& word: listWordBoundaries(UnicodeString::fromUTF8(StringPiece(strData.data(), strData.size())))) 
    { 
     result.write(word.toUtf8()); 
     result.write("\n"); 
    } 

    return 0; 
} 

當然,生成的文件是這樣的:

「 
Come 

outside 
. 

Best 

if 

we 

do 

not 

wake 

him 
. 
」 

我需要的是只是的話。如何才能做到這一點?

+0

[ispunct](http://www.cplusplus.com/reference/cctype/ispunct/)函數呢?您可以檢查令牌是否由一個字符組成,然後將其作爲整數並檢查該功能。 –

+0

@BiagioFesta:首先,我在這裏有很多非ASCII字符(如引號)。其次,非單詞不一定是單個字符(例如,逗號+空格+開頭引號)。 –

回答

1

QT庫包含幾種有用的檢查char屬性的方法: QChar

事實上,你可以創建一個從緩衝的QString變量,並檢查你需要之前插入到輸出載體的所有屬性。

例如:

auto token = QString::fromUtf8(buffer); 
if (token.length() > 0 && token.data()[0].isPunct() == false) { 
    words.push_back(std::move(token)); 
} 

與該代碼我能訪問字符串的第一個字符,並檢查 它是否是一個標點符號或沒有。

東西更健壯,我表達的功能:

bool isInBlackList(const QString& str) { 
    const auto len = str.lenght(); 
    if (len == 0) return true; 
    for(int i = 0; i < len; ++i) { 
    const auto&& c = str.data()[i]; 
    if (c.isPunct() == true || c.isSpace() == true) { 
     return true; 
    } 
    } 
    return false; 
} 

如果該函數返回,令牌還沒有被插入載體。

+0

這根本不是一個壞主意。雖然我只是爲了方便而使用Qt,並希望最終的解決方案僅依賴於ICU和stdlib。換句話說,我是否可以僅使用ICU檢查標點符號? –

+0

ICU沒有任何這種類型的方法。目前我正在考慮REGEX:[Regex Class ICU](http://icu-project.org/apiref/icu4c/classicu_1_1RegexMatcher.html)。您可以重新實現函數* isInBlackList *,只需在字符串中檢查標點符號。如果你需要它,讓我知道,我會編輯答案,添加這種解決方案! –

+0

謝謝。我現在不想爲此煩惱,也許很快就會有更好的解決方案出現。我也有關於正則表達式的性能保留。寧願將黑名單實現爲Unicode代碼點的「std :: set」,但我不想手動填充此列表 - 我們無法指定全部的LOTS非文本Unicode字符。 –

相關問題