【问题标题】:Reading line from text file and putting the strings into a vector?从文本文件中读取行并将字符串放入向量中?
【发布时间】:2012-01-11 23:52:54
【问题描述】:

我正在尝试读取每行包含一个单词的文本文件的每一行,并将这些单词放入一个向量中。我该怎么做呢?

这是我的新代码:我觉得还是有问题。

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

int main()
{
    std::string line;
    vector<string> DataArray;
    vector<string> QueryArray;
    ifstream myfile("OHenry.txt");
    ifstream qfile("queries.txt");

    if(!myfile) //Always test the file open.
    {
        cout<<"Error opening output file"<<endl;
        system("pause");
        return -1;
    }
    while (std::getline(qfile, line))
    {
        QueryArray.push_back(line);
    }
    if(!qfile) //Always test the file open.
    {
        cout<<"Error opening output file"<<endl;
        system("pause");
        return -1;
    }

    while (std::getline(qfile, line))
    {
        QueryArray.push_back(line);
    }

    cout<<QueryArray[0]<<endl;
    cout<<DataArray[0]<<endl;

}

【问题讨论】:

  • 到目前为止的代码有什么问题?
  • @Mahesh 这个 if(!myfile) 可能是第一个问题。 (对不起..需要学习STL。)
  • @RomanB:那行没有错。
  • @DeadMG 现在我明白了为什么运算符重载会受到如此批评。

标签: c++ fstream


【解决方案1】:

@FailedDev 确实列出了最简单的形式。作为替代方案,这是我经常编写该循环的方式:

std::vector<std::string> myLines;
std::copy(std::istream_iterator<std::string>(myfile),
          std::istream_iterator<std::string>(),
          std::back_inserter(myLines));

整个程序可能如下所示:

// Avoid "using namespace std;" at all costs. Prefer typing out "std::"
// in front of each identifier, but "using std::NAME" isn't (very) dangerous.
#include <iostream>
using std::cout;
using std::cin;
#include <fstream>
using std::ifstream;
#include <string>
using std::string;
#include <vector>
using std::vector;
#include <iterator>
using std::istream_iterator;
#include <algorithm>
using std::copy;

int main()
{

    // Store the words from the two files into these two vectors
    vector<string> DataArray;
    vector<string> QueryArray;

    // Create two input streams, opening the named files in the process.
    // You only need to check for failure if you want to distinguish
    // between "no file" and "empty file". In this example, the two
    // situations are equivalent.
    ifstream myfile("OHenry.txt"); 
    ifstream qfile("queries.txt");

    // std::copy(InputIt first, InputIt last, OutputIt out) copies all
    //   of the data in the range [first, last) to the output iterator "out"
    // istream_iterator() is an input iterator that reads items from the
    //   named file stream
    // back_inserter() returns an interator that performs "push_back"
    //   on the named vector.
    copy(istream_iterator<string>(myfile),
         istream_iterator<string>(),
         back_inserter(DataArray));
    copy(istream_iterator<string>(qfile),
         istream_iterator<string>(),
         back_inserter(QueryArray));

    try {
        // use ".at()" and catch the resulting exception if there is any
        // chance that the index is bogus. Since we are reading external files,
        // there is every chance that the index is bogus.
        cout<<QueryArray.at(20)<<"\n";
        cout<<DataArray.at(12)<<"\n";
    } catch(...) {
        // deal with error here. Maybe:
        //   the input file doesn't exist
        //   the ifstream creation failed for some other reason
        //   the string reads didn't work
        cout << "Data Unavailable\n";
    }
}

【讨论】:

  • 我需要什么包含和命名空间?
  • 甜蜜让它发挥作用。太感谢了。这绝对是更容易和更清洁。
  • @user977154 我很肯定你不知道它是如何工作的。你呢?
  • 如果行中有空格,此解决方案将不起作用。这些空格被视为行分隔符。
  • @void.pointer - 该条件违反了问题中所述的前提 - “每一行包含一个单词”。在这种情况下,也许我的代码正是 OP 想要的,也可能不是。
