Abhishek Singh
Abhishek Singh

Reputation: 3

Finding a particular word in a text file?

So I'm relatively new to C++ and coding and I recently tried to make this survey program (Please ignore the horrible code). Where I'm stuck is the fact that at the end, when the user would ask for existing info, I have no way to find that particular info with the name in the text file. What can I do about it? Also, the goto label before ExisitingUser shows something like -fpermissive error. Don't know what that is.

Apologies if something like this has been answered before. Couldn't find it.

The code:

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

using namespace std;

int main()
{
    char choiceInfo;
    cout << "Do you want to enter a new user or check existing info? N/E\n";
    cin >> choiceInfo;

    if(choiceInfo == 'N' || choiceInfo == 'n') {
    } else {
        goto existUser;
    }

    x:    
    string firstName,surName,fullName,DoB,quesOne,quesTwo,quesThree,quesFour,quesFive;
    int age;

    cout << "Enter your first name.\n";
    cin >> firstName;    
    cout <<"Enter your surname.\n";
    cin >> surName;

    fullName = firstName + surName;

    cout << "How old are you?\n";
    cin >> age;
    cout << "What is your DoB?\n Format:DD/MM/YYYY\n";
    cin >> DoB;
    cout <<"What is your favorite sport?\n";
    cin >> quesOne;
    cout <<"What is your favorite colour?\n";
    cin >> quesTwo;
    cout <<"Who is your favorite celebrity?\n Please enter all in one word.\n";
    cin >> quesThree;
    cout <<"What is your favorite hobby?\n";
    cin >> quesFour;
    cout <<"Which is your favorite quote?\n";
    cin >> quesFive;
    cout << "Thank you for registering.";

    ofstream writer("Users.txt");

    writer << endl << endl << endl
    << "Full Name: " << fullName << endl
    << "Age: " << age << endl
    << "DOB: " << DoB << endl
    << "Answer to Question 1: "
    << quesOne<< endl
    << "Answer to Question 2: " << quesTwo << endl
    << "Answer to Question 3: " << quesThree << endl
    <<  "Answer to Question 4: " << quesFour << endl
    << "Answer to Question 5: " << quesFive << endl;

    writer.close();

    goto z;

    existUser:
    {
        string userName;
        char letter;

        cout << "Enter full username.\n";
        cin >> userName;

        ifstream reader("Users.txt");

        if (! reader) {
            cout << "Error opening file.";
        } else {
            char(letter);
            for (int i = 0;! reader.eof(); i++) {
                reader.get(letter);
                cout << letter;
                reader.close();
            }
        }
    }
    z:
    return 0; 
}

Upvotes: 0

Views: 486

Answers (2)

mock_blatt
mock_blatt

Reputation: 965

"Ignore the horrible code" is too much to ask. Do not use goto statements, in any programming language, ever. Of course there are exceptions to everything, but they're rare and this isn't one of them. https://xkcd.com/292/

It's hard for anybody to follow your code, but I'll focus on your immediate question, which is finding a word in a text file. If your text file is unstructured and not particularly big, probably your easiest method is to put it into a string, and call the find method of string. Getline is in the string header file.

You have passing familiarity with ifstream. However, you read through the file character by character, which is very slow, and heaven help you if you want to search the file. You can read line by line, and store each line in a string. This is something you may do a lot if you work with text files. Getline reads from the stream until it hits a newline, it discards the newline, loads the line into a string, and moves the stream to the first character of the next line. getline's return value is a little weird, but suffice it to say you can use it in a while loop directly and it will stop when it hits the end of file. If it fails to find it, it returns std::string::npos which is a special value representing a failure of some sort in various string functions.

std::ifstream file("yourfile.txt");
std::string line; //this is the string that we'll be storing the line in
while (getline(file, line)) //read a line of text from file into our line variable
{
    if (line.find("text to find") != std::string::npos) //if we find our text in line
    {
        std::cout << "found it!\n";
        break; //no need to read the other lines
    }
}

An alternative approach, I could have done something like:

std::string line = "";
while (line.find("your text") == std::string::npos) //while I fail to find the line I'm looking for
{
     getline(file,line); // keep reading in lines
}

if (file.eof()) //if I read through the whole file without finding anything
    std::cout << "No luck\n";
else
    std::cout << "found it!\n";

The break in the first example is a pretty common way to see it done, and for smaller, single loops, it's pretty clear what happens. In fact, I bet some people would argue the first is preferable because it's more concise and plenty clear.

In general, you just want to be careful making the code jump all over the place. Gotos do just that, and breaks can do that if you have big, nested loops. Someone trying to follow your code comes across it, and then has to figure out what the enclosing loop is, and then remember what was going on in the outer loop.

Upvotes: 1

Thomas Matthews
Thomas Matthews

Reputation: 57678

Here is a small snippet that will search the file for a keyword:

std::string text_read;
bool        text_found = false;
while (getline(reader, text_read))
{
  if (text_read == fullname)
  {
    text_found = true;
    break;
  }
}
if (text_found)
{
  cout << "Text found.\n";
}

Upvotes: 0

Related Questions