PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Autres forums > Forum Programmation & Conception > comp.lang.cplus > Beginners: Count occurrences of a string within a string
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
Beginners: Count occurrences of a string within a string

Réponse
 
LinkBack Outils de la discussion
Vieux 27/02/2008, 03h37   #1
yogi_bear_79
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Beginners: Count occurrences of a string within a string

I'm sure I have a few things wrong here. But I am stuck on how to do
a recurring search. Also my statement cin >> quote; acts weird. If I
enter more than one word it blows right past cin >> findMe; and
completes and exits the code. If you string for cin >> quote; is one
word it behaves correctly or at least in that regard!


#include <iostream>
#include <string>
using namespace std;

string quote;
string findMe;
int foundIt(string str1, string str2);

int main ()
{
cout << " \n Enter a sentence or two:" << endl;
cin >> quote;
cout << " \n Enter string to search for:" << endl;
cin >> findMe;

cout << foundIt(quote, findMe);
}
int foundIt(string str1, string str2)
{
size_t pos;
int x = 0;

pos = str1.find(str1);
if (pos!=string::npos)
x++;

return x;
}
  Réponse avec citation
Vieux 27/02/2008, 03h56   #2
Christopher
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Beginners: Count occurrences of a string within a string

On Feb 26, 9:37 pm, yogi_bear_79 <yogi_bear...@yahoo.com> wrote:
> I'm sure I have a few things wrong here. But I am stuck on how to do
> a recurring search. Also my statement cin >> quote; acts weird. If I
> enter more than one word it blows right past cin >> findMe; and
> completes and exits the code. If you string for cin >> quote; is one
> word it behaves correctly or at least in that regard!
>
> #include <iostream>
> #include <string>
> using namespace std;
>
> string quote;
> string findMe;


Is there a reason to make these global when your passing them as
parameters anyway?

> int foundIt(string str1, string str2);
>
> int main ()
> {
> cout << " \n Enter a sentence or two:" << endl;
> cin >> quote;


you mean 'one word'. Using stream shift operators are not the same as
getting everything in the stream. You want to "get unformatted text
from a stream" or "Copy the contents of a stream buffer". I put those
in quotes for you to search against.

> cout << " \n Enter string to search for:" << endl;
> cin >> findMe;


Same as above

> cout << foundIt(quote, findMe);}


Global params being passed. Wierd.

> int foundIt(string str1, string str2)
> {
> size_t pos;
> int x = 0;
>
> pos = str1.find(str1);
> if (pos!=string::npos)


You found something, perhaps:

increment a count
get the position in the string, of the end of the substring you found
This would probably require that you obtain the length of the
substring
search again starting from that position

> x++;
>
> return x;
>
> }


  Réponse avec citation
Vieux 27/02/2008, 03h58   #3
Micah Cowan
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Beginners: Count occurrences of a string within a string

yogi_bear_79 wrote:
> I'm sure I have a few things wrong here. But I am stuck on how to do
> a recurring search. Also my statement cin >> quote; acts weird. If I
> enter more than one word it blows right past cin >> findMe; and
> completes and exits the code.


The >> operator, when applied to an input stream on the left and a
string on the right, skips any whitespace on the input stream, and then
reads in a single word, up until the next whitespace character (or the
end of the input stream). Thus, if you enter two words on a single line,
your code will print the first prompt, read the first word into quote
(leaving the second), print the second prompt, and read the next word
into findMe (leaving any remaining input, such as the final newline, in
the input stream). It won't wait to receive a second line, because it
already has a second word to read in from the first line.

If reading in a line is what you wanted, rather than words, you should
consider the getline() function.

> int foundIt(string str1, string str2)


Note that str1 and str2 are not the same strings as quote and findMe,
but are instead entirely new strings to which have been copied the
_contents_ of quote and findMe. To avoid the needless copying, you
should use references-to-string as the parameter types, rather than
plain strings.

Also, since you're not going to modify the strings, you'd do well to
make them references to _const_ strings, to tell the caller that you
won't be changing them (which is particularly ful in cases when the
caller itself has promised _its_ caller not to modify these strings):

int foundIt(const string &str1, const string &str2)

> {
> size_t pos;


size_t pos = 0;

> int x = 0;
>
> pos = str1.find(str1);
> if (pos!=string::npos)
> x++;


while (pos != string::npos) {
str1.find(str2, pos);
cout << "Found " << str2 << " at " << pos << '.' << endl;
}

>
> return x;
> }



--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
  Réponse avec citation
