簡體   English   中英

解析C ++字符串

[英]Parsing C++ strings

這里有很多關於發布字符串的文章,但實際上似乎不適合我的目的。

我正在使用std::string和所有C ++標准庫,並且我有一個使用以下協議的文本文件:

TEXT1:TEXT2-TAB-TEXT3:TEXT4 TEXT5

-TAB-\\t

我想將所有文本都轉換成字符串(也可以是數組)。 文件中的所有行都是以這種方式編寫的,我嘗試使用istringstream但它沒有功能,例如: iss >> text1 >> ":" >> text2 >> "\\t" >> text3 >> ":" >> text4 >> " " >> text5

我實際上是否需要使用find等的基本功能進行解析? 那將是大量的工作(因為我有幾個用不同格式編寫的文件,並且我需要為所有這些文件創建通用功能),但是如果我別無選擇,我會這樣做。

那么...有什么方法可以使用字符串之間的已知字符以下列方式解析字符串? 它不是特定的定界符,因為每一行都包含幾個定界符(一次是空格,然后是冒號,等等)。 我想使用C ++標准庫,而不要使用任何外部庫,如Boost。

編輯:C ++ 11。

由於您使用的是C ++ 11,並且文本行遵守協議,因此用於模式匹配和信息提取的工具就是regex庫中的功能。

符合您協議的模式可能看起來像這樣...

\\ w +:\\ w +-\\ t- \\ w +:\\ w + \\ s \\ w +

...使用默認的ECMAScript語法。 還有一些。

接下來,使用原始字符串文字來初始化正則表達式對象。

regex pat {R(“ \\ w +:\\ w +-\\ t- \\ w +:\\ w + \\ s \\ w +”)};

所以現在您的代碼可以看起來像這樣...

#include<regex>
...

regex pat{R("\w+:\w+-\t-\w+:\w+\s\w+")};
smatch m;

while (cin >> str) {  // where str is your line of formatted text
    bool match = regex_search(str, m, pat);
    for (int i = 0; i < m.size(); i++) {
        cout << m[i].str() << " "; // to make sure each component was matched
    }   
}

順便說一下, smatch就像一個容器一樣工作,並且可以迭代,因此非常方便。

注意 :上面的代碼不能保證能正常工作,它僅用作指導。

由於您有一個固定的單個字符來標記每個字段的結尾,因此諸如正則表達式之類的字詞會在過度殺傷時產生邊界。 我只是使用std::getline來讀取每個字段。

我將從在一行中為字段定義一個結構開始,然后重載operator>>以讀取這些結構之一:

struct line { 
    std::string text1, text2, text3, text4, text5;

    friend std::istream &operator>>(std::istream &is, line &l) {
        std::getline(is, l.text1, ':');
        std::getline(is, l.text2, '\t');
        std::getline(is, l.text3, ':');
        std::getline(is, l.text4, ' ');
        std::getline(is, l.text5);
        return is;
    }
};

這樣,您可以閱讀如下內容:

line x;

std::cin >> x;

...或者,如果您的整個文件中都包含這樣的行,則可以將它們全部讀入向量,例如:

std::ifstream infile("whatever.dat");

std::vector<line> lines {
    std::istream_iterator<line>(lines),
    std::istream_iterator<line>()
};

您可能應該使用std :: getline閱讀整行,然后解析該行,例如,使用std :: string的 findfind_first_of方法找到 '\\t'字符。

如果可能,請至少切換到C ++ 11 ,因為C ++ 11的許多功能將使您編寫更少的代碼。 與匿名lambda一起使用時,特別是<algorithm> std :: find會很有幫助。

當然,您應該更正式地定義可接受的輸入(也許使用一些EBNF表示法,至少在注釋中)。 特別是,您的TEXT1TEXT2TEXT3以及TEXT4TEXT5可以出現哪些確切字符。 用什么編碼? UTF-8具有多字節字符!)。

如果輸入規范很復雜,則可以考慮使用一些解析器生成器,例如ANTLR等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM