2017-10-12 161 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风格字符串背后的想法。