【问题标题】:Getline is returning nothing but blankGetline 只返回空白
【发布时间】:2016-01-26 04:39:04
【问题描述】:

我正在尝试连续打开许多文件。文件名都存储在一个向量中,该向量被传递给我的函数。这只是一个简单的测试,以确保一切正常。如果它有效,那么我需要将文件包含的任何内容推回另一个向量中。

void readfile(vector<string> &filename)
{
    string temp;
    ifstream infile(filename[2].c_str());
    getline (infile, temp);
    cout << temp << endl;
}

这只是简单地输出一个空行,尽管文本文件包含一段信息。我有一段时间没有使用文件 I/O,所以我有点生疏了。任何帮助表示赞赏。

编辑:你们都帮了大忙,还有一件事,我需要在没有句号或空格的情况下传递它们。基本上只是一串字符。

【问题讨论】:

  • 您的平台的行分隔符是什么?

标签: c++ file-io vector getline


【解决方案1】:

OP 的代码不会检查他们的任何文件 IO 是否成功,因此文件可能尚未打开,文件可能为空,并且读取可能由于多种原因而失败。

幸运的是,getline 返回输入流,并且流实现了一个非常简洁的运算符 bool,如果流处于错误状态并且无法读取,则返回 false。如果无法读取文件,则 temp 的内容肯定是无效的,不应使用。

所以...

void readfile(vector<string> &filename)
{
    string temp;
    ifstream infile(filename[2].c_str());
    if (getline (infile, temp)) //test the read for success
    {
        cout << temp << endl;
    }
    else
    {
        cout << "failed to read file" << endl;
    }    
}

如果 getline 由于任何原因失败,包括文件未打开、文件为空、文件损坏且无法读取,则流的状态将被标记为错误并在if() 检查时返回 false。

通常此时您应该检查错误的类型,infile.clear() 流以删除错误条件,然后收拾残局,但在这种情况下没有多大意义。如果您无法将文件的开头读入字符串,那么您就会遇到大问题,应该仔细查看文件 filename[2] 的运行状况和内容。

顺便说一下,如果你的编译器是最新的,ifstream 的构造函数会吃掉一个 std::string 并且ifstream infile(filename[2]); 将是有效的。

风格方面,最好将文件名字符串传递给 readfile,而不是向量。这使您可以将 readfile 函数重用于向量的元素 2 以外的地方。

void readfile(string & filename)
{
    string temp;
    ifstream infile(filename);
    if (getline (infile, temp)) //test the read for success
    {
        cout << temp << endl;
    }
    else
    {
        cout << "failed to read file " << filename << endl;
    }    
}

并调用

readfile(filename[2]);

扩展此功能以实现 OP 的真正目标

void readfile(string & filename,
              vector<string> & strings)
{
    string temp;
    ifstream infile(filename);
    if (getline (infile, temp)) //test the read for success
    {
        strings.push_back(temp);
        cout << temp << endl;
    }
    else
    {
        cout << "failed to read file " << filename << endl;
    }    
}

并调用

vector<string> strings;
...
readfile(filename[2], strings);

【讨论】:

  • 这会推回没有空格和句点的字符串吗?
  • 没有。这将需要在这里选择的答案中很好地涵盖了一堆字符串操作:stackoverflow.com/questions/5891610/…。使用类似的方法从temppush_back 中删除您不想要的字符。
【解决方案2】:

您的函数假定文件名向量中至少有三个元素,并忽略除第三个(元素 2)之外的所有文件名。

此外,对 getline() 的调用仅读取文件的 第一 行 -- 这可能是一个空行。

我建议您编写一个函数来提取单个文件的内容,并在循环中使用它(在另一个函数中?)来处理文件名列表中的每个文件名。

与此相关,“文件名”表示单个文件名; 'filenames' 会更好地表明您的变量是 多个 文件名。

// Return file content as a single string
string readfile( const string& filename )
{
  ifstream f( filename );
  stringstream ss;
  ss << f.rdbuf();
  return ss.str();
}

// Return file content as a vector/deque/whatever of strings
deque<string> readfile( const string& filename )
{
  ifstream f( filename );
  deque<string> lines;
  string line;
  while (getline( f, line )) lines.emplace_back( line );
  return lines;
}

不报告错误。 (你只会有一个空字符串/向量/双端队列/等)

在循环的其他地方使用它。这里我有一个文件名->文件数据的映射,加载文件名列表中的每个文件名:

for (const string& filename : filenames)
  filedata[ filename ] = readfile( filename );

希望这会有所帮助。

【讨论】:

  • 我拥有的将文件名读入向量的函数完美运行,我可以将 filenames[k].c_str() 传递给第一个函数,让它打开特定文件,然后 push_back 它返回什么进入另一个向量?
  • 当然。另外,请注意下面@user4581301 的回答,因为他谈到了在出现问题时特别注意,我在这里忽略了这一点。
猜你喜欢
  • 1970-01-01
  • 2011-04-02
  • 2018-12-23
  • 2017-11-20
  • 1970-01-01
  • 2011-05-27
  • 2012-09-06
  • 2018-11-27
  • 1970-01-01
相关资源
最近更新 更多