Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Type of elements of std::string

3 views
Skip to first unread message

Leslaw Bieniasz

unread,
Jan 25, 2010, 4:51:53 AM1/25/10
to

Hi,

What is actually the type of elements of std::string?

I am trying to read the elements from a stream, in the following
way:

std::string str = "";
int c;

// Read string size
int n;
is >> n;

// Read string
for(int i=0; i<n; i++)
{
c = is.get();
str += c;
}

This seems to work, but the compiler (C++ Builder 6.0)
issues a warning at
c = is.get();
The warning is: Conversion may lose significant digits

On the other hand, if I switch to "char" instead of "int"
it seems that the code does not work.

How to write the code that does exactly the same thing
but without the warning?

Leslaw

Richard Herring

unread,
Jan 25, 2010, 5:25:21 AM1/25/10
to
In message <Pine.GHP.4.64.10...@kinga.cyf-kr.edu.pl>,
Leslaw Bieniasz <nbbi...@cyf-kr.edu.pl> writes

>
>Hi,
>
>What is actually the type of elements of std::string?

char.

>
>I am trying to read the elements from a stream, in the following
>way:
>
>std::string str = "";
>int c;
>
>// Read string size
>int n;
>is >> n;
>
>// Read string
>for(int i=0; i<n; i++)
> {
> c = is.get();
> str += c;
> }
>
>This seems to work, but the compiler (C++ Builder 6.0)
>issues a warning at
>c = is.get();
>The warning is: Conversion may lose significant digits

Are you sure the warning isn't at the following line? std::string
doesn't have an operator+= which takes an int, and int to char is a
conversion that might lose significance.

>
>On the other hand, if I switch to "char" instead of "int"
>it seems that the code does not work.

What do you mean by "does not work"?


>
>How to write the code that does exactly the same thing
>but without the warning?
>

Understand how istream::get() reports errors.

--
Richard Herring

Leslaw Bieniasz

unread,
Jan 25, 2010, 6:29:31 AM1/25/10
to
On Mon, 25 Jan 2010, Richard Herring wrote:

> Are you sure the warning isn't at the following line? std::string doesn't
> have an operator+= which takes an int, and int to char is a conversion that
> might lose significance.

Well, I understand that, but the essential question is how to read
the elements of std::string correctly, if std::string contains char,
whereas get() returns int. This looks like some sort of incompatibility.


>>
> Understand how istream::get() reports errors.

Surely I am not asking how to cheat the compiler to not to get messages,
but how to do things correctly.

Leslaw

Richard Herring

unread,
Jan 25, 2010, 6:57:56 AM1/25/10
to
In message <Pine.GHP.4.64.10...@kinga.cyf-kr.edu.pl>,
Leslaw Bieniasz <nbbi...@cyf-kr.edu.pl> writes
>On Mon, 25 Jan 2010, Richard Herring wrote:
>
>> Are you sure the warning isn't at the following line? std::string
>>doesn't have an operator+= which takes an int, and int to char is a
>>conversion that might lose significance.
>
>Well, I understand that, but the essential question is how to read
>the elements of std::string correctly, if std::string contains char,
>whereas get() returns int. This looks like some sort of incompatibility.

Do you understand *why* get() returns int, and what subset of possible
int values it can return? That's the point of my question below:

>>>
>> Understand how istream::get() reports errors.
>
>Surely I am not asking how to cheat the compiler to not to get messages,
>but how to do things correctly.
>

Good. Then you should be reading an int from get(), separating out the
values that represent characters from those which don't, appending the
chars to the string and doing something else with the non-chars.

--
Richard Herring

Leslaw Bieniasz

unread,
Jan 26, 2010, 6:54:41 AM1/26/10
to
On Mon, 25 Jan 2010, Richard Herring wrote:

> Do you understand *why* get() returns int, and what subset of possible int
> values it can return? That's the point of my question below:

Yes, that's the point. I do not understand why get() returns int. If
get() is supposed to read successive bytes, then I would expect it
to return char. What are the cases when it returns int?
Is this EOF, or what else?

> Good. Then you should be reading an int from get(), separating out the values
> that represent characters from those which don't, appending the chars to the
> string and doing something else with the non-chars.

Do you mean casting from int to char? This removes the warning message
and from my brief test seems to work OK, but how can I be sure if
it always works correctly?

Leslaw

Richard Herring

unread,
Jan 26, 2010, 8:33:47 AM1/26/10
to
In message <Pine.GHP.4.64.10...@kinga.cyf-kr.edu.pl>,
Leslaw Bieniasz <nbbi...@cyf-kr.edu.pl> writes
>On Mon, 25 Jan 2010, Richard Herring wrote:
>
>> Do you understand *why* get() returns int, and what subset of
>>possible int values it can return? That's the point of my question
>>below:
>
>Yes, that's the point. I do not understand why get() returns int. If
>get() is supposed to read successive bytes, then I would expect it
>to return char. What are the cases when it returns int?
>Is this EOF, or what else?

EOF. Read the documentation.


>
>> Good. Then you should be reading an int from get(), separating out
>>the values that represent characters from those which don't,
>>appending the chars to the string and doing something else with the
>>non-chars.
>
>Do you mean casting from int to char?

Or any other form of conversion.

>This removes the warning message
>and from my brief test seems to work OK, but how can I be sure if
>it always works correctly?

By only converting when you know that the value is in the range valid
for char.

--
Richard Herring

Jerry Coffin

unread,
Jan 26, 2010, 9:52:10 AM1/26/10
to
In article <Pine.GHP.4.64.10...@kinga.cyf-kr.edu.pl>,
nbbi...@cyf-kr.edu.pl says...