Vieux 27/02/2008, 09h52   #4
James Kanze
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Beginners: Count occurrences of a string within a string

On Feb 27, 4:37 am, yogi_bear_79 <yogi_bear...@yahoo.com> wrote:
> I'm sure I have a few things wrong here. But I am stuck on
> how to do a recurring search. Also my statement cin >> quote;
> acts weird. If I enter more than one word it blows right past
> cin >> findMe; and completes and exits the code. If you
> string for cin >> quote; is one word it behaves correctly or
> at least in that regard!


So how do you want to decide how much text to read with the
first >>. If you want a word (skipping any white space which
precedes it), use >>. If you want a line, use getline(). If
you want the entire file, you can do so using
istreambuf_iterators, or with something like s <<
std::cin.rdbuf(), where s is a istringstream, but then you'll
have read end of file, and not be able to enter the search
string. If you want some other convention, you'll probably have
to program it. (Under Unix, a line consisting of a single '.'
is a frequent convention. This could be done something like:

std::string line ;
while ( std::getline( std::cin, line ) && line != "." ) {
quote += line + '\n' ;
}

. I'd definitely put this in a separate function, however.)

For the lookup, I'd generally prefer the standard algorithms
over the member functions of std::string. If you're learning,
I'd especially prefer them; they represent the usual idiom for
processing any container, and using them will get you used to
iterators in general. Something like:

int
countMatches(
std::string const& text,
std::string const& toMatch )
{
int result = 0 ;
for ( std::string::const_iterator current
= std::search( text.begin(), text.end(),
toMatch.begin(),
toMatch.end() ) ;
current != text.end() ;
current = std::search(
current + toMatch.size(), text.end(),
toMatch.begin(), toMatch.end() ) {
++ result ;
}
return result ;
}

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
  Réponse avec citation
Vieux 28/02/2008, 01h00   #5
yogi_bear_79
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Beginners: Count occurrences of a string within a string

On Feb 26, 10:58pm, Micah Cowan <mi...@cowan.name> wrote:
> yogi_bear_79 wrote:
> > I'm sure I have a few things wrong here. But I am stuck on how to do
> > a recurring search. Also my statement cin >> quote; acts weird. IfI
> > enter more than one word it blows right past cin >> findMe; and
> > completes and exits the code.

>
> The >> operator, when applied to an input stream on the left and a
> string on the right, skips any whitespace on the input stream, and then
> reads in a single word, up until the next whitespace character (or the
> end of the input stream). Thus, if you enter two words on a single line,
> your code will print the first prompt, read the first word into quote
> (leaving the second), print the second prompt, and read the next word
> into findMe (leaving any remaining input, such as the final newline, in
> the input stream). It won't wait to receive a second line, because it
> already has a second word to read in from the first line.
>
> If reading in a line is what you wanted, rather than words, you should
> consider the getline() function.
>
> > int foundIt(string str1, string str2)

>
> Note that str1 and str2 are not the same strings as quote and findMe,
> but are instead entirely new strings to which have been copied the
> _contents_ of quote and findMe. To avoid the needless copying, you
> should use references-to-string as the parameter types, rather than
> plain strings.
>
> Also, since you're not going to modify the strings, you'd do well to
> make them references to _const_ strings, to tell the caller that you
> won't be changing them (which is particularly ful in cases when the
> caller itself has promised _its_ caller not to modify these strings):
>
> int foundIt(const string &str1, const string &str2)
>
> > {
> > size_t pos;

>
> size_t pos = 0;
>
> > int x = 0;

>
> > pos = str1.find(str1);
> > if (pos!=string::npos)
> > x++;

>
> while (pos != string::npos) {
> str1.find(str2, pos);
> cout << "Found " << str2 << " at " << pos << '.' << endl;
> }
>
>
>
> > return x;
> > }

>
> --
> Micah J. Cowan
> Programmer, musician, typesetting enthusiast, gamer...http://micah.cowan.name/


Thanks to everyone for their & tips. I managed to get it really
close. Below is my entire code, the current problem is the While loop
is infinite. My task is to count the number of times the substring
appears in the string:qote. I planned to use the int x to count. That
is where I am stuck. The code as is does find the occurances I am
looking for, but I think I need an if statement to qualify weather or
not it found something, if it did, then increment x. I'd assume if it
didn't find anything then the search is over, so it would bs something
like. If found then increment x and loop, else exit the loop. So I
what I need is an if statemnt that will verify something was found or
not.

James, I think your code was a bit further ahead than I am supposed to
know at this point!

#include <iostream>
#include <string>
using namespace std;


int findIt(const string &str1, const string &str2);

int main ()
{
string quote;
string findMe;

cout << " \n Enter a sentence or two:" << endl;
getline (cin,quote);
cout << " \n Enter string to search for:" << endl;
getline (cin,findMe);

cout << findIt(quote, findMe);
}
int findIt(const string &str1, const string &str2)
{
size_t pos = 0;
int x = 0;

while (pos != string::npos) {
pos = str1.find(str2, pos);
cout << pos<<endl;
pos = pos+str2.size();
}

return x;
}
  Réponse avec citation
Vieux 28/02/2008, 02h32   #6
yogi_bear_79
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Beginners: Count occurrences of a string within a string

On Feb 27, 8:00pm, yogi_bear_79 <yogi_bear...@yahoo.com> wrote:
> On Feb 26, 10:58pm, Micah Cowan <mi...@cowan.name> wrote:
>
>
>
>
>
> > yogi_bear_79 wrote:
> > > I'm sure I have a few things wrong here. But I am stuck on how to do
> > > a recurring search. Also my statement cin >> quote; acts weird. If I
> > > enter more than one word it blows right past cin >> findMe; and
> > > completes and exits the code.

>
> > The >> operator, when applied to an input stream on the left and a
> > string on the right, skips any whitespace on the input stream, and then
> > reads in a single word, up until the next whitespace character (or the
> > end of the input stream). Thus, if you enter two words on a single line,
> > your code will print the first prompt, read the first word into quote
> > (leaving the second), print the second prompt, and read the next word
> > into findMe (leaving any remaining input, such as the final newline, in
> > the input stream). It won't wait to receive a second line, because it
> > already has a second word to read in from the first line.

>
> > If reading in a line is what you wanted, rather than words, you should
> > consider the getline() function.

>
> > > int foundIt(string str1, string str2)

>
> > Note that str1 and str2 are not the same strings as quote and findMe,
> > but are instead entirely new strings to which have been copied the
> > _contents_ of quote and findMe. To avoid the needless copying, you
> > should use references-to-string as the parameter types, rather than
> > plain strings.

>
> > Also, since you're not going to modify the strings, you'd do well to
> > make them references to _const_ strings, to tell the caller that you
> > won't be changing them (which is particularly ful in cases when the
> > caller itself has promised _its_ caller not to modify these strings):

