2017-10-12 85 views
0

我有一些關於在C++中使用std::ifstream的問題。使用ifstream來讀取文件的C++

大部分是一般性問題,我無法找到答案,所以也可能對其他人有用。

無論如何,我使用#include <fstream>並作出變量char line[20]

有具有圖案jxxx(其中x s爲數字)的幾行的文本文件,如:

 
j1234 
j5678 
j1111 
(and so on) 

所以,我這樣做:

#include <iostream> 
#include <fstream> 

char line[20] 
ifstream rfile; 
rfile.open("path-to-txt-file"); 
while (!rfile.eof()) { 
    rfile.getline(line, 20); (why is 20 needed here?) 
    cout >> data >> endl; 
    } 
rfile.close(); 

所以關注的是:

  1. 爲什麼在需要的數字方法?

  2. 確實line有沒有\0最後自動?因爲當我們創建char變量像char text[5]; text = "abc1"這樣的變量時,它實際上被保存爲"acd1\0",並且在每個jxxx行之後的文件末尾(\n)會發生什麼? (我想用比這更復雜的代碼行,所以想知道)

  3. 程序會自動移動到下一行嗎?如果不是,我該如何告訴它去下一行?

+2

'這裏爲什麼需要20個?',因爲不是使用C++字符串(std :: string),而是使用c字符串。 – drescherjm

+2

'while(!rfile.eof()){'https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong – drescherjm

回答

3
  1. 你調用std::ifstream::getline(),這需要一個char*指向緩衝區輸出。 getline()要求您指定該緩衝區的最大大小,使其不會溢出。如果要處理可變長度的行而不必擔心溢出,則應將line更改爲std::string,並改用std::getline()

  2. 如果成功,std::ifstream::getline()將null-terminate輸出緩衝區。這意味着至多getline()將讀取比請求的最大大小小1,因此請確保在傳遞的大小中包含空終止符的空間(如果遇到換行符或EOF,則getline()可能會讀取更少的空間)。至於換行符本身,它們被getline()吞噬,它們不會出現在緩衝區中。

  3. 是的,代碼將自動移動到下一行,因此您可以繼續調用getline()進行循環。

在一個側面說明:

  • while (!rfile.eof())is bad to use。改爲使用while (rfile)。或更好的,while (rfile.getline(line, 20))。無論哪種方式都將解決open()getline()中發生的任何錯誤,但後者確保如果getline()失敗,則不會調用cout

  • cout >> data >> endl;也是錯誤的。您需要使用<<std::cout,而data應該是line

試試這個:

#include <iostream> 
#include <fstream> 

char line[20]; 
std::ifstream rfile; 
rfile.open("path-to-txt-file"); 
if (rfile.is_open()) { 
    while (rfile.getline(line, 20)) { 
     std::cout << line << std::endl; 
    } 
    rfile.close(); 
} 

或者這樣:

#include <iostream> 
#include <fstream> 
#include <string> 

std::string line; 
std::ifstream rfile; 
rfile.open("path-to-txt-file"); 
if (rfile.is_open()) { 
    while (std::getline(rfile, line)) { 
     std::cout << line << std::endl; 
    } 
    rfile.close(); 
} 
+0

不需要測試'if( rfile.is_open()) - 如果流未打開,則讀取將失敗。並且不需要關閉文件;析構函數會這樣做。 –

+0

@PeteBecker:我知道這一點。 OP的問題明確地調用了'close()',所以如果'open()'失敗,檢查'is_open()'來繞過代碼的其餘部分是有意義的。是的,ifstream析構函數關閉了文件,但直到ifstream超出範圍。用戶可以在這段時間之前顯式地關閉()。在讀取文件之後,可能會有更多的代碼,將ifstream保持在更長的時間範圍內。最好在文件完成時關閉它(個人而言,我會在這種情況下將'ifstream'包裝在自己的範圍中)。我不會在我的答案中做出假設。 –

0
  1. 您提供有讀取字符的最大數目。
  2. 最後一個字符在ifstream.getline,您正在使用,是一個\ 0
  3. 它將在返回到達任一字符的數量或換行時

這聽起來像你想的getline函數的將在你的情況一樣使用函數getline(流&串,delemiter),所以

std::string buff; 
getline(rfile, buff) 

,直到一個換行符發現這將讀取該文件,並存儲字符串,減去換行,以拋光輪

0
  1. getline()函數將指針指向char作爲參數,它無法知道數組有多大,這就是爲什麼您必須自己傳遞數字,否則它可能會嘗試將chars讀入內存「陣列外「。

Passing arrays to function in C++

  • 字符數組不爲空默認情況下終止,他們必須明確這樣做(如函數getline()將在這裏做的),但你需要它只有當你想使用你的字符數組作爲字符串。通過這種方式,你可以編寫一些以char *作爲參數的函數,而不需要數組的大小,當你遇到0時,你會知道字符串的末尾在哪裏,即使調用者沒有傳遞它的大小你會在你的代碼中使用getline()。這幾乎是c風格字符串背後的想法。