2016-04-26 81 views
1

我有一個〜250k行的文本文件。每行包含由多個空格和可能的其他符號分隔的數據。我想逐行解析數據,從每行中檢索某些組件。解析C++中的大文本文件

我已經編寫了一個程序,用於打開輸入文件和輸出文件,逐行解析輸入文件,將行分解爲適當的標記並重新構建所需格式的新行,並立即輸出到輸出文件中。

問題是,當我運行它時,解析70到92k行後停止。通過攤位我的意思是程序仍然運行,但它不處理任何事情,並且我的終端中的光標停留在那裏並閃爍。通過使用愚蠢的調試(使用cout),我檢查了92521線,它確實需要一條輸入線(一條正確的線),但是它並沒有通過分解成令牌和重建格式良好的線路的部分而停下來。

下面我附上相關的代碼。我期待有人告訴我發生了什麼,也就是爲什麼我的程序停滯不前,以什麼方式解決這個問題。感謝您的關注!

#include <iostream> 
#include <fstream> 
#include <cstring> 
#include <sstream> 

int main(int argc, char** argv) { 
    std::ifstream inFile; 
    std::ofstream outFile; 
    std::string inDir("/home/marcin/jnp2/proj/data/oceny.txt"); 
    std::string outDir("/home/marcin/jnp2/proj/data/ocenyout.txt"); 
    outFile.open(outDir, std::ios::out | std::ios::app); 
    inFile.open(inDir, std::ios::in); 
    std::string line; 
    int i = 1; 
    while(std::getline(inFile, line, '\n')) { 
    //for(int i = 0; i < 251819; i++) { // 197858 
     //std::string line; 
     //std::getline(inFile, line, '\n'); 
     //std::cout << "OK1" << std::endl; 
     if(i == 92520) { 
      int x; 
      std::cin >> x; 
     } 
     if(!line.empty() && line[0] != '-' && line[0] != 'K' && line[0] != 'S') { 
      //std::cout << line << std::endl; 
      std::istringstream iss(line); 
      std::string code, name, dyd_cycle, term, grade, person, tmp; 
      iss >> code; 
      std::size_t found; 
      do { 
       if(iss >> tmp) { 
        //iss >> tmp; 
        found = tmp.find("20"); 
        if (found == std::string::npos) 
        if(name.empty()) 
         name = tmp; 
        else 
         name = name + " " + tmp; 
        else 
         dyd_cycle = tmp; 
       } else 
        return 42; 
      } while (found == std::string::npos); 
      //std::cout << "OK2" << std::endl; 
      iss >> term; 
      iss >> grade >> person; 
      std::string formattedLine = code + ";" + name + ";" + dyd_cycle + ";" + term + ";" + grade + ";" + person; 
      outFile << formattedLine << std::endl; 
     } 
     //std::cout << "OK3" << std::endl; 
     std::cout << i++ << std::endl; 
    } 
    inFile.close(); 
    outFile.close(); 
    return 0; 
} 

編輯:最後的輸出停止在 「1000-621MRB; Metody realizacji巴茲danych; 2004/TL; 3; 2; LONG_CODE_THAT_IM_NOT_SUPPOSED_TO_SHOW」。

我會另外提到,當我一點一點做到這點時,即第一個50k行,然後告訴程序(通過硬編碼它跳過第一個50k行)從50k + 1行開始等,沒有問題 - 我得到了應有的確切輸出。另一方面,當我告訴它每隔5萬行關閉文件時,重新打開它們並循環到輸入文件的正確行,然後我仍然遇到同樣的問題。

編輯2:我編譯成調試和使用GDB - 圍繞關鍵線數正確地得到了線(歡呼),但卡在iss >>代碼。我在CLion中使用調試器,所以它在一段時間後才超時。

+3

和你有沒有嘗試使用真正的調試器打入並看看發生了什麼? – pm100

+1

內循環看起來非常可疑。如果沒有「20」事件怎麼辦?我也不喜歡那個沒有大括號的「if」。 – pm100

+0

發佈它處理的最後一行的內容。另外,請修復您的縮進。 – xaxxon

回答

1

使用cout並不總是最好的調試方式,因爲我發現它有時會讓程序的終端/整體速度變得糟糕。您可以嘗試使用斷言或實際的調試器(如GDB)來調試您的程序。一個調試器會引導你通過你的代碼,並告訴你到底發生了什麼。

+0

謝謝你的建議。我試着再次調試,發現有一個錯誤的輸入,導致我的代碼進入一個永恆的循環。 –

+0

很高興知道你明白了。如果您還沒有:),請務必提高答案:) –

+0

問題是,我從許多人的評論中收集了答案(加上你的答案)......我也無法提高答案,因爲我沒有還有15位代表:/我想代表5位代表回答問題,並感謝其他兩位代表提出改進代碼的建議。 –

0

我確實有一個錯誤的日期 - 檢查「20」導致程序進入一個永恆的循環。我要感謝pm100和George Sovetov指出那些代碼有潛在危險。我使用調試器來查找問題 - 我感謝Developer和pm100提供的建議。感謝gudok,我用了一張支票來看看是否>> tmp有效,這讓我注意到我的循環會變得過於永恆。

我會修復代碼並使用正則表達式來希望避免任何其他形式的此類錯誤(按照knivil的建議)。我也會用'\ n'而不是std :: endl,就像kchinger提出的那樣。謝謝各位的評論! :)