New to using files

I have made a program that takes in a sentence from the user. Then the program makes a list of words that has one copy of each word from the sentence with no words repeated for example if the sentence was:
"This sentence is a this sentence is"
The list would have one copy of each word so the list would be:
"This sentence is a".
Once the list has been made the program goes through the initial input sentence and for each word, its position in the list is printed. So in this example it would print:
"1, 2, 3, 4, 1, 2, 3".
I made this program using strings but now I am trying to make it using files and I am having trouble getting it to work. I have made the code up to the part where it makes the list with only one copy of each word and there are no errors but when I try to print the list, it doesn't print anything. Here is my code:

#include <iostream>
#include <locale>
#include <fstream>
using namespace std;

int main()
{
string sentence;
cout <<"Please enter a sentence:\n\n";
getline(cin, sentence);
for (int i=0; i<sentence.length(); i++)
{
sentence[i]=tolower(sentence[i]);
}
cout <<"\n\n";

// The code above is creating a sentence and setting all letters to lowercase

ofstream PI_sentence ("sentence.txt", ios::trunc);
PI_sentence << sentence;
PI_sentence.close();

// The code above is inserting the sentence into file "sentence.txt"

ofstream PI_no_repeats ("no_repeats.txt", ios::trunc);
PI_no_repeats.close();
ifstream TO_no_repeats ("no_repeats.txt");
TO_no_repeats.close();

// The code above is creating the list that will contain only one copy of each
// word

ifstream TO_sentence ("sentence.txt");
bool word_repeated = false;

// The code above is declaring the stream TO_sentence which I will use to
// input from the file and the bool variable is made to be used in the loop
// below

for (string S_word; TO_sentence >> S_word; word_repeated=false, TO_no_repeats.close(), TO_no_repeats.open("no_repeats.txt"))
// This will go through each word in "sentence.txt" and puts it in S_word
//(Sentence word) UNTIL no more words to take in (loop condition)
{
for (string NR_word; TO_no_repeats >> NR_word;)// This loop goes through each
// word in "no_repeats.txt" and puts it in NR_word
// (No repeats word) UNTIL no more words to take in (loop condition)
{
if (S_word==NR_word) // compares each word in "sentence.txt" to each word in
// no repeats and if there isn't already a copy of that word in
// "no_repeats.txt", word_repeated stays fasle
{
word_repeated=true;
}
}
if (word_repeated=false)
{
TO_no_repeats.close();
PI_no_repeats.open("no_repeats.txt", ios::app);
PI_no_repeats << S_word; // if word_repeated stays false, the word is added to
// no repeats
PI_no_repeats.close();
}
else
{
TO_no_repeats.close();
}
}


string test;
while (getline(TO_no_repeats, test))
{
cout << test; // This is printing the contents of "no_repeats,txt" to see if
// the words reached it
}
}

The output is:

Please enter a sentence:

(takes in sentence)

(program ends)

I expect it to print out no repeats but it just ends. Does anyone see the problem in the code?
Last edited on
closed account (48T7M4Gy)
You seem to be opening and closing files too often. Open once, close once at the end might be better.

To display the contents use something like this.

1
2
3
4
5
6
7
8
9
10
11
12
string word;
    ifstream myfile ("no_repeats.txt");
    if (myfile.is_open())
    {
        while ( myfile >> word )
        {
            cout << word << '\n';
        }
        myfile.close();
    }
    
    else cout << "Unable to open file";


if (word_repeated==false) not if (word_repeated=false)
Last edited on
closed account (48T7M4Gy)
And when you append the word to the no_repeat file you need a space:
1
2
PI_no_repeats.open("no_repeats.txt", ios::app);
            PI_no_repeats << S_word << ' ';


BTW: Have you thought about using <map>'s? They are ideal for this.
1. Read data from the file into std::vector<std::string>
2. Apply tolower() to each std::string stored in the std::vector
3. Apply the following program to the std::vector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>

int main()
{
    const std::vector<std::string> vec { "this", "sentence", "is", "a", "this", "sentence", "is"};
	
    std::vector<size_t> positions;
    std::map<std::string, std::vector<size_t>> myMap;

    for (auto itrOut = vec.cbegin(); itrOut != vec.cend(); ++itrOut)
    {
       positions.push_back(std::distance(vec.cbegin(), itrOut));//first record position of current word
       for (auto itrIn = vec.cbegin(); itrIn != vec.cend();  ++itrIn)
       {
            if(itrIn != itrOut && *itrOut == *itrIn)//not the same word but have same value
            {
                positions.push_back(std::distance(vec.cbegin(), itrIn));//record the position of matches
            }
       }
        myMap[*itrOut] = positions;//store unique words in a map with their positions
        positions.clear();//clear positions to read in the next word
    }
    for (auto& elem : myMap)
    {
        std::cout << elem.first << " ";
        std::sort(elem.second.begin(), elem.second.end());//sort the positions vector before printing
        for (auto& elemS : elem.second)
        {
            std::cout << elemS << " ";
        }
        std::cout << '\n';
    }
}

Output
1
2
3
4
a 3
is 2 6
sentence 1 5
this 0 4

gunnerfunner Thanks for the program but I have already made a working version of this program using strings so that isn't what I need. What I need is to be able to recreate the program using files.
kemort thanks that error fix made my code print out the file at the end but now the error is that no repeats is storing the entire sentence but I only want it to store a list of words with no repeated words
closed account (48T7M4Gy)
@boring etc, I know, so now you have to modify your program so it checks for duplicates before you file a word. Alternatively you can load the current lists of words from the file in an array or vector as gunner mentions, do the comparison and update there, and finally file all the words in the vector, array or <map> even, at the end of the program.
@kem etc,
(btw I moved: TO_no_repeats.close(), TO_no_repeats.open("no_repeats.txt") from the inside for loop to the out side for loop.
All that bit does is close and reopen the file so the initial position resets to the start for the next loop.
Also, I know I could use arrays or vectors then put it into a file at the end but the task specifically says that I have to do the whole program using files. The previous task allowed me to do it using arrays and then at the end I had to import all the array into a file but with this task I have to use files for the whole program.
Also, what do you mean by I need to modify the program so it checks for duplicates before I file a word? I have already done that haven't I with the for loop that checks the current "sentence.txt" word against the entire "no_repeats.txt" file and if the word is repeated, word_repeated = true and nothing is added to the file but if it stays false, the word is added.
closed account (48T7M4Gy)
@b etc etc etc :)
Also, what do you mean by I need to modify the program so it checks for duplicates before I file a word?[/b] The comment was part of the idea around reading the words from the file into memory and doing the work there with arrays or vectors or maps and then writing that to the file at the end of the program/session.

Given that vectors etc are not an option for you the comment/observation doesn't apply.

FWIW I didn't look closely at the logic of your repeat process so I don't have any comment on that aspect.

Cheers
Ok thanks anyway
Topic archived. No new replies allowed.