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

Mar 16, 2021 at 3:13pm
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]
Mar 16, 2021 at 3:14pm
Also, thanks ahead of time!
Mar 16, 2021 at 3:26pm
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 Mar 16, 2021 at 3:27pm
Mar 16, 2021 at 3:45pm
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.
Mar 16, 2021 at 3:46pm
If it helps it does say debug assertion failed. It also say line 195, but i don’t have anything on that line.
Mar 16, 2021 at 3:55pm
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. =)
Mar 16, 2021 at 3:57pm
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
Mar 16, 2021 at 3:59pm
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 Mar 16, 2021 at 4:01pm
Mar 16, 2021 at 4:10pm
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 Mar 16, 2021 at 4:27pm
Mar 16, 2021 at 4:13pm
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.
Mar 16, 2021 at 4:14pm
I just put everything into the function adjusted it to work and then called the function in the main section.
Mar 16, 2021 at 4:15pm
See the edit to my post as well.
Mar 16, 2021 at 4:19pm
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.