从文本文件中读取一行并将字符串放入向量中?

30

我试图读取文本文件中的每一行,每一行都包含一个单词,并将这些单词放入向量中。我该如何做?

这是我的新代码:我认为它仍然有问题。

#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;

}

2
你对目前的代码有什么问题? - Mahesh
@Mahesh,这个*if(!myfile)*可能是第一个问题。 (对不起..我需要学习STL。) - Roman Byshko
@RomanB:这行代码没有任何问题。 - Puppy
@DeadMG 现在我明白了为什么运算符重载会受到如此多的批评。 - Roman Byshko
4个回答

40

最简单的形式:

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;
}

使用关键字 "using" 在 C++ 中是非法的!不要使用它。好了?好的。现在比较一下我写的和你写的,看看有什么区别。如果你还有问题,请回来。


我已经修复了我的帖子中的代码,现在我做错了什么?因为我需要处理两个不同的文本文件。顺便说一下,非常感谢您的帮助。 - user977154
@user977154,你不需要外部的while循环。在两种情况下都要删除它!另外,你确定你的向量中存在12行和20行吗? - FailedDev
是的,我确定我的测试文件中有超过20行已经填充。但我一直收到错误提示,说无法打开输出文件。 - user977154
1
等一下。我知道这是一个旧帖子,但这很危险。在C++中,关键字“using”有什么不合法的地方?使用与命名空间一起引入了该语言。 "using std :: cout"是完全有效的。“using std”是完全有效的,尽管是不良实践。 - gamers2000
1
@gamers2000 是在讽刺。 int * aPtr = NULL; *aPtr = 5; // 也是完全有效的,但应被视为非法... - FailedDev
@void.pointer 感谢您澄清这一点,在我指出之后。 - FailedDev

38

@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
1
太棒了,我成功了。非常感谢你。这绝对更加简单和清晰。 - user977154
@user977154 请参考上面的完整示例。 - Robᵩ
1
@user977154 我相信你完全不知道它是如何工作的。对吧? - FailedDev
8
如果您的文本行中有空格,则此解决方案将无效。这些空格会被视为行分隔符。 - void.pointer
1
@void.pointer - 那个条件违反了问题中所述的前提条件 - "每行只包含一个单词。"也许在这种情况下我的代码恰好符合OP想要的,也可能不是。 - Robᵩ

26

最简单的版本:

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

我省略了头文件和其他杂项。我的版本与FailedDev的版本几乎相同,但是我使用'for'循环将“line”的声明放在了循环中。这不仅仅是为了减少行数而是为了减小“line”的作用域——在for循环之后,“line”就消失了。所有变量都应该具有最小的作用域,因此这样做更好。for循环非常棒。


太好了。使用using namespace std;后代码更加简洁,不需要写std::。'ifs'的声明缺失,可以这样声明:ifstream ifs(textFilePath, ios::in); - Brent Faust
1
更少的if范围:for(auto [line, ifs] = std::make_tuple<std::string, std::ifstream>("", std::ifstream(log_filename)); std::getline(ifs, line);) lines.push_back(line); - mheyman

1

以下是C++11及以上版本的简短代码。向量直接从文件内容构建:

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

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

1
这会在任何空白字符处中断 queries.txt,您必须使用仅将换行符作为空格的区域设置(Locale),对 qfile.imbue() 进行处理以使其适用于 OP。 - mheyman
True,并且被接受的答案也有同样的限制。在我们这个特定的情况下,代码应该可以工作,因为OP声明他的输入文件格式是“每行包含一个单词”。我已经将这个信息添加到答案中。 - Alexei Khlebnikov

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