Skip to main content
GameDev.net gamedev.net
🔒 Locked

[c++] ostram method

Started by Nanook Mar 20, 2009 at 11:14 PM 5 replies 1.4k views
Original Post
Nanook
Nanook
I get an error when I try to compile this.. I know its something to do about the const strLst object.. but I dont get why, cause the member functions called arent realy changing anything in the object?

#include "stringl.h"

void StringList::push_back(const string &str)
{
    list.push_back(str);
}

string StringList::getString(unsigned i)
{
    return (list);
}

void StringList::addStrTokenz(const string &str,const string &delim)
{
    //skips any delimiters at start of string(sets startPos to start of the first single word string)
    string::size_type startPos = str.find_first_not_of(delim, 0);
    //finding first delimiter(sets endPos to end of the first single word string)
    string::size_type endPos = str.find_first_of(delim, startPos);

    //checks if any of the find_ algorithms failed
    while(string::npos != endPos && string::npos != startPos)
    {
        //putting string at the end of the list vector
        list.push_back(str.substr(startPos, endPos - startPos));
        //skipping consecutive delimiters (sets startPos to the start of the next single word string)
        startPos = str.find_first_not_of(delim, endPos);
        //finding the next delimiter (sets endPos to the end of the next single word string )
        endPos = str.find_first_of(delim, startPos);
    }
}

StringList StringList::strOfSizeBelow(StringList &strLst, const unsigned size)
{
    StringList returnList;
    string tmpStr;
    for(unsigned i = 0; i < strLst.size(); i++)
    {
        tmpStr = strLst.getString(i);
        if(tmpStr.size() < size)
            returnList.push_back(tmpStr);
    }

    return returnList;
}

StringList StringList::noDuplicate(StringList &strLst)
{
    StringList returnList;
    string tmpStr;
    for(unsigned i = 0; i < strLst.size(); i++)
    {
        tmpStr = strLst.getString(i);
        if(!returnList.find(tmpStr))
            returnList.push_back(tmpStr);
    }

    return returnList;
}

bool StringList::find(string &str)
{
    bool flag = false;
    string tmpStr;
    for(unsigned i = 0; i < list.size(); i++)
    {
        tmpStr = list;
        if(str == tmpStr)
            flag = true;
    }

    return flag;
}

float StringList::averageLength()
{
    unsigned sum = 0;
    string tmpStr;
    for(unsigned i = 0; i < list.size(); i++)
    {
        tmpStr = list;
        sum += tmpStr.size();
    }

    return (float)sum / size();
}


ostream & operator <<( ostream & os,const StringList & strLst )
{
    unsigned count = 1;
    for(unsigned i = 0; i < strLst.size(); i++)
    {
        if (count == 1)
        {
            count++;
            os << strLst.getString(i);
        }
        else
        {
            count = 1;
            os << strLst.getString(i) << '\n';
        }
    }

    return os;
}


J:\ict209\assignment1\STRINGL.CPP||In function `std::ostream& operator<<(std::ostream&, const StringList&)':|
J:\ict209\assignment1\STRINGL.CPP|91|error: passing `const StringList' as `this' argument of `unsigned int StringList::size()' discards qualifiers|
J:\ict209\assignment1\STRINGL.CPP|96|error: passing `const StringList' as `this' argument of `std::string StringList::getString(unsigned int)' discards qualifiers|
J:\ict209\assignment1\STRINGL.CPP|101|error: passing `const StringList' as `this' argument of `std::string StringList::getString(unsigned int)' discards qualifiers|
||=== Build finished: 3 errors, 0 warnings ===|


Nanook
Nanook
here's the .h file if needed..

#ifndef STRINGL_H#define STRINGL_H#include <string>#include <vector>#include <iostream>using namespace std;class StringList{public:    StringList(){};    StringList(string &str, string &delim) { addStrTokenz(str,delim); };    ~StringList(){};    void clear(){ list.clear(); };    void push_back(const string &str);    string getString(unsigned i);    void addStrTokenz(const string &str,const string &delim);    StringList strOfSizeBelow(StringList &strLst, const unsigned size);    StringList noDuplicate(StringList &strLst);    bool find(string &str);    float averageLength();    unsigned size(){ return (unsigned)list.size(); };    friend ostream & operator <<( ostream & os, const StringList & strLst );private:    unsigned outPerLine;    vector<string> list;};#endif
Mike.Popoloski
Mike.Popoloski
You may only call const member functions on a const object. You are right that your functions do not change anything in the object, but the compiler can't be sure since you haven't marked them as such. In C++, you can place the const keyword after the method declarations in the header file to denote that they do not modify the object, which will let you call them on a const parameter.

By the way, what compiler is this? Those error messages don't look like they came from Visual Studio.
Mike Popoloski | Journal | SlimDX
Nanook
Nanook
hum.. I tried to change to;

friend ostream & operator <<( ostream & os,StringList & strLst ) const;

but then it says;
J:\ict209\assignment1\stringl.h:28: error: non-member function std::ostream& operator<<(std::ostream&, StringList&)' cannot have const' method qualifier

also tried;
friend ostream & operator <<( ostream & os,const StringList & strLst ) const;

still an error..


The compiler is code::blocks
chairthrower
chairthrower
Follow what Mike said,

J:\ict209\assignment1\STRINGL.CPP|91|error: passing const StringList' as this' argument of `unsigned int StringList::size()' discards qualifiers|

