Archived

This topic is now archived and is closed to further replies.

csxpcm

Searching for the occurance of a string at the beginning of a larger string

Recommended Posts

Hi I''m trying to find the method call in C++ to find a substring occurance within a larger string. This will then determine if it should be read in. for instance, FG, Fred, 334, 45 FG, Tony, 321, 34 DB, Paul, 432, 54 FG, Eric, 433, 21 Only if the string starts with FG should it be read in. So assuming I have the following code, "line" is the string to search through (i.e. FG, Fred, 334, 45). string line; getline(in, line); Im stuck here, what method can I use from C++ to determine if it begins with FG. Thanks in advance for any help

Share this post


Link to post
Share on other sites
Instead of reading in the whole line:

std::string first;
std::getline(inFile, first, ',');   // reads the first value, for example "FG", into a std::string

if (first == "FG")   // if the first value is 'FG',
{
    // do whatever
}


std::string has an overloaded equality operator (==), so you can compare strings.

[ Google || Start Here || ACCU || MSDN || STL || GameCoding || BarrysWorld || E-Mail Me ]

[edited by - Lektrix on May 26, 2003 12:46:58 PM]

Share this post


Link to post
Share on other sites
strstr() in string.h

or, just checking the first two characters:

strncmp( line, "FG", strlen("FG") )

Share this post


Link to post
Share on other sites
Hi
thanks for the suggestions!!
The problem is, when using getline to get the first occurance of the larger string, it detects it, but then back in the calling method, it doesnt work.
In the current code layout it doesnt output anything, and when the ''if'' loop body is set to end at the point //A, the calling function doesnt include the first string (the one we checked for), when setting the attributes of glass g.
i.e. the first sting ''valid'' isnt there anymore!
iss >> g.valid >> g.name >> g.score >> g.age;
I guess I have to reset it and move back to the beginning of the string?




  



bool checkValid(istream& in)
{
std::string first;
std::getline(in, first, '','');

if (first == "$FG")
return true;
else
return false;
}





istream& operator>>(istream& in, CPEOPLE& g)
{
using std::replace_if;
istringstream iss;
string line;

bool isValid = checkValid(in);

if (isValid) {
cout << "VALID" << endl;
// A

getline(in, line);
replace_if(line.begin(),line.end(),isComma,'' '');
iss.str(line);

iss >> g.valid >> g.name >> g.score >> g.age;
return iss;
}

}


Share this post


Link to post
Share on other sites
Yes, you could move back to the beginning of the string, or you could do this:

bool checkValid(std::istream& in, std::string& first)
{
    std::getline(in, first, ',');

    return first == "$FG";   // this is just a simpler way; it returns the result of first == "$FG"
}

std::istream& operator>>(std::istream& in, CPEOPLE& g)
{
    using std::replace_if;

    std::string first;
    if (checkValid(in, first))
    {
        g.valid = first;
        // you might want to put the line above at the end of the function, so that
        // all the assignment of g's members are together, but bleh

        std::cout << "VALID" << std::endl;

        std::string line;
        std::getline(in, line);
        replace_if(line.begin(), line.end(), isComma, ' ');

        std::istringstream iss(line);
        iss >> g.name >> g.score >> g.age;
    }

    return in;
    // before you had "return iss;" inside the if statement block, I think you meant "return in;"
    // to be at the end of the function
}


As you can see, the checkValid() function stores the valid value (first) in the std::string that you pass to it. It then assigns this to g.valid. This saves having to go back to the start of the line and read into a string again, etc. Although it is not particularly neat, it is still OK. By the way, sorry but I felt the need to change some of the declarations of the objects to different places and change the code slightly. Bleh, I'm an efficiency boy.

[ Google || Start Here || ACCU || MSDN || STL || GameCoding || BarrysWorld || E-Mail Me ]

[edited by - Lektrix on May 26, 2003 1:57:00 PM]

Share this post


Link to post
Share on other sites
Thanks Lektrix and S1CA!
But Lektrix, there one thing I dont understand.
With the checkValid function you defined, it does''t evaluate to True or False. Therefore, we can''t enter the calling fcuntion loop:
if (checkValid(in, first))
{
// this code would never get executed?
}




  

bool checkValid(std::istream& in, std::string& first)
{
std::getline(in, first, '','');
return first == "$FG";
}

Share this post


Link to post
Share on other sites
It does evaluate to true or false. The line:

return first == "$FG";

returns a bool. The '' first == "$FG" '' part returns true or false and then this bool value is returned by the function. Maybe it will make more sense to you if I add brackets:

return (first == "$FG");

For example, if first does contain "$FG", the std::string comparison will return true and then this true is returned. In this case it would evaluate to this:

return (first == "$FG");   ->   return (true);

[ Google || Start Here || ACCU || MSDN || STL || GameCoding || BarrysWorld || E-Mail Me ]

Share this post


Link to post
Share on other sites
Just do this:


  
std::string line;
std::getline( cin, line );
if( line.substr( 0, 2 ) == "FG" ) {
// read it

}


simple and concise

Share this post


Link to post
Share on other sites
Hmmm, didn't know about the substr() method. What an idiot I am. So yeah, just do what daerid said.

P.S. Remember to add the string stream extraction into g.valid back into the code:

iss >> g.valid >> g.name >> g.score >> g.age;

[ Google || Start Here || ACCU || MSDN || STL || GameCoding || BarrysWorld || E-Mail Me ]

[edited by - Lektrix on May 26, 2003 5:45:01 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Creating a new string with substr isn''t as fast as an in-place compare, though..

inline bool startswith(const std::string& text, const char* start) {
std::string::iterator i = text.begin();
std::string::iterator e = text.end();
while (*start) {
if (i == e || *start != *i) return false;
++i;
++start;
}
return true;
}

Share this post


Link to post
Share on other sites