【解决方案2】:

最简单的形式:

std::string line;
std::vector<std::string> myLines;
while (std::getline(myfile, line))
{
   myLines.push_back(line);
}

不需要疯狂的 c 东西 :)

编辑:

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

int main()

{
    std::string line;
    std::vector<std::string> DataArray;
    std::vector<std::string> QueryArray;
    std::ifstream myfile("OHenry.txt");
    std::ifstream qfile("queries.txt");

    if(!myfile) //Always test the file open.
    {
        std::cout<<"Error opening output file"<< std::endl;
        system("pause");
        return -1;
    }
    while (std::getline(myfile, line))
    {
        DataArray.push_back(line);
    }

    if(!qfile) //Always test the file open.
    {
        std::cout<<"Error opening output file"<<std::endl;
        system("pause");
        return -1;
    }

    while (std::getline(qfile, line))
    {
        QueryArray.push_back(line);
    }

    std::cout<<QueryArray[20]<<std::endl;
    std::cout<<DataArray[12]<<std::endl;
    return 0;
}

使用的关键字是非法的 C++!永远不要使用它。好吗? 很好。现在比较我写的和你写的,试着找出不同之处。如果您仍有问题,请回来。

【讨论】:

  • 我修复了帖子中的代码,我现在做错了什么?因为我需要处理两个不同的文本文件。顺便说一句,非常感谢您的帮助。
  • @user977154 你不需要外部的while循环。去掉它!在这两种情况下。另外你确定你的向量中存在 12 和 20 行吗?
  • 是的,我很肯定我的测试文件中有超过 20 行填充。而且我一直收到错误提示错误打开输出文件
  • 等一下。我知道这是一个旧帖子-但这很危险。 C ++中的关键字'使用'非法是什么方式? Using 与命名空间一起被引入到语言中。 “使用 std::cout”是完全有效的。 “使用标准”是完全有效的,尽管是不好的做法。
  • @gamers2000 有点讽刺。 int * aPtr = NULL; *aPtr = 5; // is also perfectly valid but should be considered illegal...
【解决方案3】:

最简单的版本:

std::vector<std::string> lines;
for (std::string line; std::getline( ifs, line ); /**/ )
   lines.push_back( line );

我省略了包含和其他垃圾。我的版本与 FailedDev 的版本几乎相同,但通过使用“for”循环,我将“line”的声明放入循环中。这不仅仅是减少行数的技巧。这样做会缩小行的范围——它在 for 循环之后消失。所有变量都应该具有尽可能小的范围,因此这更好。 for 循环很棒。

【讨论】:

  • 优秀。使用using namespace std; 更清洁,因此可以删除所有std::。缺少“ifs”声明,声明如下:ifstream ifs(textFilePath, ios::in);
  • ifs 的范围更小:for(auto [line, ifs] = std::make_tuple&lt;std::string, std::ifstream&gt;("", std::ifstream(log_filename)); std::getline(ifs, line);) lines.push_back(line);
【解决方案4】:

适用于 C++11 及更高版本的简短版本。向量是直接从文件内容构造的:

ifstream qfile("queries.txt");
vector<string> lines {
    istream_iterator<string>(qfile),
    istream_iterator<string>()
};

请注意,此代码仅在输入文件采用 OP 描述的格式时才有效,即“每一行包含一个单词”。或者,如果您通过 qfile.imbue() 设置特殊语言环境,正如 mheyman 所指出的那样。

【讨论】:

  • 这会破坏任何空格上的 queries.txt,您必须使用仅使用换行符作为空格的语言环境 qfile.imbue() 才能为 OP 工作。跨度>
  • True,并且接受的答案具有相同的限制。在我们的特殊情况下,代码应该可以工作,因为 OP 声明他的输入文件的格式是“每一行包含一个单词”。我已将此信息添加到答案中。
猜你喜欢
  • 1970-01-01
  • 2020-08-19
  • 1970-01-01
  • 2014-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-11
相关资源
最近更新 更多