473,405 Members | 2,415 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

C++ strings and strchr()

I want to find the position of a character in a string and replace it another
if it is actually there, and I'd like the operation to be efficient. I'm
assuming the "standard" way to do this is something like

string s = "blah";
int i = s.find_first_of('a'); /* returns 2, I presume? */
s.replace(i,0,"e");

Right? Is this the best way (assuming I haven't made some stupid error)? Is
there a way to (easily!) get a character pointer from a C++ string so I can
just change that one character, like maybe

char *cp;

if( (cp=strchr(s.c_str(), 'a') != NULL)
*cp='e';

? If neither way is good, what's a better way?

(if this is a FAQ, I didn't see it...)

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |
Jul 19 '05 #1
32 8801

<at***@nospam.cyberspace.org> wrote in message news:bi**********@chessie.cirr.com...
string s = "blah"; int i = s.find_first_of('a'); /* returns 2, I presume? */
You need to check to see if the find succeeds (unless you are sure it won't fail).
It might return npos. You could also use s.find('a'). Since your match string is
only a single character they both do the same thing (I'm not sure that one would
be faster than the other).
s.replace(i,0,"e");


That's a no op. It says to replace zero chars. You want.
s.replace(i, 1, "e");
Actually, for a single character this would be just as good
s[i] = 'e';

Jul 19 '05 #2
Ron Natalie <ro*@sensor.com> broke the eternal silence and spoke thus:
Actually, for a single character this would be just as good
s[i] = 'e';


You can reference strings as though they were C-style char*'s?
--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |
Jul 19 '05 #3
at***@nospam.cyberspace.org:
I want to find the position of a character in a string and replace it another if it is actually there, and I'd like the operation to be efficient. I'm
assuming the "standard" way to do this is something like

string s = "blah";
int i = s.find_first_of('a'); /* returns 2, I presume? */
s.replace(i,0,"e");


#include<algorithm>
replace(s.begin(),s.end(),'a','e');

-X
Jul 19 '05 #4

<at***@nospam.cyberspace.org> wrote in message
news:bi**********@chessie.cirr.com...
Ron Natalie <ro*@sensor.com> broke the eternal silence and spoke thus:
Actually, for a single character this would be just as good
s[i] = 'e';


You can reference strings as though they were C-style char*'s?


Not entirely. E.g. 'strlen()' et al won't necessarily work
as you expect. But std::string does feature 'index'
operators '[]'. It also has other 'intuitive' operators,
such as '+' for concatenation.

Which C++ book(s) are you reading?

-Mike

Jul 19 '05 #5

Agent Mulder <mb*******************@home.nl> wrote in message
news:bi**********@news2.tilbu1.nb.home.nl...
at***@nospam.cyberspace.org:
I want to find the position of a character in a string and replace it

another
if it is actually there, and I'd like the operation to be efficient. I'm assuming the "standard" way to do this is something like

string s = "blah";
int i = s.find_first_of('a'); /* returns 2, I presume? */
s.replace(i,0,"e");


#include<algorithm>
replace(s.begin(),s.end(),'a','e');


Nearly all C++ literature I've read states that one
should usually prefer a member function over a 'free'
function, if it does what you need. This is because
a member function could be optimized to take advantage
of internal details not available to 'free' functions.

In OP's case, I'd use 'std::string::find()' followed
by access to the found element with 'std::string::operator[]()'.

$.02,
-Mike

Jul 19 '05 #6
MW> Nearly all C++ literature I've read states that one
MW> should usually prefer a member function over a 'free'
MW> function, if it does what you need. This is because
MW> a member function could be optimized to take advantage
MW> of internal details not available to 'free' functions.

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

<mikes>
#include <iostream>
#include <string>

int main()
{
his();
std::string s("blah");
std::cout << s << '\n';
std::string::size_type i(s.find('a'));

if(i != std::string::npos)
s[i] = 'e';

std::cout << s << '\n';

return 0;
}
</mikes>

-X


Jul 19 '05 #7

<at***@nospam.cyberspace.org> wrote in message news:bi**********@chessie.cirr.com...
Ron Natalie <ro*@sensor.com> broke the eternal silence and spoke thus:
Actually, for a single character this would be just as good
s[i] = 'e';


You can reference strings as though they were C-style char*'s?


Well, not totally, but they do support operator[] as shown above.
Jul 19 '05 #8
Mike Wahler <mk******@mkwahler.net> broke the eternal silence and spoke thus:
Which C++ book(s) are you reading?


"The C++ Programming Language" by Stroustrup (aka God?) - it's in there, but
the book is so big I overlooked it... sorry... but I do have a question
about how they're implemented. Why can't you effectively modify the char*
that c_str gives you? Wouldn't that make one's life easier?

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |
Jul 19 '05 #9
Mike Wahler <mk******@mkwahler.net> broke the eternal silence and spoke thus:
Which C++ book(s) are you reading?


"The C++ Programming Language" by Stroustrup (aka God?) - it's in there, but
the book is so big I overlooked it... sorry... but I do have a question
about how they're implemented. Why can't you effectively modify the char*
that c_str gives you? Wouldn't that make one's life easier when dealing with
C-style string functions?

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |
Jul 19 '05 #10

"Mike Wahler" <mk******@mkwahler.net> wrote in message
news:l8*****************@newsread4.news.pas.earthl ink.net...

Agent Mulder <mb*******************@home.nl> wrote in message
news:bi**********@news2.tilbu1.nb.home.nl...
at***@nospam.cyberspace.org:
I want to find the position of a character in a string and replace it

another
if it is actually there, and I'd like the operation to be efficient. I'm assuming the "standard" way to do this is something like

string s = "blah";
int i = s.find_first_of('a'); /* returns 2, I presume? */
s.replace(i,0,"e");


#include<algorithm>
replace(s.begin(),s.end(),'a','e');


Nearly all C++ literature I've read states that one
should usually prefer a member function over a 'free'
function, if it does what you need. This is because
a member function could be optimized to take advantage
of internal details not available to 'free' functions.

In OP's case, I'd use 'std::string::find()' followed
by access to the found element with 'std::string::operator[]()'.


It would be useful to know the OP's intention here, as the two examples
aren't completely equivalent. One is intended to replace the first occurence
of 'a' with 'e' whilst the other will replace all instances of 'a' with 'e'.
For "blah" the effect is the same, of course.

Jul 19 '05 #11

Agent Mulder <mb*******************@home.nl> wrote in message
news:bi**********@news2.tilbu1.nb.home.nl...
MW> Nearly all C++ literature I've read states that one
MW> should usually prefer a member function over a 'free'
MW> function, if it does what you need. This is because
MW> a member function could be optimized to take advantage
MW> of internal details not available to 'free' functions.

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


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

-Mike

Jul 19 '05 #12
Bob Jacobs <ne****@robertjacobs.fsnet.co.uk> broke the eternal silence and spoke thus:
It would be useful to know the OP's intention here, as the two examples
aren't completely equivalent. One is intended to replace the first occurence
of 'a' with 'e' whilst the other will replace all instances of 'a' with 'e'.
For "blah" the effect is the same, of course.


My original (flawed!) intention was actually to replace a single character in
a string with a null terminator (a la C - guess what I took in college? ;)),
which of course wouldn't have worked... And then I realized that the strings
I wanted already existed in the code anyway, so the whole exercise was
pointless... but at least I learned something.

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |
Jul 19 '05 #13

<at***@nospam.cyberspace.org> wrote in message
news:bi**********@chessie.cirr.com...
Mike Wahler <mk******@mkwahler.net> broke the eternal silence and spoke thus:
Which C++ book(s) are you reading?
"The C++ Programming Language" by Stroustrup (aka God?) - it's in there,

but the book is so big I overlooked it... sorry... but I do have a question
about how they're implemented. Why can't you effectively modify the char*
that c_str gives you? Wouldn't that make one's life easier when dealing with C-style string functions?
Why do you want to use those functions with std::string's?

AFAIK, std::string supports anything you can do with a 'C-style
string', and more, in a much safer way.

-Mike

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |

Jul 19 '05 #14
at***@nospam.cyberspace.org wrote:
Ron Natalie <ro*@sensor.com> broke the eternal silence and spoke thus:

Actually, for a single character this would be just as good
s[i] = 'e';

You can reference strings as though they were C-style char*'s?


You can't access the string directly as C-style char*'s,
but you _can_ access a copy that is a C-style string.
Look up the "c_str()" method:
string b("blah");
cout << strlen(b.c_str());

The std::string class has many of the functions that
are used on C-style strings. Look through the list
of std::string methods.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book

Jul 19 '05 #15

"Mike Wahler" <mk******@mkwahler.net> wrote in message news:Tu81b.1985
2) Even if modifying this array were allowed, it is *not*
the characters of the string itself, only a copy.


Well, potentially not. In practice, it usually is.
Jul 19 '05 #16

<at***@nospam.cyberspace.org> wrote in message news:bi**********@chessie.cirr.com...
Bob Jacobs <ne****@robertjacobs.fsnet.co.uk> broke the eternal silence and spoke thus:
It would be useful to know the OP's intention here, as the two examples
aren't completely equivalent. One is intended to replace the first occurence
of 'a' with 'e' whilst the other will replace all instances of 'a' with 'e'.
For "blah" the effect is the same, of course.


My original (flawed!) intention was actually to replace a single character in
a string with a null terminator (a la C - guess what I took in college? ;)),
which of course wouldn't have worked... And then I realized that the strings
I wanted already existed in the code anyway, so the whole exercise was
pointless... but at least I learned something.


Did you really want to poke a null terminator there, or shorten the string.
Putting a null terminator in a C++ string doesn't make it any shorter.
Jul 19 '05 #17
Mike Wahler <mk******@mkwahler.net> broke the eternal silence and spoke thus:
AFAIK, std::string supports anything you can do with a 'C-style
string', and more, in a much safer way.


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

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |
Jul 19 '05 #18
Mike Wahler <mk******@mkwahler.net> broke the eternal silence and spoke thus:
1) c_str() returns a pointer to an array of *const* characters.
2) Even if modifying this array were allowed, it is *not*
the characters of the string itself, only a copy.


