Strange error with iterators

M

Michael Coley

Hi, I've wrote this function which should add a comma for every 3
digits in a number (so that it looks something like 5,000).

This is my function:
std::string formatNumber(int number)
{
// Convert the int to a string.
std::string numString = boost::lexical_cast<std::string>(number);

std::string::const_reverse_iterator i = numString.rbegin(), end =
numString.rend();
for (int j = 0; i != end; ++i, ++j)
{
// Add a comma every three places.
if (j < 3)
{
// ERROR HAPPENS ON THIS LINE BELOW.
i = numString.insert(i + 1, ',');
end = numString.rend();

j = 0;
}
}

return numString;
}

I get an error saying it cannot convert from reverse_iterator to
unsigned int. It looks to me as if it's trying to call the wrong
overloaded function, as I did a search on the method and I can indeed
pass an iterator and a char.

Can anybody tell me why this is failing?

Thanks in advance.
 
R

Richard Herring

Hi, I've wrote this function which should add a comma for every 3
digits in a number (so that it looks something like 5,000).

This is my function:
std::string formatNumber(int number)
{
// Convert the int to a string.
std::string numString = boost::lexical_cast<std::string>(number);

std::string::const_reverse_iterator i = numString.rbegin(), end =
numString.rend();
for (int j = 0; i != end; ++i, ++j)
{
// Add a comma every three places.
if (j < 3)
{
// ERROR HAPPENS ON THIS LINE BELOW.
i = numString.insert(i + 1, ',');
end = numString.rend();

j = 0;
}
}

return numString;
}

I get an error saying it cannot convert from reverse_iterator to
unsigned int. It looks to me as if it's trying to call the wrong
overloaded function, as I did a search on the method and I can indeed
pass an iterator and a char.

i+1 isn't an iterator, it's a const_reverse_iterator
 
V

Victor Bazarov

Michael said:
Hi, I've wrote this function which should add a comma for every 3
digits in a number (so that it looks something like 5,000).

This is my function:
std::string formatNumber(int number)
{
// Convert the int to a string.
std::string numString = boost::lexical_cast<std::string>(number);

std::string::const_reverse_iterator i = numString.rbegin(), end =
numString.rend();
for (int j = 0; i != end; ++i, ++j)
{
// Add a comma every three places.
if (j < 3)
{
// ERROR HAPPENS ON THIS LINE BELOW.
i = numString.insert(i + 1, ',');

Are you sure you can do +1 to the 'i'? Are you sure you can use the
*const* iterator for that? Just checking. Since your 'numString'
is not a constant object, why do you think you need a _const_ iterator
to work with it?
end = numString.rend();

j = 0;
}
}

return numString;
}

I get an error saying it cannot convert from reverse_iterator to
unsigned int. It looks to me as if it's trying to call the wrong
overloaded function, as I did a search on the method and I can indeed
pass an iterator and a char.

Can anybody tell me why this is failing?

Well, try to rewrite this using a non-const reverse iterator, or even
better, not using iterators at all. You know, you can just use
indices...

V
 
R

Richard Herring

Victor Bazarov said:
Are you sure you can do +1 to the 'i'? Are you sure you can use the
*const* iterator for that? Just checking.

No problem. The const describes what the iterator refers to, not the
iterator itself, and it models the random-access iterator concept, so
why not?

The real problem is elsewhere...
Since your 'numString'
is not a constant object, why do you think you need a _const_ iterator
to work with it?


Well, try to rewrite this using a non-const reverse iterator,

or better, a non-const non-reverse iterator :-/
or even
better, not using iterators at all. You know, you can just use
indices...

Indeed.
 
J

Joe Greer

I get an error saying it cannot convert from reverse_iterator to
unsigned int. It looks to me as if it's trying to call the wrong
overloaded function, as I did a search on the method and I can indeed
pass an iterator and a char.

Can anybody tell me why this is failing?

Because, while you can pass insert() an iterator and a character, you can't pass it a
reverse_iterator and a char.

joe
 
J

Jerry Coffin

Hi, I've wrote this function which should add a comma for every 3
digits in a number (so that it looks something like 5,000).

iostreams can already format numbers like that without your doing all
the work:

First you create a numpunct facet to tell it how you want the formatting
done:

#include <locale>

template <class T>
struct formatter : std::numpunct<T> {
protected:
T do_decimal_point() const { return T('.'); }
T do_thousands_sep() const { return T(','); }
std::basic_string<T> do_grouping() const {
return std::basic_string<T>("\3");
}
};

Then you create a locale using that facet, and imbue a stream with the
locale to get it to use it:

std::locale f(std::locale::classic(), new formatter<char>);
std::cout.imbue(f);

Then when you write numbers to that stream, they're formatted as you've
specified. If you really need to produce a string as the output, you can
imbue a stringstream with a locale as well.

Nicely enough, it's (usually) even easier to do the right thing, and
format the numbers the way the user expects:

std::locale local("");
std::cout.imbue(local);
std::cout << 123456789;

For me, this produces "123,456,789" -- but as (for example) a European
would typically configure their machine, it would produce "123.456.789"
instead, just as they expect.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top