2012-06-22 77 views
2

我得到了很多的數據點從.dat文件看起來像這樣解析一個奇怪的字符串C++

+ ( 0.00000000E+00 0.00000000E+00  //this '(' happens once per block of data 
+ 0.99999997E-04 0.00000000E+00 
+ 0.19999999E-03 0.00000000E+00 
+ ... 

我有沒有控制,以使該吐出來的這一數據更友好,我的工作程序用。

到目前爲止,我得到了一個向量中的每一行,我想解析它們,所以我只能使用這些數字,但我仍然希望保持.dat文件的完整性,因爲另一個程序使用.dat文件原樣。

我想通過空格分隔每個字符串,但空間大小不同(除非沒關係),並將它們放在向量中,只獲取我需要的數據,但數據的第一行有4個字符串,其中爲各行的其餘部分有3

任何幫助,將不勝感激

編輯: 我走原來的.dat文件,通過它跟蹤,和任何數據塊那不符合我的門檻,會被忽略。所有這些都會被寫入一個新文件。 這個新文件的所有內容都必須與原始文件完全相同,當然,減去我不需要的數據。

[JD]每個評論編輯:

我將如何分析這些線下,保持了它的一切同樣沒有關於刪除線上的任何事情,並得到號碼,以便我可以用什麼我需要保持工作我不需要什麼?

+0

現在的問題不是很清楚你寫任何東西回數據文件可以隨時正常化空間但是,如果你想正常化空間,將其寫回,你都會有。確保* other *程序不會混淆。 – dirkgently

+0

更多信息!! 好吧,所以這個.dat文件我有模擬的東西。我用20,000個模擬文件製作了文件,但由於γ射線如何與實驗相互作用,大約有17,000多個這些信號是空的。 我想跟蹤這個巨大的文件和任何通過我的條件的信號,將被寫入一個新的文件。任何不會被忽略的東西。 – shaboinkin

+0

我還不確定實際的問題是什麼。 –

回答

0

您應該使用字符串標記器來獲取每個數據。根據您已經使用的館藏,這可能非常簡單。

否則,你可以通過使用strtok來做些簡單的事情。

如果您正在使用MS CString的,你可以自己喜歡代碼的東西:

CStringArray TokenizeString(const CString& str, const CString &sep) 
{ 
    CStringArray elements; 

    CString item = ""; 
    CString strCpy = str; 
    long sepPos = strCpy.Find(sep); 

    while (sepPos != -1) 
    { 
     // extract item 
     item = strCpy.Left(sepPos); 
      // add it to the list 
     elements.Add(item); 
     // prepare next loop 
     strCpy = strCpy.Right(strCpy.GetLength() - sepPos - sep.GetLength()); // get the right part of the string (after the found separator) 
     sepPos = strCpy.Find(sep); 
    } 

    // add last item if needed (remaining part of the string) 
    if (!strCpy.IsEmpty()) elements.Add(strCpy); 
} 

希望這有助於!

3

我會創建一個ctype構面,將+( [0124]編輯:和),根據評論]分類爲空白,然後只讀取數字。讓我們假設你保留一個數字的標準是它比1.0e-4更大。將數據複製到一個新的文件,卸下較小的數字,你可以做這樣的事情:

#include <locale> 
#include <iostream> 
#include <algorithm> 
#include <iterator> 
#include <vector> 
#include <sstream> 
#include <numeric> 

class my_ctype : public 
std::ctype<char> 
{ 
    mask my_table[table_size]; 
public: 
    my_ctype(size_t refs = 0) 
     : std::ctype<char>(&my_table[0], false, refs) 
    { 
     std::copy_n(classic_table(), table_size, my_table); 
     my_table['('] = (mask)space; 
     my_table['+'] = (mask)space; 
     my_table[')'] = (mask)space; 
    } 
}; 

int main() { 
    std::locale x(std::locale::classic(), new my_ctype); 
    std::cin.imbue(x); 

    std::remove_copy_if(std::istream_iterator<double>(std::cin), 
     std::istream_iterator<double>(), 
     std::ostream_iterator<double>(std::cout, "\n"), 
     [](double in){return in < 1.0e-4; }); // criterion for removing a number 
    return 0; 
} 

我猜(但真的不知道),你的用於去除數量標準可能是一個比簡單的比較稍微複雜一些。如果它變得更加複雜,那麼您可能想要使用手動定義的函數而不是lambda來定義您的標準。其餘的代碼(尤其是讀取數據的部分)可能保持不變。

另外請注意,我剛剛寫了每行輸出一個數字。我不知道你是否需要維持一些更接近原始格式的東西,所以目前我只是保持簡單。

+0

你只需要小心處於1.0E + 00格式的指數。但除此之外,「正確的方式去做」 –

+0

@羅伯特梅森:雖然看起來這將是一個問題,但實際上並不是(我測試確定 - 它正確地將'1.0e + 01'解釋爲10. –

+0

我'll ll give this shot。謝謝! – shaboinkin

0

您可以使用文件流的operator>>一次獲取每個項目,這將跳過空格。當你到達'('或空白(例如,空格)的列時,檢查它並根據你得到的結果切換。如果你得到了「(」,再做operator>>獲得實際的數據。如果你沒有得到「(」,那麼你得到的數據,因爲operator>>跳過空白

下面是一個有希望完整的例子:。

#include <string> 
#include <iostream> 
#include <vector> 
#include <fstream> 
#include <algorithm> 
using namespace std; 

struct Inbound 
{ 
    std::string a_, b_; 
}; 

int main() 
{ 
    ifstream f("c:\\dev\\hacks\\data.txt"); 

    while(!f.bad() && !f.eof()) 
    { 
     string s; 
     f >> s; // should be '+' -- discard 
     f >> s; // either '(' or first datum 
     if(s == "(") 
      f >> s; // get the first datum 
     Inbound in; 
     in.a_ = s; 
     f >> in.b_; 

     cout << "Got: " << in.a_ << "\t" << in.b_ << endl; 
    } 

} 

輸出:?

Got: 0.00000000E+00  0.00000000E+00 
Got: 0.99999997E-04  0.00000000E+00 
Got: 0.19999999E-03  0.00000000E+00 
+0

而這看起來不太複雜:),我會試試這個。還要感謝 – shaboinkin