1

I'm working on an assignment to take data out of a list of names in a .txt document (one on each line, each ending with a comma).

What I want is:

  • Count how many lines there were

  • Use the count to define the size of an array to hold the words

  • Pick two random words from the list and print them.

This is my code:

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

using namespace std;

int main() {    
    srand(time(NULL));
    int j;
    int rand1 = rand() % 5;
    int rand2 = rand() % 5;

    ifstream myfile ("NAMES.txt");

    if (myfile.is_open()) {
        myfile.unsetf(ios_base::skipws);

        unsigned line_count = count(
            istream_iterator<char>(myfile),
            istream_iterator<char>(), 
            '\n');
        j = line_count;

        cout << j << endl;      

        string *MN1 = new string[j];

        for(int i = 0; i <= j; i++) {
            getline(myfile, MN1[i], ',');
        }
        cout << rand1 << endl;
        cout << MN1[rand1] << " " << MN1[rand2] << endl;
    }
    else {
        cout << "Unable to open file" << endl;
    }
}

However, there seems to be something going wrong between when the code reads the number of lines, uses that as the size of the array, then prints the random words.

2
  • 1
    wt is the exact issue ? as you can see, is line_count ok ? Commented Jun 7, 2015 at 2:23
  • Please be more specific when writing questions. Consider: "There seems to be something going wrong" could mean anything. Did the program crash? Infinite loop? Print out the lyrics to "Friday" by Rebecca Black instead of the output you were expecting? What output DID you expect? Notice that the only way for others to have a shot at seeing exactly what you saw would require something you don't provide here... e.g. the file content of "NAMES.TXT". Read up on MCVE and sscce...the bugs you find may be your own! Commented Jun 7, 2015 at 23:40

3 Answers 3

2

It isn't necessary to parse the file twice, and you can use myfile.ignore to ignore the trailing endline which will otherwise pollute your output. It's also not necessary to allocate your strings on the heap, which is generally best to avoid. Here's an example solution using this technique.

#include <fstream>
#include <iostream>
#include <string>
#include <time.h>

using namespace std;

int main()
{
    srand(time(NULL));
    int j;
    int rand1 = rand() % 5;
    int rand2 = rand() % 5;

    ifstream myfile("NAMES.txt");

    if (myfile.is_open()) {
        myfile.unsetf(ios_base::skipws);

        string str;
        for (int i = 0; !myfile.eof(); i++)
        {
            getline(myfile, str, ',');
            myfile.ignore(1);

            if (i == rand1 || i == rand2) {
                cout << str << endl;
            }
        }


    }
    else {
        cout << "Unable to open file" << endl;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

The first iterator reads the file fully. You have to rewind the file after that so you can read it again.

myfile.clear();  // reset file states
myfile.seekg(0); // go back to the the beginning
for(int i = 0; i<=j; i++)
....

2 Comments

Note: To avoid having to read the file twice it would be best to not do this line counting thingy. Resizing buffers is time costly, but reading a file twice costs far more time.
you are correct. My suggestion is to use a stl::vector insted.
0

I would recommend you to use vector <std::string> instead of array of strings, this way you can read all the lines into memory from the file, and then count the number of lines.

std::vector <std::string> MN1;

Reading lines:

for ( std::string line; std::getline ( myfile, line );)
{
    MN1.push_back ( line );
}

Count the number of lines:

j = MN1.size ( );

And i will recommend you to avoid using of keyword new unless it's necessary, and if you allocate memory with keyword new you also have to clean it up when it's not used anymore, this is done with keyword delete.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.