0

I am trying to overload operator>> for a custom PriorityQueue class I've been writing, code is below:

/**
 * @brief Overloaded stream extraction operator.
 *
 * Bitshift operator>>, i.e. extraction operator. Used to write data from an input stream
 * into a targeted priority queue instance. The data is written into the queue in the format,
 *
 * \verbatim
 [item1] + "\t" + [priority1] + "\n"
 [item2] + "\t" + [priority2] + "\n"
 ...
 * \endverbatim
 *
 * @todo Implement functionality for any generic Type and PriorityType.
 * @warning Only works for primitives as template types currently!
 * @param inStream Reference to input stream
 * @param targetQueue Instance of priority queue to manipulate with extraction stream
 * @return Reference to input stream containing target queue data
 */
template<typename Type, typename PriorityType> std::istream& operator>>(std::istream& inStream, PriorityQueue<Type, PriorityType>& targetQueue) {

    // vector container for input storage
    std::vector< std::pair<Type, PriorityType> > pairVec;
    // cache to store line input from stream
    std::string input;

    std::getline(inStream, input);

    if (typeid(inStream) == typeid(std::ifstream)) {
        inStream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }

    // loop until empty line
    while (!input.empty()) {
        unsigned int first = 0;
        // loop over input cache
        for (unsigned int i = 0; i < input.size(); ++i) {
            // if char at index i of cache is a tab, break from loop
            if (input.at(i) == '\t')
                break;
            ++first;
        }
        std::string data_str = input.substr(0, first);
        // convert from std::string to reqd Type
        Type data = atoi(data_str.c_str());

        std::string priority_str = input.substr(first);
        // convert from std::string to reqd PriorityType
        PriorityType priority = atof(priority_str.c_str());

        pairVec.push_back(std::make_pair(data, priority));

        // get line from input stream and store in input string
        std::getline(inStream, input);
    }

    // enqueue pairVec container into targetQueue
    //targetQueue.enqueueWithPriority(pairVec);

    return inStream;

}

This currently works for stdin or std::cin input however it doesn't work for fstream input - the very first getline always reads an empty line from the input such that the while loop never gets triggered, and I can't seem to skip it (I tried with inStream.ignore() as you can see above but this doesn't work.

Edit:

Currently I just want to get it working for file input ignoring the fact it only works for int data type and double priority type right now - these aren't relevant (and neither is the actual manipulation of the targetQueue object itself).

For the moment I'm just concerned with resolving the blank-line issue when trying to stream through file-input.

Example file to pass:

3    5.6
2    6.3
1    56.7
12   45.1

where the numbers on each line are \t separated.

Example testing:

#include "PriorityQueue.h"
#include <sstream>
#include <iostream>
#include <fstream>

int main(void) {

    // create pq of MAX binary heap type
    PriorityQueue<int, double> pq(MAX);


    std::ifstream file("test.txt");

    file >> pq;

    std::cout << pq;

}

where "test.txt" is the in the format of the example file above.

Edit: Simpler Example

Code:

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

class Example {

public:

    Example() {}

    size_t getSize() const { return vec.size(); }

    friend std::istream& operator>>(std::istream& is, Example& example);

private:

    std::vector< std::pair<int, double> > vec;

};

std::istream& operator>>(std::istream& is, Example& example) {

    int x;
    double y;
    while (is >> x >> y) {
        std::cout << "in-loop" << std::endl;
        example.vec.push_back(std::make_pair(x, y));
    }
    return is;
}

int main(void) {

    Example example;

    std::ifstream file("test.txt");

    file >> example;

    file.close();

    std::cout << example.getSize() << std::endl;

    return 0;

}
sjrowlinson
  • 3,297
  • 1
  • 18
  • 35
  • Please provide an [mcve]. What are example file contents you might need to read? – Barry Mar 14 '16 at 20:36
  • @Barry Indeed, I have added an edit to the OP now - to re-iterate the actual manipulation of the queue is not important here, I'd just like to know how to resolve the blank line issue when reading from a file input stream. – sjrowlinson Mar 14 '16 at 20:40
  • That's part the **minimal** part. Just remove all the irrelevant stuff to the code, and show an example file that fails to do what you want. – Barry Mar 14 '16 at 20:44
  • how about adding an extra `getline` before the while loop into some temp string and then do the actual `getline` for `input` – Thesane Mar 14 '16 at 21:02

1 Answers1

1

The operator is already overloaded -- and shall be overloaded -- for many types. Let those functions do their work:

template<typename Type, typename PriorityType>
std::istream& operator>>(std::istream& inStream, PriorityQueue<Type, PriorityType>& targetQueue)
{
  std::vector< std::pair<Type, PriorityType> > pairVec;
  Type data;
  PriorityType priority;

  while(inStream >> data >> priority)
    pairVec.push_back(std::make_pair(data, priority));

  targetQueue.enqueueWithPriority(pairVec);

  return inStream;
}
Beta
  • 96,650
  • 16
  • 149
  • 150
  • Works well for `stdin` and `std::cin` however this still doesn't seem to work for file streaming :/ – sjrowlinson Mar 14 '16 at 21:14
  • @ArchbishopOfBanterbury: Really? I tested it with file streaming and it worked perfectly. If you post a [minimal complete example](http://stackoverflow.com/help/mcve), maybe we can figure it out. – Beta Mar 14 '16 at 21:16
  • Maybe I'm being an idiot and forgetting how to properly file stream, but I'll the test code from my `main` to the OP now – sjrowlinson Mar 14 '16 at 21:19
  • @ArchbishopOfBanterbury: That still isn't a complete example. And you're sure nothing goes into `pairVec`? – Beta Mar 14 '16 at 21:34
  • If I was to post a complete example (including all necessary parts of the PriorityQueue) then it would take up far too much room. It is superfluous in this case anyway as any object type could be used in place of the PQ to achieve the same result - upon testing with file input, it seems that the while loop is not entered at all (never gets past condition to enter the loop) – sjrowlinson Mar 14 '16 at 21:39
  • @ArchbishopOfBanterbury: If that's true, then post an example that shows the result with a simpler type-- that's the "minimal" part of "minimal complete example". Would it help if I posted a complete example in which control *does* enter the loop? – Beta Mar 14 '16 at 21:50
  • I'll add a simpler (complete) example in the OP, shouldn't take too long – sjrowlinson Mar 14 '16 at 21:56
  • Simpler example added - when running in my case using the `.txt` file shown in OP, the while loop is never entered. – sjrowlinson Mar 14 '16 at 22:10
  • 1
    @ArchbishopOfBanterbury: Works for me: *in-loopin-loopin-loopin-loop4* Is this a minimal example? That is, if you simplify it any further, does the error vanish and the file I/O start working? – Beta Mar 14 '16 at 22:15
  • Well this is most odd, even just writing a small amount of code to compute the number of lines in the text file yields zero for me - something weird must be going on. – sjrowlinson Mar 14 '16 at 22:20