comparing string elements

M

MC felon

what's the best way to compare two string elements?

std::string cstr;
if ( cstr.at(3) == cstr.at(2)) //do something
or
std::string cstr;
if ( cstr[3] == cstr[2]) //do something

?
 
G

Gianni Mariani

MC said:
what's the best way to compare two string elements?

std::string cstr;
if ( cstr.at(3) == cstr.at(2)) //do something
or
std::string cstr;
if ( cstr[3] == cstr[2]) //do something

That depends.

Do you know that cstr has at least 4 chars ? Do you want it to throw an
exception if it does not ?

operator[] will not check for out of bounds access while at should.

I think for readability, operator[] is probably easier but it really
makes very little practical difference.
 
J

Jim Langston

MC said:
what's the best way to compare two string elements?

std::string cstr;
if ( cstr.at(3) == cstr.at(2)) //do something
or
std::string cstr;
if ( cstr[3] == cstr[2]) //do something

?

[] is a *little* faster, but should only be used when it is known that the
length of the string is greater than the index. If it is not sure, .at()
should be used.

I.E.

if ( cstr.size() < index )
{
if ( cstr[index] == cstr[index] // do something
}

Of course, that check for size() brings it's own overhead, so in that case
just use .at(). However, at lot of times at the beginning of a function I
will validate sizes and throw an error or return with an empty string. So
in my base I know the size indexes will fit, so then I will just use []

Realistically, I never use .at() because I always check the length of the
strings before I do operations on them. I would rather check on error
conditions in code rather than have to depend on throws.
 
M

MC felon

Thanks. The problem is i'm programming a Tic Tac Toe game and the AI
just isn't working! I think there's something wrong with the way i'm
comparing the strings.
 
T

tragomaskhalos

Thanks. The problem is i'm programming a Tic Tac Toe game and the AI
just isn't working! I think there's something wrong with the way i'm
comparing the strings.

<OT>
whilst I know what you mean, 'AI' seems a very grandiose
term for Tic Tac Toe - I mean, I once wrote a passable
implementation on a programmable calculator !
</OT>
 
J

James Kanze

operator[] will not check for out of bounds access while at should.

That's a quality of implementation issue. In the libraries I use
most often, operator[] does bounds checks, aborting the program
if the index is out of bounds. At() guarantees an exception,
which is rarely what you want.
 
J

James Kanze

MC said:
what's the best way to compare two string elements?
std::string cstr;
if ( cstr.at(3) == cstr.at(2)) //do something
or
std::string cstr;
if ( cstr[3] == cstr[2]) //do something
?
[] is a *little* faster, but should only be used when it is
known that the length of the string is greater than the index.
If it is not sure, .at() should be used.

If using an out of bounds index is an error, you should use [],
rather than at(). At least with the implementations I use, []
treats an out of bounds index as an error condition; at() treats
it as an exceptional (but not wrong) situation.
if ( cstr.size() < index )
{
if ( cstr[index] == cstr[index] // do something
}
Of course, that check for size() brings it's own overhead, so
in that case just use .

More frequently, you'll have something like:

assert( index < cstr.size() ) ;

Except, of course, that this code is normally in the operator[]
function itself.
 
J

Jim Langston

(e-mail address removed)
MC said:
what's the best way to compare two string elements?
std::string cstr;
if ( cstr.at(3) == cstr.at(2)) //do something
or
std::string cstr;
if ( cstr[3] == cstr[2]) //do something
?
[] is a *little* faster, but should only be used when it is
known that the length of the string is greater than the index.
If it is not sure, .at() should be used.

If using an out of bounds index is an error, you should use [],
rather than at(). At least with the implementations I use, []
treats an out of bounds index as an error condition; at() treats
it as an exceptional (but not wrong) situation.
if ( cstr.size() < index )
{
if ( cstr[index] == cstr[index] // do something
}
Of course, that check for size() brings it's own overhead, so
in that case just use .

More frequently, you'll have something like:

assert( index < cstr.size() ) ;

Except, of course, that this code is normally in the operator[]
function itself.

============

I see a different result. This program in debug mode:

#include <vector>
#include <iostream>

int main()
{
std::vector<int> data(5);

try
{
data.at(5) = 5;
}
catch (...)
{
std::cout << "Error1\n";
}

try
{
// Causes run time overflow
data[5] = 5;
}
catch (...)
{
std::cout << "Error2\n";
}
}

will output
"Error1"

then tell me that memory has been corrupted.

That being the case isn't it opposite of what you say? That if an overflow
is an error condition then .at() should be used.

I was always lead to be leive that at() would throw on overflow, [] would
not check.
 
J

James Kanze

If using an out of bounds index is an error, you should use
[], rather than at(). At least with the implementations I
use, [] treats an out of bounds index as an error condition;
at() treats it as an exceptional (but not wrong) situation.
I.E.
if ( cstr.size() < index )
{
if ( cstr[index] == cstr[index] // do something
}
Of course, that check for size() brings it's own overhead, so
in that case just use .
More frequently, you'll have something like:
assert( index < cstr.size() ) ;
Except, of course, that this code is normally in the
operator[] function itself.
I see a different result. This program in debug mode:
#include <vector>
#include <iostream>
int main()
{
std::vector<int> data(5);
try
{
data.at(5) = 5;
}
catch (...)
{
std::cout << "Error1\n";
}
try
{
// Causes run time overflow
data[5] = 5;
}
catch (...)
{
std::cout << "Error2\n";
}
}
will output
"Error1"
then tell me that memory has been corrupted.

I get:
Error1
/home/team02/jakan/gnu/gcc/install-4.1.0/sparc/lib/gcc/sparc-sun-
solaris2.8/4.1.0/../../../../../include/c++/4.1.0/debug/vector:192:
error: attempt to subscript container with out-of-bounds index
5, but
container only holds 5 elements.

Objects involved in the operation:
sequence "this" @ 0xffbedf34 {
type = N15__gnu_debug_def6vectorIiSaIiEEE;
}
Abort (core dumped)

That's with g++ (4.1.0). I don't have access to a version of
VC++ at the moment (my PC was "upgraded", and all of the
software I installed myself was lost), so I can't check, but I'm
pretty sure that I've checked this in the past, and VC++ (the
Studios 2005 version) also caught the error (with the options I
normally used---since my .bashrc was also lost in the upgrade, I
can't tell you what they were, except that they were called
$VCPPFLAGS:).
That being the case isn't it opposite of what you say? That
if an overflow is an error condition then .at() should be
used.

At throws an exception. That's NOT what you want in case of a
software error.
I was always lead to be leive that at() would throw on
overflow, [] would not check.

at() is guaranteed to throw, and should be used if you are
prepared to handle the case at some higher level. [] is
undefined behavior, and will cause something similar to an
assertion failure in a good implementation of the library (with,
of course, the possibility of turning the testing off if the
profiler says you have to).

It is regrettable that these checks aren't on by default with
g++, but then, the defaults aren't generally usable for any
compiler I've seen.
 

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

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top