>
> > int foundIt(const string &str1, const string &str2)

>
> > > {
> > > size_t pos;

>
> > size_t pos = 0;

>
> > > int x = 0;

>
> > > pos = str1.find(str1);
> > > if (pos!=string::npos)
> > > x++;

>
> > while (pos != string::npos) {
> > str1.find(str2, pos);
> > cout << "Found " << str2 << " at " << pos << '.' << endl;
> > }

>
> > > return x;
> > > }

>
> > --
> > Micah J. Cowan
> > Programmer, musician, typesetting enthusiast, gamer...http://micah.cowan..name/

>
> Thanks to everyone for their & tips. I managed to get it really
> close. Below is my entire code, the current problem is the While loop
> is infinite. My task is to count the number of times the substring
> appears in the string:qote. I planned to use the int x to count. That
> is where I am stuck. The code as is does find the occurances I am
> looking for, but I think I need an if statement to qualify weather or
> not it found something, if it did, then increment x. I'd assume if it
> didn't find anything then the search is over, so it would bs something
> like. If found then increment x and loop, else exit the loop. So I
> what I need is an if statemnt that will verify something was found or
> not.
>
> James, I think your code was a bit further ahead than I am supposed to
> know at this point!
>
> #include <iostream>
> #include <string>
> using namespace std;
>
> int findIt(const string &str1, const string &str2);
>
> int main ()
> {
> string quote;
> string findMe;
>
> cout << " \n Enter a sentence or two:" << endl;
> getline (cin,quote);
> cout << " \n Enter string to search for:" << endl;
> getline (cin,findMe);
>
> cout << findIt(quote, findMe);}
>
> int findIt(const string &str1, const string &str2)
> {
> size_t pos = 0;
> int x = 0;
>
> while (pos != string::npos) {
> pos = str1.find(str2, pos);
> cout << pos<<endl;
> pos = pos+str2.size();
> }
>
> return x;
>
>
>
> }- Hide quoted text -
>
> - Show quoted text -- Hide quoted text -
>
> - Show quoted text -


Final Working Code:

