-1

I want to check if the chosen strings appear in the same line. Sadly I don't get the correct output. The file contains this text

/* one 
two
one two
two one
two 
one
something
else */



#include <iostream>
#include <string>
#include <fstream>

using namespace std;

void display(ifstream& MyFile, string a, string b)
{
    string s="";
    int choice;
    cout << "Choose the mode you want to use " << endl;
    cout << "1. Find both words" << endl;
    cout << "2. Find one words" << endl;
    cout << "3. Find where there is none words" << endl;
    cout << "Choose the mode you want to use : ";
    cin >> choice;
    switch (choice) {
    case 1:
        while (getline(MyFile, s))
        {
    
            if (s.find_first_of(a, 0) && (s.find_first_of(b, 0)) )
            {
                cout << "Found both words" << endl;  
            }
        }
        break;
    case 2:
        while (getline(MyFile, s))
        {
            if ((s.find_first_of(a, 0)  && !s.find_first_of(b, 0)) || (!s.find_first_of(a, 0) && s.find_first_of(b, 0) ))
            {
                cout << "Found one word" << endl;
            }
        }
        break;
    case 3:
        while (getline(MyFile, s))
        {
            getline(MyFile, s);
            if (!s.find_first_of(a, 0) && !s.find_first_of(b, 0))
            {
                cout << "No words " << endl;
            }
        }
        break;
    default:
        cout << "Wrong Input" << endl;
    }
}

  
int main()
{
    ifstream Myfile("Mydata.dat");
    string a = "one", b = "two",fileData;
    display(Myfile, a, b);
    Myfile.close();
    return 0;
}

I get "Found both words" 5 times whereas it should be 2. The same thing happens with the other options. My thoughts are that in the if statement I compare the function s.find_firstof(str, pos) wrongly because this function returns the index of the first instance in s of any character in str, starting the search at position pos. My second thought is that I read the data of the file wrong.

Found both words
Found both words
Found both words
Found both words
Found both words
Coder777
  • 49
  • 5
  • Are you sure about the `OR` in `s.find_first_of(a, 0) || (s.find_first_of(b, 0)` ? It seems to me like you would want _both_ conditions to be `true` to say that you've found both words. – Ted Lyngmo Mar 03 '21 at 00:02
  • If you review how your C++ textbook explains the return value from `find_first_of` the problem should be very obvious. `find_first_of` does ***NOT*** return true if the string was found. That's not what it returns. Besides, `find_first_of` is not the right way to search for a given word in the first place, since searching for the word "a" will find it five times in a line that contain a single word: "abracadabra". Would that be your expected result (assuming the return value is checked correctly)? – Sam Varshavchik Mar 03 '21 at 00:06
  • yes, you are right. I've changed that and now it outputs it 1 time. – Coder777 Mar 03 '21 at 00:06
  • Alright, then il try to find a different way. – Coder777 Mar 03 '21 at 00:14

2 Answers2

1

Two obvious errors:

find_first_of() returns a size_t (position) not a bool. To check for success you need find_first_of() != string::npos

Assuming find_first_of() did return a bool:

if (s.find_first_of(a, 0) || (s.find_first_of(b, 0)) )
{
     cout << "Found both words" << endl;  
}

If you find either string then you found both? Wrong. You need && (logical AND) not || (logical OR)

Ignoring the word vs string issue in the comments, I'd simplify your code by counting how many strings were found:

int num_words_found = 0;
if (s.find_first_of(a, 0) != string::npos) { num_words_found++; }
if (s.find_first_of(b, 0) != string::npos) { num_words_found++; }
// none: num_words_found= 0
// one/either: num_words_found= 1
// both: num_words_found= 2
John3136
  • 27,345
  • 3
  • 44
  • 64
0

You are doing the if statement wrong.

I changed the way to verify if a string contains another one, basically s.find(a) will return the start position of a in s if it exists in it, or will return -1 if it doesn't. This way, verifying like this s.find(a) != -1 or s.find(a) <s.length() would work the same way, bacause in conversion of -1 to int is the max of size_t

This should solve your problem:

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

void display(ifstream &MyFile, string a, string b)
{
    string s = "";
    int choice;
    cout << "Choose the mode you want to use " << endl;
    cout << "1. Find both words" << endl;
    cout << "2. Find one words" << endl;
    cout << "3. Find where there is none words" << endl;
    cout << "Choose the mode you want to use : ";
    cin >> choice;
    switch (choice)
    {
    case 1:
        while (getline(MyFile, s))
        {

            if (s.find(a) < s.length() && (s.find(b) < s.length()))
            {
                cout << "Found both words" << endl; // means that this line have BOTH words
            }
        }
        break;
    case 2:
        while (getline(MyFile, s))
        {
            if (s.find(a) < s.length() || (s.find(b) < s.length()))
            {
                cout << "Found one word" << endl; //means that this line have at least one of the two words
            }
            /*
            if (s.find(a) < s.length() && (s.find(b) < s.length())) 
            {
                cout << "Found one word" << endl; //means that this line have the two words at the same time
            }
            */
        }
        break;
    case 3:
        while (getline(MyFile, s))
        {
            getline(MyFile, s);
            if (!s.find_first_of(a, 0) && !s.find_first_of(b, 0))
            {
                cout << "No words " << endl; // means that this line do not have ANY of the two words
            }
        }
        break;
    default:
        cout << "Wrong Input" << endl;
    }
}

int main()
{
    ifstream Myfile("Mydata.dat");
    string a = "one", b = "two", fileData;
    display(Myfile, a, b);
    Myfile.close();
    return 0;
}

The output ou this code is:

Choose the mode you want to use 
1. Find both words
2. Find one words
3. Find where there is none words
Choose the mode you want to use : 1
Found both words
Found both words

and

Choose the mode you want to use 
1. Find both words
2. Find one words
3. Find where there is none words
Choose the mode you want to use : 2
Found one word
Found one word
Found one word
Found one word
Found one word
Found one word
  • Taking your comments at face value: "find returns -1 if not found" then this logic is wrong "s.find(a) < s.length()" because -1 will be < length. The test should just be `find() != npos` (don't use -1, use npos. no need to check against length - c++ isn't going give you a result beyond the end of the string) – John3136 Mar 03 '21 at 00:21
  • Thank you for helping Rodrigo. – Coder777 Mar 03 '21 at 00:33
  • My problem was resolved! Thanks to everybody. – Coder777 Mar 03 '21 at 00:39
  • @Coder777 You accept a completely incorrect answer? I give up ! – John3136 Mar 03 '21 at 01:01