C++使用ifstream读取文件

11

我对在C++中使用std::ifstream有一些问题。

大部分问题都是一般性问题,我找不到答案,所以可能对其他人也有用。

无论如何,我使用#include <fstream>并创建了一个变量char line[20]

有一个文本文件,其中有几行模式为jxxx(其中x表示数字),例如:

j1234
j5678
j1111
(等等)

那么,我这样做:

#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. 为什么在 getline 方法中需要数字?

  2. line 是否自动在末尾添加 \0?因为当我们创建像 char text[5]; text = "abc1" 这样的变量时,它实际上被保存为 "acd1\0",并且文件中每个 jxxx 行后面的换行符(\n)会发生什么?(我想在比这更复杂的代码中使用这些行,所以想知道)

  3. 程序是否会自动跳到下一行?如果不是,我该如何告诉它去下一行?


2
为什么这里需要20?因为你使用的是C字符串,而不是C++字符串(std::string)。 - drescherjm
2
当 (!rfile.eof()) { - drescherjm
3个回答

22
  1. 你正在调用 std::ifstream::getline(),它需要一个指向缓冲区的 char* 指针进行输出。 getline() 要求你指定缓冲区的最大大小,以防止溢出。如果你想处理可变长度的行而不必担心溢出,你应该将 line 更改为 std::string 并使用 std::getline()

  2. 如果成功,std::ifstream::getline() 将在输出缓冲区中添加空字符终止符。这意味着最多,getline() 将读取比请求的最大大小少 1,因此请确保在传递的大小中包含空字符终止符的空间(如果 getline() 遇到换行符或 EOF,则可能会读取更少)。至于换行符本身,它们被 getline() 忽略了,不会出现在缓冲区中。

  3. 是的,代码将自动移动到下一行,所以你可以在循环中继续调用 getline()

顺便说一句:

  • while (!rfile.eof()) 使用此方法是不好的。应该使用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();
}

不需要测试if (rfile.is_open()) -- 如果流没有打开,则读取将失败。并且不需要关闭文件;析构函数会处理它的关闭。 - Pete Becker
1
@PeteBecker:我知道这一点。OP的问题显式调用了close(),因此如果open()失败,检查is_open()跳过其余代码是有意义的。是的,ifstream析构函数会关闭文件,但要等到ifstream超出范围时才会关闭。用户可以在那之前显式地close()。也许文件读取后还有更多的代码,使得ifstream保持在范围内更长时间。最好在完成文件操作后close()它(个人而言,在这种情况下,我会将ifstream包装在自己的范围内)。我的回答不做任何假设。 - Remy Lebeau

0
  1. 您提供的数字是要读取的最大字符数。
  2. 在您使用的ifstream.getline中,最后一个字符是\0。
  3. 当达到字符数或换行符时,它将返回。

看起来您想要使用getline函数,该函数可用于像getline(stream,&string,delemiter)这样的用法,因此在您的情况下:

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

这将读取文件,直到找到换行符,并将字符串(不包括换行符)存储在缓冲区中。


0
  1. getline()函数以char指针作为参数,它无法知道数组的大小,这就是为什么你必须自己传递数字,否则它可能会尝试将字符读入“数组外”的内存中。

请参见C++中将数组传递给函数

  1. Char数组默认情况下不以null结尾,必须显式地完成(就像getline()在此处所做的那样),但只有在您想将char数组用作字符串时才需要。这样,您可以编写一些函数,该函数以char*作为参数,而无需使用数组大小的附加函数,即使调用者不像您在代码中对getline()所做的那样传递它的大小,您也将知道字符串的末尾在哪里。这基本上是c-style字符串背后的思想。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接