Trying to use a set to generate a list with nonduplicate words( ascending). It works until list needs to display in console.

I'm not quite sure what is wrong with why the text file I put is not showing up in the console. I don't have to have them in ascending order, but at the very least I would like the list to show up.

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  #include<iostream>
#include<set>
#include <fstream>
#include<string>


class info {
	public:
	void ascending() {
		std::string file;
		std::set<std::string> list;
		std::ifstream input(file.c_str());
		std::string words;
		do {
			list.insert(words);

		} while (input >> words);
	}
};


int main() {
	std::set<std::string> list;
	std::string file;
	info text;
	std::cout << "Please enter the name the file that you would like to have read and \n placed in ascending order (duplicates will not appear):" << std::endl;
	std::cin >> file;
	
	//void ascending();
	std::ifstream input(file.c_str());
	
	if (input.is_open()) {
		std::cout << "Here is your list of words in ascending order with no duplicates:" << std::endl;
		text.ascending();
		std::set<std::string>::iterator i = list.begin();
		do {
			i++;
			std::cout << *i << std::endl;
			
		} while (input.is_open() && i != list.end());

		input.close();
	}
	else
	{
		do {
			std::cout << "Please enter a valid filename." << std::endl;
			std::cin >> file;
		} while (input.fail());
	}

return 0;
}


List example, though any txt file can be used.
[code]
burn
juice
secretary
ball
spiffy


{/code]
Also, thanks ahead of time!
Is your if branch (line 32) being entered, or does it go into the else branch and display "Please enter a valid filename"?

The problem appears to be your ascending function.

1
2
3
4
		std::string file;
		std::set<std::string> list;
		std::ifstream input(file.c_str());
		std::string words;
These are all local variables, which have nothing to do with the variables in your main function.

In particular, a std::string is empty by default, so you are doing:
1
2
std::string file;
std::ifstream input(file.c_str());

which is trying to open a file with an empty name, which is not valid.

Also, in your negative path handling:
1
2
3
4
		do {
			std::cout << "Please enter a valid filename." << std::endl;
			std::cin >> file;
		} while (input.fail());
This is an infinite loop. You need to clear the file stream of errors (input.clear()), then call open again.
Last edited on
When I enter anything into my if branch it does say the “here is your list...” section, but nothing shows up. i’m checking on the other sections for the empty file part because that would explain why nothing is happening.
If it helps it does say debug assertion failed. It also say line 195, but i don’t have anything on that line.
I was able to get the list to display in ascending order, but for some reason debug assertion failed is still popping up. I removed the infinite loop and put everything into the function and then called the function in main. I’m going to look it up to try to figure out what that means. Thank you so much! At least it is recognizing the file now. =)
Ignoring the potential issues with reading from a file.....output using a ranged based for loop does work as expected showing the sorted elements in the set:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <string>
#include <set>

int main()
{
   std::set<std::string> mySet { "burn", "juice", "secretary", "ball", "spiffy" };

   for (auto& itr : mySet)
   {
      std::cout << itr << ' ';
   }
   std::cout << '\n';
}

ball burn juice secretary spiffy
If you're still getting some sort of runtime debug assert error, then show your new code, and when you click on "Debug" from the pop-up, what line of code does it bring you to?

Edit: You have an "off-by-one" error in your loop, which is perhaps what FurryGuy is alluding to.
1
2
			i++;
			std::cout << *i << std::endl;
This increments the iterator, and THEN dereferences it. So i could be the last valid element, and then it's incremented and points to list.end(), which should not be dereferenced.
Last edited on
A do...while loop is also not the best choice of iterating through a C++ container. What happens if the container is empty? You have no check for that condition until after your first loop through.

You can use a for loop using iterators (using cbegin/cend instead of begin/end creates a constant iterator, one that won't allow alteration of the elements):
9
10
11
12
13
   for (auto itr { mySet.cbegin() }; itr != mySet.cend(); ++itr)
   {
      std::cout << *itr << ' ';
   }
   std::cout << '\n';


Or a while loop that checks the container before each loop of outputting the elements:
9
10
11
12
13
14
15
16
   auto itr { mySet.cbegin() };

   while (itr != mySet.cend())
   {
      std::cout << *itr << ' ';
      ++itr;
   }
   std::cout << '\n';

If'n you want a range-based for loop that doesn't allow alteration of the container's elements:
9
10
11
12
13
   for (const auto& itr : mySet)
   {
      std::cout << itr << ' ';
   }
   std::cout << '\n';
Last edited on
oh sorry here is the new code. I was looking up stuff on debug assertions.
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58


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


class info {
	public:
	 void ascending() {
		std::string fi;
		std::set<std::string> li;
		std::cin >> fi;
		std::ifstream input(fi.c_str());
		std::string words;
		do {
			li.insert(words);

		} while (input >> words);

		if (input.is_open()) {
			std::cout << "Here is your list of words in ascending order with no duplicates:" << std::endl;
			std::set<std::string>::iterator i = li.begin();
			do {
				i++;
				std::cout << *i << std::endl;

			} while (input.is_open() && i != li.end());

			input.close();
		}
		else
		{/*
			do {
				std::cout << "Please enter a valid filename." << std::endl;
				std::cin >> fi;
			} while (input.fail());*/
		}

	}

};


int main() {
	std::set<std::string> list;
	std::string file;
	info text;
	std::cout << "Please enter the name the file that you would like to have read and \n placed in ascending order (duplicates will not appear):" << std::endl;
	//std::cin >> file;
	
	text.ascending();
	//std::ifstream input(file.c_str());
	
	
return 0;
}


I haven't made complete changes to the do while yet, but i did comment out a portion to test it. I plan on changing it for for based on what Furry Guy said.
I just put everything into the function adjusted it to work and then called the function in the main section.
See the edit to my post as well.
Thank you so much! That is exactly what the problem was. Thanks Furry Guy and Ganado! I should be able to clean up the code from here.
Topic archived. No new replies allowed.