To fix this you need to change the size implementation from,

unsigned size(){ return (unsigned)list.size(); };


to

unsigned size() const { return (unsigned)list.size(); };


likewise
string StringList::getString(unsigned i)
to
string StringList::getString(unsigned i) const.
for the other two errors.

In the ostream operator std::ostream& operator<<(std::ostream&, const StringList&), you have promised that the StringList instance will not be modifed due to the const modifier. However you are calling methods on it (size and getString) that do not indicate according to their method signature that they will conform.

Nanook
Nanook
aah.. ok.. got him wrong..
Zahlman
Zahlman
Some simplifications and other minor details: :)

#include "stringl.h"// Left as an exercise: find out what else has to be #included from the// standard library headers to make everything work. :)void StringList::push_back(const std::string& str){    list.push_back(str);}// This one should also be marked const.std::string StringList::getString(unsigned i) const{    return list; // parentheses are unnecessary here}// Helper functions that translate the string find algorithms to use// iterators instead (more convenient here).std::string::iterator find_first_of(const std::string& delimiters, std::string::iterator position, const std::string& in) {    std::string::size_type index = std::distance(in.begin(), position);    std::string::size_type result = in.find_first_of(delimiters, index);    if (result == std::string::npos) { return in.end(); }    std::advance(position, result - index);    return position;}std::string::iterator find_first_not_of(const std::string& delimiters, std::string::iterator position, const std::string& in) {    std::string::size_type index = std::distance(in.begin(), position);    std::string::size_type result = in.find_first_not_of(delimiters, index);    if (result == std::string::npos) { return in.end(); }    std::advance(position, result - index);    return position;}// A hopefully clearer renaming of the function.// Referring to "string tokens" is redundant :)void StringList::addTokensFrom(const std::string& from, const std::string& delimiters){    // I don't think this really needs as much commenting as you had.     // But now I've added more comments to explain to you specifically why    // I've changed things in certain ways. :)    // The next non-empty token is found between 'start' and 'end' since    // we skip delimiters before 'start' (skipping empty tokens) and search    // for the next delimiter after that.    std::string::iterator begin = find_first_not_of(delimiters, from.begin(), from);    std::string::iterator end = find_first_of(delimiters, begin, from);    // You actually only want to check the begin position in your while    // condition. Otherwise you won't get to add the last word. This is why    // the iterator approach is more convenient: it's hard/ugly to account for    // npos in substring operations.    while (begin != from.end())    {        // Extract the word from the list and add it.        list.push_back(std::string(begin, end));        // Find the next word.        begin = find_first_not_of(delimiters, end, from);        end = find_first_of(delimiters, begin, from);    }}// Helper for filtering the list.struct notShorterThan {   int value;   notShorterThan(int value): value(value) {}   bool operator()(const std::string& s) { return s.size() >= value; }};// Again with the renaming. It's long, but...// Also, there's no reason to accept a StringList parameter here; you can have// it operate on 'this' instead. (If it was a static function before, you'll// need to change that.)StringList StringList::withOnlyStringsShorterThan(const unsigned size) const{    StringList result;    std::remove_copy_if(list.begin(), list.end(), result.list.begin(), notShorterThan(size));    return result;}// Similarly here. Note that there is a faster way to remove duplicates from// a list: if you sort it first, duplicates will always be adjacent, and the// standard library provides an algorithm that removes adjacent duplicates in// a single pass. Of course, sorting would change the object, so we make a// copy first, and then modify the copy in place.StringList StringList::withoutDuplicates() const{    StringList result(*this);    std::sort(result.list.begin(), result.list.end());    result.list.erase(std::unique(result.list.begin(), result.list.end()), result.list.end());    return result;}// Again, the standard library knows how to find things in general containers.// And don't call something "find" if it returns a boolean :)bool StringList::contains(std::string& toMatch){    return std::find(list.begin(), list.end(), toMatch) != list.end();}// At this point I'm mostly just showing off. ;)unsigned addLengthOf(unsigned accumulator, const std::string& s){    return accumulator + s.size();}float StringList::averageLength() const{    return float(std::accumulate(list.begin(), list.end(), 0, addLengthOf)) / list.size();}ostream& operator<<(ostream & os, const StringList& sl){    // A small simplification.    unsigned count = 0;    for(unsigned i = 0; i < strLst.size(); i++)    {        os << strLst.getString(i);        count++;        if (count == 2) {            os << '\n';            count = 0;        }    }    return os;}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.