>
> Hi,
>
> What is actually the type of elements of std::string?

char. Specifically, the definition of std::string looks like:
typedef basic_string<char> string;



> I am trying to read the elements from a stream, in the following
> way:
>
> std::string str = "";
> int c;
>
> // Read string size
> int n;
> is >> n;
>
> // Read string
> for(int i=0; i<n; i++)
> {
> c = is.get();
> str += c;
> }

Hmm...I think I'd do this more like:

int n;
is >> n;

std::string str(n, ' ');
is.read(&str[0], n);

This should eliminate the warning(s), and if there's a difference in
efficiency, I'd guess it's more likely to favor this version than the
other. In theory, this isn't entirely portable -- the current
standard doesn't guarantee that std::string will use contiguous
storage for the characters. In reality, current implementations do
use contiguous storage, and the next version of the standard will
require it, so there's not really much chance of a new implementation
that uses non-contiguous storage.

--
Later,
Jerry.

James Kanze

unread,
Jan 26, 2010, 8:18:11 PM1/26/10
to
On Jan 26, 2:52 pm, Jerry Coffin <jerryvcof...@yahoo.com> wrote:
> In article <Pine.GHP.4.64.1001251045190.17...@kinga.cyf-kr.edu.pl>,
> nbbie...@cyf-kr.edu.pl says...

> int n;
> is >> n;

What happens if there aren't n characters left to read? (And in
fact, I don't know. I practically never use istream::read, and
I don't have any documentation handy to check. But it's
obviously a case which has to be considered.)

More generally, considering the first algorithm: the
no-argument form of istream::get returns an int in order to
return out of band data, e.g. EOF. Once that data has been
tested for and excluded, the resulting value must be converted
to a char. Formally, a rather complex operation, since the
resulting value is in the range 0...UCHAR_MAX, which might not
fit into a char (and if the results don't fit, the behavior is
implementation defined, and might result in a signal).
Practically, implementations which use signed plain char will
always ensure that this works, given that it is such a standard
idiom (in C, at least). But if you really want to avoid it,
something like:

char ch;

// ...
if ( input.get( ch ) ) {
// succeeded, you can safely use ch...
} else {
// error or end of file, the contents of
// ch are unchanged.
}

--
James Kanze

Jerry Coffin

unread,
Jan 27, 2010, 9:10:39 AM1/27/10
to
In article <fe150af1-3499-46e2-b9ac-efa490368d42
@m25g2000yqc.googlegroups.com>, james...@gmail.com says...

[ ... ]

> > std::string str(n, ' ');
> > is.read(&str[0], n);

[ ... ]

> What happens if there aren't n characters left to read? (And in
> fact, I don't know. I practically never use istream::read, and
> I don't have any documentation handy to check. But it's
> obviously a case which has to be considered.)

It returns the stream, which will have its failbit set if the read
failed (i.e., if it couldn't read as many characters as requested).
Given that the file specified the length, chances are pretty good
that the proper reaction is to log the error and abort, but depending
on what data it's trying to read, it might be able to live with
partial input, request the input from another source, or who knows
what.

Unlike fread, however, istream::read does NOT indicate how many
characters were read, so if (for example) trailing blanks in the
input were significant, and you really needed to distinguish them
from the string's initial value, this method probably wouldn't work
well (unless you could initialize the string to some other value you
knew wouldn't come from the input).

--
Later,
Jerry.

Leigh Johnston

unread,
Jan 27, 2010, 11:22:48 AM1/27/10
to

> Unlike fread, however, istream::read does NOT indicate how many
> characters were read, so if (for example) trailing blanks in the
> input were significant, and you really needed to distinguish them
> from the string's initial value, this method probably wouldn't work
> well (unless you could initialize the string to some other value you
> knew wouldn't come from the input).
>

istream::gcount() will tell you how many characters were read by the last
call to istream::read

/Leigh

Leigh Johnston

unread,
Jan 27, 2010, 11:41:04 AM1/27/10
to

> More generally, considering the first algorithm: the
> no-argument form of istream::get returns an int in order to
> return out of band data, e.g. EOF. Once that data has been
> tested for and excluded, the resulting value must be converted
> to a char. Formally, a rather complex operation, since the
> resulting value is in the range 0...UCHAR_MAX, which might not
> fit into a char (and if the results don't fit, the behavior is
> implementation defined, and might result in a signal).
> Practically, implementations which use signed plain char will
> always ensure that this works, given that it is such a standard
> idiom (in C, at least). But if you really want to avoid it,
> something like:
>

Your insistence on describing the behaviour of rare corner case
implementations is unhelpful as it confuses the issue, the fact that char ch
= (unsigned char) foo; is implementation defined behaviour is not
justification for eschewing the use of istream::read(). Please rejoin the
real world.

/Leigh

James Kanze

unread,
Jan 27, 2010, 5:43:30 PM1/27/10
to

I never said it was (and I do use istream::read and
istream::write). Still, a competent programmer will want to
understand what he's doing, and what the restrictions and the
trade-offs are.

> Please rejoin the real world.

In the real world, not every machine is a PC.

--
James Kanze

Jerry Coffin

unread,
Jan 28, 2010, 1:07:52 AM1/28/10
to
In article <5fCdnegTIMLC9f3W...@giganews.com>,
le...@i42.co.uk says...

[ ... ]

> istream::gcount() will tell you how many characters were read by
> the last call to istream::read

Ah, quite right. I should have thought of that...

--
Later,
Jerry.

0 new messages