2

I'm coding an assignment where, basically, I have a client and server communicating. For this, I'm using a stringstream in the server side to process the requests (that come in the form of strings) and help build a string response. The server side holds an object (FileManager) that contains several MultimediaFile objects, each with information about themselves. This information can be printed through a method, of which one of the parameters is an ostream&.

To get the request from the client, the stringstream works just fine, but when I pass it to the method, for some reason it doesn't read the content (whereas if I pass std::cout it works just fine). I'm thinking it has something to do with the way stringstream uses the << operator to read information, but I'm unsure how to correct this.

I know I could simply store the information I need about the object in a string or something like that (instead of using ostream&), but the professor wants the method to print directly to the passed ostream, and not return a string.

Here's the code:

bool processRequest(TCPServer::Cnx& cnx, const string& request, string& response)
{
bool changeData = false;
if (request == "delMedias" || request == "delGroups") changeData = true;

TCPServer::Lock lock(cnx, changeData);

cerr << "request: '" << request << "'" << endl;
string operation = "";
string filename = "";
stringstream iss;

iss.str(request); //next few lines get request info, works just fine!

if (iss.rdbuf()->in_avail() != 0)
    iss >> operation;
if (iss.rdbuf()->in_avail() != 0)
    iss.get();
if (iss.rdbuf()->in_avail() != 0)
    getline(iss, filename);
iss.str("");


if (operation.size() == 0 || filename.size() == 0) return false;

response = "";

if (operation.compare("print") == 0)
{
        filem.showFile(filename, iss); //Problem here!!!!
        if (iss.rdbuf()->in_avail() != 0) //iss is always empty
        {
            response = iss.str();
            response = "Print info: " + response;
        }
        else
            response = "No info received!";
}
else if (operation.compare("play") == 0)
{
        filem.playFile(filename);
        response = "File played!";
}
else
    response = "Operation not valid";

cerr << response << endl;

return true;
}

TCPServer is a class provided by the professor to make things easier, but basically the client sends a string request and, at the end of this function, receives a string response from the server. filem is the FileManager class object, and here's the code for the showFile method:

void FileManager::showFile(string name, ostream& s)
{
    if (mfiles.find(name) != mfiles.end())
        mfiles[name]->printFile(s);
}

mfiles is a map of string to MultimediaFile* (specifically std::shared_ptr of MultimediaFile, but anyway). Basically, this code checks if there is a file named name, and if so, calls the method printFile(s) where s here would be the stringstream. Here's the method's code:

void MultimediaFile::printFile(ostream& s) const
{
    s << "File name: " << name << "\tFilepath: " << filepath << "\n";
}

name and filepath are instance variables of the MultimediaFile class. So, yeah, here I was expecting my stringstream to receive this information, which would then be used to build the response string in the main part of the code, just after the method call. That's not what happens however, and the stringstream is always empty (and since this works with std::cout, then the problem is not the data in the MultimediaFile object).

Again, I would say stringstream behaves differently than cout when getting data through the << operator, but I couldn't find any information that would help me in this case... Does anybody have an idea?

If there's any other information you need please let me know. And thanks in advance!

Berne
  • 793
  • 1
  • 7
  • 8
  • Just as a side note: Why do you use `operation.compare("print") == 0` instead of `operation == "print"`? – Nobody moving away from SE Feb 17 '16 at 12:19
  • I don't think that it should behave differently and cannot reproduce such a problem. Are you sure that the code paths are the same? Does the `if` in `showFile` decide differently between the `cout` and the `stringstream` variant? – Nobody moving away from SE Feb 17 '16 at 12:51
  • Yeah, the paths are the same. I tried using gdb, and it goes straight to that bit of code, so it should be the same, right? – Berne Feb 17 '16 at 12:58
  • Also, for the compare, I admit I don't remember why, haha. I think I was getting some kind of warning when using ==. I'd try it again now to check, but unfortunately I'm in class, so I'll have to give you a better answer later. – Berne Feb 17 '16 at 13:01
  • `and it goes straight to that bit of code` Which bit? You should try to give code that reproduces the problem. Given the current information I (and probably others as well) cannot recreate it. – Nobody moving away from SE Feb 17 '16 at 13:08
  • I meant that both cout and stringstream make a call to the same method, they execute exactly the same lines. But I'll provide something reproducible as soon as possible, thanks! – Berne Feb 17 '16 at 13:32
  • Found a solution (which creates some new questions, but anyway, just made a new post with the answer). Also, I really don't remember why I used compare, so I just changed it back, haha. And sorry for the delay, got busy with other stuff. – Berne Feb 20 '16 at 00:48

1 Answers1

0

So, apparently I found a solution.

To test some things, I tried creating a separate bit of code just to check how the method would behave with the stringstream. And... it worked. The only difference between my separate tests, and the problem itself was that, in my program, the stringstream was being used to get data from the request string before being passed to the method to get data from there. So, what I did is, I created a second stringstream that was passed to the method... and it worked.

Basically, this is what I changed (the rest of the code is the same as the original post):

response = "";
stringstream iss2; //create another stringstream

if (operation == "print")
{
        filem.showFile(filename, iss2); //use it instead of the first one
        if (iss2.rdbuf()->in_avail() != 0)
        {
            response = iss2.str();
            response = "Print info: " + response;
        }
        else
            response = "No info received!";
}

I have no idea why the first stringstream doesn't work; maybe one of the methods I used to get the request information (str(), get(), getline() or the >> operator) change the state of the stringstream so that it doesn't accept new information? I don't know, just random thoughts.

But anyway, this works, so I'm happy for now...

P.S.: I also changed the operation.compare("print") to operation == "print". I couldn't remember the reason I used compare, and I got no warnings during compilation like I thought I had, so, yeah...

Berne
  • 793
  • 1
  • 7
  • 8