|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
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; } |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
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; > > } |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
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/ |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
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; } |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
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; } |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
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 |
|
![]() |
| Outils de la discussion | |
|
|