C++ Searching for chars from one string in another string...best approach

Started by
12 comments, last by SKonen 18 years, 9 months ago
Hi all, I'm using the STL to search for characters from one string in another string. I was just wondering is there is another way to do this more efficiently:

using namespace std;

string digitch_ = "0123456789";
string integerch_ = digitch_ + "+-";

bool isInteger(const string & strg)
{
   intu i;
  
   // Check whether an entire string is a number or not
   for (i = 0; i < strg.size(); ++i)
   {
      
      // The string is an integer with just pos or neg sign.
      if ( integerch_.find(strg) != string::npos )
      {
	 // Do nothing.
      }
      else
      {
	 // Just one non-integer breaks and returns.
	 return false;
      }
      
   }
   return true;
}
Any ideas? --random edit: added code tags -SiCrane
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
Advertisement
You can use the std::string::find_first_of() member function. ex:

std::string::size_type index = integerch_.find_first_of(digitch_);
Thanks Si..

Seems there's always another and perhaps better way with the STL.

--random
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
Quote:Original post by SiCrane
You can use the std::string::find_first_of() member function. ex:

std::string::size_type index = integerch_.find_first_of(digitch_);


I've tried to use this, but I think that the logic is the reverse of what was used before. The previous version determines whether the entire string is an integer. However, the version

strg.find_first_of(integerch_)

looks for just one instance of intergerch_ within strg. This can be used as follows:

using namespace std;

bool isNotIntegerch(const string & strg)
{
if ( strg.find_first_of(integerch_) == string::npos )
{
// This means that there is no integerch_.
return true;
}
// This does not mean that all are integerch_! Only one needs to be.
return false;
}

To use find_first_of() I would have to define and search the entire universe of non-integer characters. This seems less efficient than the previous version.

Any suggestions for improvement? Possibly using streams?

--random

--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
If you're specifically trying to determine whether your string is an integer, put it in a stringstream, read the integer off the stream, and check if the read was successful (!fail) and complete (eof).

Added bonus - you get the integer if there is one.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Thanks Fruny,

I've thought about this, but I don't follow. As the argument being passed is a string regardless of character composition, how can I use a stringstream for truth? Won't the argument always be true? Or are you thinking that I pass the argument as a characters?

--random
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
std::string data = "12456";std::ostringstream oss(data);int number;oss >> number;if (oss.fail()){   // Couldn't read the number, so it can't be an int.}else if(!oss.eof()){   // Haven't reached the end of the string   // so it's not just an int. }


Of course, that approach is designed to check for ints, and assumes that getting the actual number is a significant benefit. It wouldn't work for arbitrary set of characters - in which case, you're better off with find_first_not_of, or a regular expression engine. And if you don't need the number, but are doing massive string handling, you may have to roll a custom function.


Incidentally, that stringstream reading pattern is available in Boost as lexical_cast (which literally allows you to cast between strings and numbers). You might want to check it out.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Being the ASCII codepage lists the numerical characters consecutively, you can use this to determine whether a string is representing a numerical value.

bool isInteger( const string & strg ) const
{
for ( int n = strg.size()-1; n >= 0; --n )
{
if (strg[n] >= '0' && (strg[n] - '0') <= 9)
continue;

if (n == 0 && (strg[n] == '-' || strg[n] == '+')
continue;

return false;
}

return true;
}
Quote:Original post by Fruny
std::string data = "12456";std::ostringstream oss(data);int number;oss >> number;if (oss.fail()){   // Couldn't read the number, so it can't be an int.}else if(!oss.eof()){   // Haven't reached the end of the string   // so it's not just an int. }


Of course, that approach is designed to check for ints, and assumes that getting the actual number is a significant benefit. It wouldn't work for arbitrary set of characters - in which case, you're better off with find_first_not_of, or a regular expression engine. And if you don't need the number, but are doing massive string handling, you may have to roll a custom function.


Incidentally, that stringstream reading pattern is available in Boost as lexical_cast (which literally allows you to cast between strings and numbers). You might want to check it out.



Thanks Fruny,

So in my case, something like:

using namespace std;

bool isInteger(const string & strg)
{
ostringstream oss(strg);
int anInteger;

if (oss >> anInteger)
{
return true;
}
return false;
}

bool isReal(const string & strg)
{
ostringstream oss(strg);
float aFloat;

if (oss >> aFloat)
{
return true;
}
return false;
}

Do you think that this would be more efficient (use less cpu) than the original version?

--random
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
If you'd like to use a method similiar to your original (and extremely simple too), just use:

bool isInteger( const string &strg )
{
return (strg.find_first_not_of( integerch_ ) == string::npos);
}

This topic is closed to new replies.

Advertisement