为什么两次使用ifstream对象会导致错误

why using a ifstream object twice causes error?

本文关键字:对象 ifstream 错误 两次 为什么      更新时间:2023-10-16

我想输出一个单词在文本中出现的次数,并输出包含该单词的行,但是当我输出vector[*beg]时,我发现向量为空!

我认为问题在于使用ifstream &ifs两次:

auto wordMap=setMap(ifs);
std::vector<std::string> vvector = read_to_vector(ifs);

如果我交换这两个语句,它会立即崩溃

我想知道问题在哪里以及如何解决。

#include <iostream>
#include<vector>
#include <fstream>
#include <string>
#include <set>
#include <map>
#include <sstream>
#include <memory>
std::vector<std::string> read_to_vector(std::ifstream &ifs)
{
    std::string lines;
    std::vector<std::string> sentences;
    while (std::getline(ifs, lines))
    {
        sentences.push_back(lines);
    }
    return sentences;
}

std::map<std::string,std::set<size_t>> setMap(std::ifstream &ifs)
{
    std::vector<std::string> word_vector = read_to_vector(ifs);
    std::string lines, words;
    std::map < std::string, std::set<size_t> > word_map;
    for (size_t i = 0; i < word_vector.size(); i++)
    {
        //i is the current line_num
        std::istringstream stream(word_vector[i]);
        while (stream >> words)
        {
            word_map[words].insert(i);
        }
    }
    return word_map;
}
void print(std::ifstream &ifs)
{
    auto wordMap=setMap(ifs);
    std::vector<std::string> vvector = read_to_vector(ifs);
    std::string search;
    std::cout << "please input the word that you wanna search" << "n";
    std::cin >> search;
    auto findw = wordMap.find(search);
    if (findw != wordMap.cend())
        std::cout << search << " occurs " << findw->second.size() 
                  << " times : " << std::endl;
    std::set<size_t> lineNum = findw->second;
    //it is a set
    auto beg = lineNum.begin();
    while (beg != lineNum.end())
    {
        std::cout << *beg;
        //std::cout<<vvector[*beg];
        beg++;
    }   
    for (auto c : vvector)
        std::cout << c << std::endl;
    if (vvector.empty())
        std::cout << "vector is empty!";
    //WTF!!! vector is empty!!!
}
int main()
{
    std::ifstream ifs;
    ifs.open("text.txt",std::ios::in);
    print(ifs);
    ifs.close();
}

当您第一次调用read_to_vector时(在setMap中),它到达文件的末尾,因此下次调用它时(在print中),vector将为空。在读取read_to_vector中的行之前重置光标。改为:

std::vector<std::string> read_to_vector(std::ifstream &ifs)
{
   ifs.seekg (0, ifs.beg);//add this
   std::string lines;
   std::vector<std::string> sentences;
   while (std::getline(ifs, lines))
   {
      sentences.push_back(lines);
   }
   return sentences;
}

我认为最好读取一次文件,然后传递向量:

std::map<std::string,std::set<size_t>> setMap(std::vector<std::string> word_vector )
{
   //std::vector<std::string> word_vector = read_to_vector(ifs);
   std::string lines, words;
   std::map < std::string, std::set<size_t> > word_map;
   //some code
}

然后

void print(std::ifstream &ifs)
{
    std::vector<std::string> vvector = read_to_vector(ifs);
    auto wordMap=setMap(vvector);
    // some code
}