Yes, but my question is why? Are they that afraid of someone actually getting
a char* with strchr() or something and modifying it? Or is it just to
discourage C-style thinking?

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |
Jul 19 '05 #19

<at***@nospam.cyberspace.org> wrote in message news:bi**********@chessie.cirr.com...
Mike Wahler <mk******@mkwahler.net> broke the eternal silence and spoke thus:
AFAIK, std::string supports anything you can do with a 'C-style
string', and more, in a much safer way.


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.
Jul 19 '05 #20
at***@nospam.cyberspace.org wrote:

Ron Natalie <ro*@sensor.com> broke the eternal silence and spoke thus:
Actually, for a single character this would be just as good
s[i] = 'e';


You can reference strings as though they were C-style char*'s?

Yes. What book are you using?

Brian Rodenborn
Jul 19 '05 #21
Ron Natalie wrote:
<at***@nospam.cyberspace.org> wrote in message news:bi**********@chessie.cirr.com...
Mike Wahler <mk******@mkwahler.net> broke the eternal silence and spoke thus:
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.


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.

Jul 19 '05 #22
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

Jul 19 '05 #23
<at***@nospam.cyberspace.org> wrote in message
news:bi**********@chessie.cirr.com...
Ron Natalie <ro*@sensor.com> broke the eternal silence and spoke thus:
Did you really want to poke a null terminator there, or shorten the string. Putting a null terminator in a C++ string doesn't make it any shorter.
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

