C++ std::stringstream not accepting chars?

Discussion in 'Computer Programming, Emulation, and Game Modding' started by StackMasher, May 9, 2017.

  1. StackMasher
    OP

    StackMasher GBAtemp Regular

    Member
    2
    Nov 29, 2016
    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
     
  2. souler92
    This message by souler92 has been removed from public view by raulpica, May 9, 2017, Reason: Shitposting -rp.
    May 9, 2017
  3. evandixon

    evandixon PMD Researcher

    Member
    7
    May 29, 2009
    United States
    Try buffer.str().c_str()
     
  4. StackMasher
    OP

    StackMasher GBAtemp Regular

    Member
    2
    Nov 29, 2016
    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
     
  5. GerbilSoft

    GerbilSoft GBAtemp Addict

    Member
    11
    Mar 8, 2012
    United States
    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.
     
  6. sarkwalvein

    sarkwalvein There's hope for a Xenosaga port.

    Member
    17
    GBAtemp Patron
    sarkwalvein is a Patron of GBAtemp and is helping us stay independent!

    Our Patreon
    Jun 29, 2007
    Germany
    Niedersachsen
    WARNING!!!
    strcpy syntax is strcpy(destination, source)
     
  7. StackMasher
    OP

    StackMasher GBAtemp Regular

    Member
    2
    Nov 29, 2016
    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?

    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, May 9, 2017
  8. GerbilSoft

    GerbilSoft GBAtemp Addict

    Member
    11
    Mar 8, 2012
    United States
    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, May 9, 2017
    StackMasher likes this.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice