c++seekg

Cant understand how to use seekg tellg to achieve the following result


As part of a larger program, my task is to read each line of an input file and store the index offset to each line. Later given all the index offsets, I want to be able to go to that position in the file directly and print the line corresponding to that offset. Can someone help me in figuring out what I am doing incorrectly in the following code.

    #include <iostream>
    #include <sstream> 
    #include <vector>
    #include <iterator>
    #include <stdio.h>
    #include <string.h>    

    void create_index_info(ifstream& myFile, std::unordered_map<size_t, std::pair<std::streampos, size_t>>& map_index_start_end_pos)
    {
        size_t uiLength;
        size_t uiCount = 0;
        std::string line;

        while (getline(myFile, line))
        {        
            start_pos = myFile.tellg();
            uiLength = strlen(line.c_str());

            map_index_start_end_pos.emplace( uiCount, std::make_pair(start_pos, uiLength) );
            uiCount++;                        
        }
    }

    void print_index_info(ifstream& myFile, const std::unordered_map<size_t, std::pair<std::streampos, size_t>>& map_index_start_end_pos)
    {
        size_t uiLength;
        for(auto it = map_index_start_end_pos.begin(); it != map_index_start_end_pos.end(); it++)
        {
            auto res = it->second;

            myFile.clear();
            myFile.seekg(res.first, ios::beg);
            uiLength = res.second;

            char* buffer = (char*)malloc(uiLength * sizeof(char));
            myFile.read(buffer, uiLength);

            for(size_t uiCount = 0; uiCount < uiLength; uiCount++)
            {
                std::cout<< buffer[uiCount];
            }
            std::cout<<"\n";

            free(buffer);
            buffer = NULL;    
        }
    }

    int main()
    {
        std::unordered_map<size_t, std::pair<std::streampos, size_t>> map_index_start_end_pos;
        ifstream myFile("Filename.txt");
        create_index_info(myFile, map_index_start_end_pos);
        myFile.close();

        ifstream myFile1("Filename.txt");
        print_index_info(myFile1, map_index_start_end_pos);
        myFile1.close();
        return 0;
    }

The data in the input text file contains the following entries:

9 10 11

8 7 5

67 34 12 45 9

20

The ideal output for the code should be same as the input modulo upto ordering of the lines being printed (I am using an unordered map, so the output need not be printed in the same order as it was fed). However my code is outputting some garbage, mostly characters of the form \x00. Can someone please help me figure out what is wrong in my code.


Solution

  • You are probably looking for this:

    #include <iostream>
    #include <vector>
    #include <string>
    #include <fstream>
    
    std::istream& get_line_idx( std::istream& is, std::vector<std::streampos>& result )
    {
      for( std::streampos pos = is.tellg(); is.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ); pos = is.tellg() )
        result.push_back( pos );
      return is;
    }
    
    void print( std::istream& is, std::vector<std::streampos>& pos )
    {
      for( auto curpos : pos )
      {
        std::string line;
        is.seekg( curpos );
        std::getline( is, line );
        std::cout << line << std::endl;
      }
    }
    
    int main()
    {
      std::vector<std::streampos> result;
      {
        std::ifstream is { "c:\\temp\\test.txt" };
        if( !is )
          return -1;
        get_line_idx( is, result );
      }
    
      {
        std::ifstream is { "c:\\temp\\test.txt" };
        if( !is )
          return -2;
        print( is, result );
      }
    
      return 0;
    }