#include <iostream>
#include <string>
using namespace std;


int findIt(const string &str1, const string &str2);

int main ()
{
string quote;
string findMe;

cout << " \n Enter a sentence or two:" << endl;
getline (cin,quote);
cout << " \n Enter string to search for:" << endl;
getline (cin,findMe);

cout << "\n There are " << findIt(quote, findMe) <<
" occurances of '" << findMe << "' in the "
"string you entered."<<endl;
}
int findIt(const string &str1, const string &str2)
{
size_t pos = 0;
int x = 0;

while (pos != string::npos) {
pos = str1.find(str2, pos);
if (pos!=string::npos){
x++;
pos = pos+str2.size();
}
}

return x;
}
  Réponse avec citation
Vieux 28/02/2008, 14h49   #7
James Kanze
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Beginners: Count occurrences of a string within a string

On Feb 28, 2:00 am, yogi_bear_79 <yogi_bear...@yahoo.com> wrote:
> On Feb 26, 10:58 pm, Micah Cowan <mi...@cowan.name> wrote:
> > yogi_bear_79 wrote:


[...]
> James, I think your code was a bit further ahead than I am
> supposed to know at this point!


I'm not sure how? You should be learning the standard
algorithms long before the specific functions of std::string
(which I probably wouldn't bother teaching at all), and you
should be learning iterators before dealing with pos in a
string. (But of course, you can apply the exact same algorithm
using the position and std::string::find instead of the
iterators and std::search.)

> #include <iostream>
> #include <string>
> using namespace std;


> int findIt(const string &str1, const string &str2);


> int main ()
> {
> string quote;
> string findMe;


> cout << " \n Enter a sentence or two:" << endl;
> getline (cin,quote);
> cout << " \n Enter string to search for:" << endl;
> getline (cin,findMe);


> cout << findIt(quote, findMe);}


> int findIt(const string &str1, const string &str2)
> {
> size_t pos = 0;
> int x = 0;


> while (pos != string::npos) {
> pos = str1.find(str2, pos);
> cout << pos<<endl;
> pos = pos+str2.size();


What happens in this line when str1.find returns
std::string::npos?

> }


You really do want the loop I proposed:

for ( size_t pos = str1.find( str2 ) ;
pos != std::string::npos ;
pos = str1.find( str2, pos + str2.size() ) {
// Whatever you do when you find a match...
}

As a general rule: prefer for, with no modification of the
control variable outside of the third part. It's much easier to
get right. (If you need the value of the control variable after
the loop, either move the first part of the for before the loop,
or rewrite the loop as a while. And of course, don't try to
force things which don't fit into this pattern.)

You're problem, of course, is that you're modifying the control
variable twice in the loop, and the first modification might
cause the loop invariant (pos != std::string::npos) to be
invalid. The only operations which should possibly invalidate
the loop invariant should be at the end of the loop. A for
makes this clearer---the only operations which might invalidate
the loop invariant should be in the third part of the for.

> return x;
> }


--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
  Réponse avec citation
Vieux 28/02/2008, 14h58   #8
James Kanze
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Beginners: Count occurrences of a string within a string

On Feb 28, 3:32 am, yogi_bear_79 <yogi_bear...@yahoo.com> wrote:

[...]
> Final Working Code:


> int findIt(const string &str1, const string &str2)
> {
> size_t pos = 0;
> int x = 0;


> while (pos != string::npos) {
> pos = str1.find(str2, pos);
> if (pos!=string::npos){
> x++;
> pos = pos+str2.size();
> }
> }
> return x;
> }


Sort of. I think you'll still missing the basic principles of
how to write a loop. For example, what is the loop invariant
here? And how do you prove that each pass through the loop
"advances"? (You can do the latter, but it's far more
complicated than it should be.)

Suppose we take as an invariant that pos points to a match (and
thus is not std::string::npos). That results in something like
the loop I just proposed. Where the invariant is always true in
the loop (no need for a special if to verify it---the test is
part of the loop condition). And it's trivial to prove
advancement, because the pos + str2.size() is executed every
time we enter the loop---it's not in any conditional block.

(FWIW: both your code and mine do have one error. What are the
results if someone enters an empty string as the search string?
I think this problem needs to be handled first at the level of
specification, however; there are an infinite number of empty
strings in any string you care to consider.)

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 13h33.


Édité par : vBulletin® version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières
Ad Management by RedTyger
©Tous droits réservés par les parties respectives
Page generated in 0,31021 seconds with 16 queries