C++ std::stringstream not accepting chars?

  • Thread starter Thread starter StackMasher
  • Start date Start date
  • Views Views 1,380
  • Replies Replies 6

StackMasher

Well-Known Member
Member
Joined
Nov 29, 2016
Messages
136
Reaction score
65
Trophies
0
Age
23
XP
410
Country
Here's my function:
Code:
const char* getToken(std::ifstream& input) {
    std::stringstream buffer;
    char curChar;
    bool inString = false;
   
    //Get rid of any leading whitespace
    while (input.peek() == ' ') {
        input >> curChar;
    }
   
    //Extract the token
    while (true) {
        input >> curChar;
       
        if (!inString && ( curChar == ' ' || curChar == '\n' || input.eof() == true )) {
            break;
        }
        else if (curChar == '"') {
            inString = !inString;
        }
       
        buffer << curChar;
    }
   
    char* toReturn = new char[buffer.width() + 1];
    buffer.seekg(0,std::ios::beg);
    for (int i{}; i<buffer.width(); ++i) {
        buffer >> toReturn[i];
    }
    toReturn[buffer.width()] = '\0';
    return toReturn;
}
the string this function returns is empty, and buffer returns 0 as it's width
 
Try buffer.str().c_str()
nope, same results
Code:
char* toReturn = new char[strlen(buffer.str().c_str()) + 1];
strcpy((char*)buffer.str().c_str(), toReturn);
return toReturn;
I've also tried directly returning buffer.str().c_str(), and that doesn't work either
 
You may want to change the return type to std::string and return buffer.str().

stringstream::width() doesn't do what you think it does. That returns the width parameter for the next added object, i.e. for formatting. It doesn't return the length of the string.
 
nope, same results
Code:
char* toReturn = new char[strlen(buffer.str().c_str()) + 1];
strcpy((char*)buffer.str().c_str(), toReturn);
return toReturn;
I've also tried directly returning buffer.str().c_str(), and that doesn't work either
WARNING!!!
strcpy syntax is strcpy(destination, source)
 
OK i've changed the strcpy to a custom for loop and it works now
Code:
int strLen = strlen(buffer.str().c_str()) + 1;
char* toReturn = new char[strLen];
for (int i{}; i<strLen; ++i) {
    toReturn[i] = buffer.str().c_str()[i];
}
Just out of curiosity, why can't you save or pass the pointer that buffer.str().c_str() returns?

WARNING!!!
strcpy syntax is strcpy(destination, source)
I remember it with the GAS assembly syntax, first src then dest, though I've probably got that wrong because I haven't done assembly in a while
 
Last edited by StackMasher,
Just out of curiosity, why does buffer.str().c_str() act like this (you can't pass it's return value, or save it to a pointer)?
The original strcpy might have worked; you just had the parameters reversed.

If you were trying to return buffer.str().c_str(), that's undefined. buffer is a local variable in the function. c_str() returns a pointer to a temporary string created by the stringstream, so you end up returning a pointer to a temporary object, which gets deleted immediately after returning. The pointer ends up pointing to freed memory.

Here's what you can and can't do in this case.

Yes:
Code:
{
    string str = buffer.str();
    const char *c_str = str.c_str();
    // do stuff with c_str within this function, e.g.:
    cout << "c_str == " << c_str << endl;
}
You first save the string object to a local variable, then take the c_str() pointer from the str. This works within the same function as long as the original string is in scope. You cannot return c_str, because that will result in a dangling pointer.

No:
Code:
{
    const char *c_str = buffer.str().c_str();
    // BAD! This will result in undefined behavior!
    cout << "c_str might be: " << c_str << endl;
}
buffer.str() returns a temporary string object. This then calls c_str() to get the C string pointer, but after that's done, the temporary string object is deleted. This results in c_str pointing to nowhere.

No:
Code:
{
    string str = buffer.str();
    const char *c_str = str.c_str();
    return c_str; // BAD: str is deleted after returning
}
str is deleted after returning, so the returned c_str pointer is pointing nowhere.
 
Last edited by GerbilSoft,
  • Like
Reactions: StackMasher

Site & Scene News

Popular threads in this forum