C++ strings and strchr()

R

Ron Natalie

I guess I'm still dwelling in pointer-land... oh well. Actually, did C++
come up with a better strtok()?
You can write one in a few lines. strtok bites because it maintains a
hidden internal state and that it modifies it's input.
 
R

red floyd

Ron said:
You can write one in a few lines. strtok bites because it maintains a
hidden internal state and that it modifies it's input.

IANALG (I am not a language guru), but I'd bet that your best bet is to write a
"Tokenizer" class. The advantage of that over "strtok" would be that (if done right)
each Tokenizer would have its own state, so you could have several different "parsings"
going on simultaneously, plus you wouldn't corrupt your original string.
 
M

Mike Wahler

I know this now, which is why I said my original plan was flawed (because I
*did* want to shorten the string...) :)

#include <iostream>
#include <string>

int main()
{
std::string s("blah");
std::string::size_type pos(s.find('a'));

if(pos != std::string::npos)
s.erase(pos);

std::cout << s << '\n'; /* prints "bl" */
return 0;
}

Recommendation:
http://www.josuttis.com/libbook/index.html

-Mike
 
A

Agent Mulder

AM> You produced some very ugly code, Mike ;-)7

MW> Why do you find it 'ugly'? What would you do instead
MW> that you'd consider less 'ugly'?

At least you took the effort to type code. That's good.

#include <iostream>
#include <algorithm>
#include <string>
int main(int argc,char**argv)
{
std::string s("Bach");
std::cout<<"\nBefore: "<<s.c_str();
std::replace(s.begin(),s.end(),'B','J');
std::replace(s.begin(),s.end(),'c','h');
std::replace(s.begin(),s.end(),'h','z');
std::cout<<"\nAfter: "<<s.c_str();
}
______
output
Before: Bach
After: Jazz
 
D

Default User

I know this now, which is why I said my original plan was flawed (because I
*did* want to shorten the string...) :)


If you want to use std::string, you need to sit and study them
thoroughly. Stop worrying about C-style strings.




Brian Rodenborn
 
R

Ron Natalie

red floyd said:
IANALG (I am not a language guru), but I'd bet that your best bet is to write a
"Tokenizer" class. The advantage of that over "strtok" would be that (if done right)
each Tokenizer would have its own state, so you could have several different "parsings"
going on simultaneously, plus you wouldn't corrupt your original string.

Yep, and I believe if you google back a bit in this group for "stringtok" you'll find one has
been posted.
 
M

Mike Wahler

Agent Mulder said:
AM> You produced some very ugly code, Mike ;-)7

MW> Why do you find it 'ugly'? What would you do instead
MW> that you'd consider less 'ugly'?

At least you took the effort to type code. That's good.

#include <iostream>
#include <algorithm>
#include <string>
int main(int argc,char**argv)
{
std::string s("Bach");
std::cout<<"\nBefore: "<<s.c_str();
std::replace(s.begin(),s.end(),'B','J');
std::replace(s.begin(),s.end(),'c','h');
std::replace(s.begin(),s.end(),'h','z');
std::cout<<"\nAfter: "<<s.c_str();
}

Why is my code 'uglier' than yours?

I find yours 'uglier' if for no other reason than
that you failed to indent. You also declared parameters
to main() which you never use. Yuck! :)

Why do you make the unnecessary call to 'c_str()'
for output?



(My computer can beat up your computer! :) )

-Mike
 
D

Default User

I guess I'm still dwelling in pointer-land... oh well. Actually, did C++
come up with a better strtok()?


Nothing built-in. Here's a utility I wrote, it's not equivilent to
strtok() but rather ones like PHP explode():


#include <vector>
#include <string>

// breaks apart a string into substrings separated by a character string
// does not use a strtok() style list of separator characters
// returns a vector of std::strings

std::vector<std::string> Explode (const std::string &inString,
const std::string &separator)
{
std::vector<std::string> returnVector;
std::string::size_type start = 0;
std::string::size_type end = 0;

while ((end=inString.find (separator, start)) != std::string::npos)
{
returnVector.push_back (inString.substr (start, end-start));
start = end+separator.size();
}

returnVector.push_back (inString.substr (start));

return returnVector;
}



Brian Rodenborn
 
M

Mike Wahler

Default User said:
Nothing built-in. Here's a utility I wrote, it's not equivilent to
strtok() but rather ones like PHP explode():


#include <vector>
#include <string>

// breaks apart a string into substrings separated by a character string
// does not use a strtok() style list of separator characters
// returns a vector of std::strings

std::vector<std::string> Explode (const std::string &inString,
const std::string &separator)
{
std::vector<std::string> returnVector;
std::string::size_type start = 0;
std::string::size_type end = 0;

while ((end=inString.find (separator, start)) != std::string::npos)
{
returnVector.push_back (inString.substr (start, end-start));
start = end+separator.size();
}

returnVector.push_back (inString.substr (start));

return returnVector;
}

I guess I'll throw mine away now. :) I started to
hack one out, which was beginning to look very much
like this. :)

Thanks.
-Mike
 
A

Agent Mulder

Duh, I forgot the return statement:

#include <string>
#include <iostream>
#include <algorithm>
static std::string s="Bach";
int main(int argc,char**argv)
{
std::cout<<"\nBefore: "<<s.c_str();
std::replace(s.begin(),s.end(),'B','J');
std::replace(s.begin(),s.end(),'c','h');
std::replace(s.begin(),s.end(),'h','z');
std::cout<<"\nAfter: "<<s.c_str();
return 0;
}
______
output
Before: Bach
After: Jazz
 
D

Default User

Mike said:
I guess I'll throw mine away now. :) I started to
hack one out, which was beginning to look very much
like this. :)


I had a project last year that required parsing long strings (flight
plans) with nested delimiters, first "\r\n", then "..", then ":",
finally ",".



Brian Rodenborn
 
D

Default User

Explode? Oh, you mean like "get bigger" and not "make pretty exceptions all
over the place" ;)


Cool, thank you...


One major difference between that code and strtok() (besides string
separators vs. character delimiters) is the behavior with adjacent
delimiters.

Example, the string "one,two,,three" gives the tokens:

one
two
three

When using strtok().

And:

one
two

three

With the Explode() routine. That's by design and desire, so that "empty"
fields are represented, not just ignored.



Brian Rodenborn
 

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

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top