2015-08-17 58 views
1

目前我正在試圖操縱一個文本文件中的文本(不使用矢量)編輯文本文件:C++使用ofstream的

(這是一個工程文件的任務,而我不能使用載體)

可變numRows行可以是任意整數(我選擇3只是在這個例子中),並在我的輸出文本文件「example.txt中」

這裏元素的平方矩陣是我的代碼:

#include <iostream> 
#include <fstream> 
using namespace std; 

int main() { 

int numRows = 3; 

    ofstream myfile ("example.txt"); 
    if (myfile.is_open()) 
    { 
    for (int i = 0; i < numRows; i++) { 
    for (int j = 0; j < numRows; j++) { 
    myfile << "Test\t"; 
    } 
    myfile << "\n"; 
    } 
    myfile.close(); 
    } 

    else cout << "Unable to open file"; 

    return 0; 
} 

文本文件如下:

Test Test Test  
Test Test Test  
Test Test Test  

我的問題是,一旦我做了這一切 - 我該如何再次打開它,並進行修改?例如。說我想編輯第2行第2列到「你好」:

Test Test Test  
Test Hello Test  
Test Test Test  

我該怎麼做?我需要能夠操作存儲在這個文本文件中的字符串和我不確定該怎麼做,因爲我已經由製表符

感謝您抽出時間來幫助分離每串!

回答

1

由於大多數文件系統(和標準文件I/O API)僅支持覆蓋文件內容,所以在「編輯」這樣的文件方面不太現實,因爲大多數文件系統(和標準文件I/O API)僅支持覆蓋文件內容 - 不能用文本替換某些文本不同的長度並且使文件相應地調整剩餘文件內容的位置。因此,最好將文件讀入內存中的某些變量,在那裏進行編輯,然後在您完成所需的所有編輯時寫出更新的內容(即覆蓋整個文件)。要閱讀文件,您可以使用std::ifstream。爲了將文件存儲在內存中,std::vector<std::vector<std::string>> - 其中vectors代表行/行,並且該行/行中的內部vector列值似乎與給出問題描述的天然匹配,但您可以考慮std::vector<std::string>,其中每個string代表包含製表符的完整行/行。 (如果你知道單個字符串的寬度的上限(在你的例子中爲"Text""Hello"),並且很樂意用空格而不是尾部標籤填充每個字符串的寬度,那麼你可以覆蓋文本和空格,而不用該文件需要調整大小(只要不改變行數/行數或添加/刪除列)。要做到這一點,您需要將"seek"std::fstream設置爲您想要替換值的位置)

進一步討論註釋,如果你堅持直接更改文本文件,一個簡單的選擇是在讀取原始文件時編寫更新的文件,然後將更新後的輸出文件在原始文件之後移動。更新的輸出文件的實際發電可能看起來是這樣的:

#include <fstream> 
#include <iostream> 

void edit_file(int line_to_change, int column_to_change, const std::string& change_to) 
{ 
    if (std::ifstream in{"txt_in"}) 
     if (std::ofstream out{"txt_out"}) 
     { 
      int line = 1, column = 1; 
      std::string word; 
      char whitespace; 
      while (in >> word && in.get(whitespace)) 
      { 
       if (line == line_to_change && column == column_to_change) 
        word = change_to; 
       out << word << whitespace; 
       if (whitespace == '\n') // newline... 
       { 
        ++line; 
        column = 1; 
       } 
       else // presumably a tab... 
        ++column; 
      } 
     } 
     else 
      std::cerr << "unable to open output file\n"; 
    else 
     std::cerr << "unable to open input file\n"; 
} 

int main() 
{ 
    edit_file(2, 2, "Hello"); 
} 

注:

  • in.get(whitespace)代替>>,因爲後者跳過空白而這正是我們所需要閱讀爲了區分製表符和換行符

  • 將輸出發送到不同的文件可以防止在插入比先前包含的文件更長的「單詞」時的麻煩,如果完成了天真的話Ÿ將覆蓋你就要寫輸入,如果處理得當,需要緩衝任意數量的內存

+0

問題是我不能使用這個項目的矢量,並且我需要能夠在不同的時間點處理行和列。我將如何做到這一點,並可能擔心後面的標籤空間等? – Jared

+0

@Jared:使用'new []'您可以手動分配動態內存是一種功能上等同於矢量的方式,但是初學者在這樣做時往往會犯很多錯誤。另一種方法是即時讀取和修改文件,隨時寫出新值,而不是一種可擴展的方法,如果您要進行較長的更新或處理大型文件,性能明智,但也許您不。 –

2

在典型的文件系統,你不能在任意posistions插入字符。如果你想在原地「編輯」一個文件,你可以使用格式,每個記錄佔用一定數量的空間。當然,每個記錄的大小將受到這個固定金額的限制。例如,您可以使用每個記錄10個字節,將最大大小限制爲10.如果記錄更短,您可以用一些不可能發生的字節(例如製表符)填充或使用合適的字節數在記錄的固定位置指定使用的字符串的大小。對於最多255個字節,將使用一個額外的字節。

由於記錄具有固定的大小,因此您可以尋找修改後的記錄的位置:起始位置爲(row * columns + column) * record_size。您只需編寫新值(如果您選擇保存大小,字符串在記錄中的大小)。

如果您需要支持沒有上限的變長字符串,或者您需要使用緊湊表示,上述方法不起作用。你需要完全重寫文件。對此你會

  1. 打開輸入文件進行閱讀。
  2. 打開臨時文件進行書寫。
  3. 將每個未更改的記錄prio讀入chang並將其寫入臨時文件。
  4. 閱讀更改後的記錄,不做任何事情。
  5. 將新值寫入臨時文件。
  6. 將輸入文件的其餘部分複製到臨時文件中。
  7. 關閉這兩個文件。
  8. 將臨時文件重命名爲源文件名。

顯然,如果您需要一次執行多個編輯,您可以根據需要繼續進行復制/替換。儘管如此,這種方法仍然保持幾乎相同。

我可以輕鬆地爲您的作業分配編寫代碼,但上面已經刪除了所有分配的思路。另外,我並不需要練習編程,所以我會跳過提供代碼。