0

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; 
}
  • Could you please use the formatting guidelines for your code. It's difficult to read as is. Also, why are you using a goto? You could easily write this code without them. – ydobonebi Jul 19 '15 at 16:06
  • 2
    I agree - "horrible code" is very difficult to debug. Can you make it less *horrible*? – Drew Dormann Jul 19 '15 at 16:06
  • As I said, I'm relatively new to coding and this is what I intuitively thought to do at first. I tried creating a new function to do it, but I couldn't get it to work and gave up. – Abhishek Singh Jul 19 '15 at 16:08
  • 1
    it looks like the goto statements are just an if/else semantic, I would start by writing it as such. You're relatively new to C++, what did you know/use before? how did you even come to use a goto? generally better techniques are taught first leaving goto unneeded (with like 1 exception) – ydobonebi Jul 19 '15 at 16:09
  • How can you read this?! Also either there are a _lot_ of people named Abhishek Singh, or you keep creating new accounts every few days. If the latter, please stop that. – Lightness Races in Orbit Jul 19 '15 at 16:11
  • *"I tried creating a new function...and gave up"* That's a wrong move. If this question is based on your goal of writing C++ programs without creating a new function, you've already taken a wrong turn. Please, ask a question about your difficulties with writing a function instead. – Drew Dormann Jul 19 '15 at 16:14
  • 1
    Uhm, no. I don't create new accounts. This is my first. – Abhishek Singh Jul 19 '15 at 16:15
  • I understand. And it's not based on my goal. I just wanted to know how can I find a particular word in a text file. I'll try and figure out the rest for myself. – Abhishek Singh Jul 19 '15 at 16:16
  • Well, for future reference, avoid the use of goto statements. Generally, if you're using a goto, you're not doing something right. – ydobonebi Jul 19 '15 at 16:38
  • @QuinnRoundy there are exceptions : http://stackoverflow.com/questions/245742/examples-of-good-gotos-in-c-or-c – Hatted Rooster Jul 19 '15 at 16:51
  • @JameyD if you read my earlier comments, I did mention that. – ydobonebi Jul 19 '15 at 16:53
  • I highly recommend search the web or stackoverflow for "c++ read file string". – Thomas Matthews Jul 19 '15 at 16:54
  • Please show the layout of the data file. Can't read from the data file unless we know the format. – Thomas Matthews Jul 19 '15 at 16:55

2 Answers2

1

"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.

mock_blatt
  • 955
  • 5
  • 11
0

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";
}
Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154