Jul 19 '05 #24

"red floyd" <no*****@here.dude> wrote in message news:G9*******************@newssvr21.news.prodigy. com...

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.
Jul 19 '05 #25
at***@nospam.cyberspace.org wrote:

Ron Natalie <ro*@sensor.com> broke the eternal silence and spoke thus:
Did you really want to poke a null terminator there, or shorten the string.
Putting a null terminator in a C++ string doesn't make it any shorter.


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
Jul 19 '05 #26

Agent Mulder <mb*******************@home.nl> wrote in message
news:bi**********@news2.tilbu1.nb.home.nl...
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

Jul 19 '05 #27
at***@nospam.cyberspace.org wrote:

Mike Wahler <mk******@mkwahler.net> broke the eternal silence and spoke thus:
AFAIK, std::string supports anything you can do with a 'C-style
string', and more, in a much safer way.


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
Jul 19 '05 #28
Default User <fi********@company.com> wrote in message
news:3F***************@company.com...
at***@nospam.cyberspace.org wrote:

Mike Wahler <mk******@mkwahler.net> broke the eternal silence and spoke thus:
AFAIK, std::string supports anything you can do with a 'C-style
string', and more, in a much safer way.


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;
}


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

Jul 19 '05 #29
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


Jul 19 '05 #30
at***@nospam.cyberspace.org wrote:

Default User <fi********@company.com> broke the eternal silence and spoke thus:
Nothing built-in. Here's a utility I wrote, it's not equivilent to
strtok() but rather ones like PHP explode():


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

Like bust it into pieces.

Brian Rodenborn
Jul 19 '05 #31
Mike Wahler wrote:
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
Jul 19 '05 #32
at***@nospam.cyberspace.org wrote:

Default User <fi********@company.com> broke the eternal silence and spoke thus:
Nothing built-in. Here's a utility I wrote, it's not equivilent to
strtok() but rather ones like PHP explode():


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


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
Jul 19 '05 #33

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Venkat | last post by:
Hi All, I need to copy strings from a single dimensional array to a double dimensional array. Here is my program. #include <stdio.h> #include <stdlib.h>
18
by: stroker_ace | last post by:
Hi, I wonder if anyone could point me in the direction of a discussion on the similarities and differences between the C++ String type and char* strings? The reason I ask is because I am...
23
by: Il Prof | last post by:
Hi! I'm new in C language (but not in structured programming) and i have some questions about strings: 1) What of this two string access methods is faster? - Direct access of the elemtns of...
7
by: David Jacques | last post by:
I have to reformat a string from the form "SRID=4269;POINT(-90.673 69.4310000006199)" to GeometryFromText('POINT (-141.095 68.5430000006417)',4269) ); I have a function to do this by...
15
by: I. Myself | last post by:
This is about reading the .ini files which are used in several of our projects. Currently, the actual read of each line of the file is with this statement: fscanf(file, "%s %s", name, value);...
19
by: pkirk25 | last post by:
I wonder if anyone has time to write a small example program based on this data or to critique my own effort? A file called Realm List.html contains the following data: Bladefist-Horde...
74
by: cman | last post by:
Can you "walk across" C strings or char pointers (using *(sz+1)) like you can with arrays. If not, why not? If so, how? cman
2
by: ts | last post by:
Hello all, Can somebody explain why strchr is declared the way it is? Here is the declaration: char *strchr(const char *s, int c); Mainly I do not understand why the second ...
95
by: hstagni | last post by:
Where can I find a library to created text-based windows applications? Im looking for a library that can make windows and buttons inside console.. Many old apps were make like this, i guess ...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.