Searching Vectors of strings for user input values

Pages: 12
Hi all,
very new beginner to C++ here. I'm writing a simple program that reads a .txt file of an english dictionary, and allows the user to search for words and returns the definition.

I've managed to get the .txt file stored into a vector, but i'm stuck trying to figure out a function that takes the user input, searches the vector for their word, then prints that word with the following element (the definition). alot of posts i've seen talk about the .find() function, is that suitable for what i need to do?

.txt file format:

a [misc]
The first letter of the English and of many other alphabets. The capital A of the alphabets of Middle and Western Europe as also the small letter (a) besides the forms in Italic black letter etc. are all descended from the old Latin A which was borrowed from the Greek Alpha of the same form; and this was made from the first letter (�) of the Phoenician alphabet the equivalent of the Hebrew Aleph and itself from the Egyptian origin. The Aleph was a consonant letter with a guttural breath sound that was not an element of Greek articulation; and the Greeks took it to represent their vowel Alpha with the a sound the Phoenician alphabet having no vowel symbols; The name of the sixth tone in the model major scale (that in C) or the first tone of the minor scale which is named after it the scale in A minor. The second string of the violin is tuned to the A in the treble staff. -- A sharp (A♯) is the name of a musical tone intermediate between A and B. -- A flat (A♭) is the name of a tone intermediate between A and G; An adjective commonly called the indefinite article and signifying one or any but less emphatically; In each; to or for each; as “twenty leagues a day” “a hundred pounds a year” “a dollar a yard” etc; In; on; at; by; In process of; in the act of; into; to; -- used with verbal substantives in -ing which begin with a consonant. This is a shortened form of the preposition an (which was used before the vowel sound); as in a hunting a building a begging; Of; A barbarous corruption of have of he and sometimes of it and of they; An expletive void of sense to fill up the meter.

a- [misc]
A as a prefix to English words is derived from various sources. (1) It frequently signifies on or in (from an a forms of AS. on) denoting a state as in afoot on foot abed amiss asleep aground aloft away (AS. onweg) and analogically ablaze atremble etc. (2) AS. of off from as in adown (AS. ofdūne off the dun or hill). (3) AS. ā- (Goth. us- ur- Ger. er-) usually giving an intensive force and sometimes the sense of away on back as in arise abide ago. (4) Old English y- or i- (corrupted from the AS. inseparable particle ge- cognate with OHG. ga- gi- Goth. ga-) which as a prefix made no essential addition to the meaning as in aware. (5) French a (L. ad to) as in abase achieve. (6) L. a ab abs from as in avert. (7) Greek insep. prefix α without or privative not as in abyss atheist; akin to E. un-.

aa [n]
acronym for Associate in Arts a college degree granted for successful completion of a two-year course of study in arts or general topics; Alcoholics Anonymous.

aaas [n]
the American Association for the Advancement of Science an organization with headquarters in Washington D.C. Its goal is to advance the physical and social sciences and it publishes a weekly journal Science with original research articles as well as reviews and commentary.

aam [n]
A Dutch and German measure of liquids varying in different cities being at Amsterdam about 41 wine gallons at Antwerp 3612 at Hamburg 3814.

aardvark [n]
An edentate mammal of the genus Orycteropus (Orycteropus afer) somewhat resembling a pig common in some parts of Southern Africa. It is a nocturnal ungulate burrows in the ground with its powerful claws and feeds entirely on ants and termites which it catches with its long extensile slimy tongue. It is the sole extant representative of the order Tubulidentata.

aard-wolf [n]
A carnivorous striped quadruped mammal (Proteles cristata formerly Proteles Lalandii) of South Africa resembling the fox and hyena. It feeds chiefly on insects. See Proteles.

aaronic [adj]
Pertaining to Aaron the first high priest of the Jews.

aarons-rod [misc]
A rod with one serpent twined around it thus differing from the caduceus of Mercury which has two; A plant with a tall flowering stem; esp. the great mullein or hag-taper and the golden-rod.

aas [n]
an associate degree conferred for successful studies in applied science; a loose sleeveless outer garment made from aba cloth; worn by Arabs.


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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

class Word
{
public:
	string setWord()
	{

	}

	string getWord() {
		return word;
	}
	string getDef() {
		return definition;
	}
	string getType() {
		return type;
	}
private:
	string word;
	string definition;
	string type;
};

class Dictionary_part01
{
private:
	vector<string> wordList;
public:
	void searchVector()
	{
		string value;
		cin >> value;

		if (std::find(wordList.begin(), wordList.end(), value) != wordList.end())
		{
			cout << value;
		}
	}
	//setters
	void setInput()
	{
	
	}

	//loadDictionary function
	    void loadDictionary() {
			string words;
		string myfile = "dictionary2021.txt";
		cout << "Attempting to read Dictionary....\n";
		ifstream dict(myfile);
		if (!dict)
		{
			cout << "Error reading file :( Please restart the program" << endl;
			exit(4);
		}
		while (!dict.eof())
		{
			getline(dict, words);
			{
				wordList.push_back(words);
			}
		}
	dict.close();
	}
};


int main()
{
	Dictionary_part01 function;
	function.loadDictionary();
	int choice;
	
	do
	{
		cout << "Welcome to my Dictionary program!\n----------------------------------\nPlease select an option from the menu:\n1. Enter a word to search\n2.Find words with more than three Zs\n3.List all words that have a q without a following u\n4. Quit\n";
		cin >> choice;
		switch (choice)
		{
		case 1:
			cout << "Enter your word: \n";
			function.searchVector();

			break;
		case 2:
			cout << "Lets have a look!\n";
			break;
		case 3:
			cout << "This might be hard, lets find them!\n";
			break;
		case 4:
			cout << "Thanks for checking this out, see you next time!\n";
		}
	} 	
	while (choice!=4);
	
}
Last edited on
The file used should have both the word and its definition. These need to be stored together - possibly using a vector of some struct. Then you can find the word and obtain the definition. Examples (not tried):

1
2
3
4
5
6
7
8
9
10
11
struct Words {
    std::string word;
    std::string def;
};

std::vector<Words> wordList;

if (const auto itr {std::find_if(wordlist.begin(), wordlist.end(), [&value](const auto& w) {return w.word == value;})}; itr != wordlist.end())
    std::cout << itr->def << '\n';
else
    std::cout << "Not found\n";


However, a better container to use would be std::map.
http://www.cplusplus.com/reference/map/map/

1
2
3
4
5
6
std::map<std::string, std::string> wordList;

if (const auto itr {wordList.find(value)}; itr != wordList.end())
    std::cout << itr->second << '\n';
else
    std::cout << "Not found\n";

Last edited on
Hello ConfusedCoder90,

To start with line 9 should be using "std::getline()". I am guessing that the "word"list" vector is given values from a file because you did not say anything different.

Speaking of file you should post the input file, if it is large a good sample will do.

I also have to question if the word list contains any words that may have a space, hence the "std::getline()".

Should any word have a space it would through the vector off and be 1 or more than you need.

Line is missing the rest. It is challenging to figure out what is missing.

In the if statement "std::find" returns an iterator to the element that is found, but you never capture this for later use.

It appears that you have a vector for words, but what did you do about the definitions? Is that a different vector?

You may want to consider a struct to hold the word and the definition then a vector of structs. This way the work and definition is in 1 place.

Most times it is best to provide enough code that can be compiled and tested along with any input file(s) that are needed.

Andy
Hey guys, thanks very much for the speedy responses, apologies for the lack of information earlier, I've posted the full code (unfiinished) as well as a snapshot of the format the .txt file is in.

I know the code is probably all over the place, it's the first thing i've tried to make with C++
Hello ConfusedCoder90,


I've posted the full code



Where?

Andy

Edit:
" http://www. " as long as there is a space preceding "html" and a space or enter after the end it will show up here as a link.
Last edited on
Hi Handy Andy,

sorry i edited my original post, but if it isn't showing, it's also here;
https://pastebin.com/EPMBJsTZ

The .txt file format is as follows;
a [misc]
The first letter of the English and of many other alphabets. The capital A of the alphabets of Middle and Western Europe as also the small letter (a) besides the forms in Italic black letter etc. are all descended from the old Latin A which was borrowed from the Greek Alpha of the same form; and this was made from the first letter (�) of the Phoenician alphabet the equivalent of the Hebrew Aleph and itself from the Egyptian origin. The Aleph was a consonant letter with a guttural breath sound that was not an element of Greek articulation; and the Greeks took it to represent their vowel Alpha with the a sound the Phoenician alphabet having no vowel symbols; The name of the sixth tone in the model major scale (that in C) or the first tone of the minor scale which is named after it the scale in A minor. The second string of the violin is tuned to the A in the treble staff. -- A sharp (A♯) is the name of a musical tone intermediate between A and B. -- A flat (A♭) is the name of a tone intermediate between A and G; An adjective commonly called the indefinite article and signifying one or any but less emphatically; In each; to or for each; as “twenty leagues a day” “a hundred pounds a year” “a dollar a yard” etc; In; on; at; by; In process of; in the act of; into; to; -- used with verbal substantives in -ing which begin with a consonant. This is a shortened form of the preposition an (which was used before the vowel sound); as in a hunting a building a begging; Of; A barbarous corruption of have of he and sometimes of it and of they; An expletive void of sense to fill up the meter.

a- [misc]
A as a prefix to English words is derived from various sources. (1) It frequently signifies on or in (from an a forms of AS. on) denoting a state as in afoot on foot abed amiss asleep aground aloft away (AS. onweg) and analogically ablaze atremble etc. (2) AS. of off from as in adown (AS. ofdūne off the dun or hill). (3) AS. ā- (Goth. us- ur- Ger. er-) usually giving an intensive force and sometimes the sense of away on back as in arise abide ago. (4) Old English y- or i- (corrupted from the AS. inseparable particle ge- cognate with OHG. ga- gi- Goth. ga-) which as a prefix made no essential addition to the meaning as in aware. (5) French a (L. ad to) as in abase achieve. (6) L. a ab abs from as in avert. (7) Greek insep. prefix α without or privative not as in abyss atheist; akin to E. un-.

aa [n]
acronym for Associate in Arts a college degree granted for successful completion of a two-year course of study in arts or general topics; Alcoholics Anonymous.

aaas [n]
the American Association for the Advancement of Science an organization with headquarters in Washington D.C. Its goal is to advance the physical and social sciences and it publishes a weekly journal Science with original research articles as well as reviews and commentary.

aam [n]
A Dutch and German measure of liquids varying in different cities being at Amsterdam about 41 wine gallons at Antwerp 3612 at Hamburg 3814.

aardvark [n]
An edentate mammal of the genus Orycteropus (Orycteropus afer) somewhat resembling a pig common in some parts of Southern Africa. It is a nocturnal ungulate burrows in the ground with its powerful claws and feeds entirely on ants and termites which it catches with its long extensile slimy tongue. It is the sole extant representative of the order Tubulidentata.

aard-wolf [n]
A carnivorous striped quadruped mammal (Proteles cristata formerly Proteles Lalandii) of South Africa resembling the fox and hyena. It feeds chiefly on insects. See Proteles.

aaronic [adj]
Pertaining to Aaron the first high priest of the Jews.

aarons-rod [misc]
A rod with one serpent twined around it thus differing from the caduceus of Mercury which has two; A plant with a tall flowering stem; esp. the great mullein or hag-taper and the golden-rod.

aas [n]
an associate degree conferred for successful studies in applied science; a loose sleeveless outer garment made from aba cloth; worn by Arabs.

Hello ConfusedCoder90,

What I have noticed or found so far:

Both classes have a set function that need to be completed if you intend to use them.

In the "loadDictionary" function you have some problems. Do not use the C function exit. This is an immediate exit from the program and as a C function it does not know about classes and how to clean them up before the program ends.

Next is the while loop. It does not work the way that you are thinking it does. It is checking for end of file before it is actually set. This tends to do 1 more loop than is needed. And you process something that is not read.

This should work better for you:
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
int loadDictionary()
{
    const string myfile{ "dictionary2021.txt" };  // <--- Moved. You do not need the (=) the {}s will do.

    ifstream dict(myfile);  // <--- You should do this part first. If the file did not open you leave the function.

    if (!dict)
    {
        cout << "Error reading file :( Please restart the program\n";

        return 4;  // <--- Do not use the C function exit.
    }

    string words, deff;

    cout << "Attempting to read Dictionary....\n";

    //while (!dict.eof())  // <--- Does not work the way you are thinking.
    //{
    //    getline(dict, words);
    //    {  // <--- You do not need the {}s here.
    //        wordList.push_back(words);
    //    }
    //}

    while (getline(dict, words))
    {
        std::cout << "\n" << words << '\n';

        wordList.push_back(words);

        std::getline(dict, deff);

        std::cout<<"\n"<<deff;  // <--- Not quite what you need, but shows what you read.

        std::cin.get();
    }

    //dict.close();  // <--- Not required as the dtor will close the file when the function looses scope. OK if you want to leave it.

    return 0;  // <--- Means everything is OK.
}


This code produces this output:

Attempting to read Dictionary....
a [misc]

The first letter of the English and of many other alphabets. The capital A o
f the alphabets of Middle and Western Europe as also the small letter (a) besides the forms in Italic black le
tter etc. are all descended from the old Latin A which was borrowed from the Greek Alpha of t
he same form; and this was made from the first letter (�) of the Phoenician alphabet the eq
uivalent of the Hebrew Aleph and itself from the Egyptian origin. The Aleph was a consonant l
etter with a guttural breath sound that was not an element of Greek articulation; and the Gre
eks took it to represent their vowel Alpha with the a sound the Phoenician alphabet having no
 vowel symbols; The name of the sixth tone in the model major scale (that in C) or the first
tone of the minor scale which is named after it the scale in A minor. The second string of the violin is tuned to the A in the treble staff. -- A sharp (AΓÖ») is the name of a musical tone intermediate between A and B. -- A flat (AΓÖ¡) is the name of a tone intermediate between A and G; An adjective commonly called the indefinite article and signifying one or any but less emphatically; In each; to or for each; as ΓÇ£twenty leagues a dayΓÇ¥ ΓÇ£a hundred pounds a yearΓÇ¥ ΓÇ£a dollar a yardΓÇ¥ etc; In; on; at; by; In process of; in the act of; into; to; -- used with verbal substantives in -ing which begin with a consonant. This is a shortened form of the preposition an (which was used before the vowel sound); as in a hunting a building a begging; Of; A barbarous corruption of have of he and sometimes of it and of they; An expletive void of sense to fill up the meter.


As you can try to see the console is much smaller than the last line or when everything was on 1 line.

As you scroll to the right notice some part in bold that do not print what you originally put in your file. The fancy (” “) you use may print here fine, but may not work in the program. Not every console used the same font as what you wrote the definition in. You will need to change this(” “) to this (" "). It would look a little better.

At the moment all I could is print out the definition since you do not show ayy way of storing it.

Also you will need to account for the blank line between words. Then there is the question of [misc] or [n] that I see. is that to be part of the work or something else.

The next thing to consider is a word that has a space in it. "std""getline will get the whole line, but then would you need to remove the [] part into something else. Although I have not tried it yet the search function yet, just thinking about the find function you are using and if it will do what you want.

To work with the "load" function in "main" I did this:
1
2
3
4
5
6
7
8
9
10
11
12
int main()
{
    int result{};

    Dictionary_part01 function;

    if (result = function.loadDictionary())
        return result;

    int choice;

    do

Lines 7 and 8 will deal with the return value of the function. Should it be something other than (0)zero you leave the program to fix the problem. Otherwise you continue with the program.

One other thing I did is set up you menu as:
1
2
3
4
5
6
7
8
cout << 
    "Welcome to my Dictionary program!\n"
    "----------------------------------\n"
    "Please select an option from the menu:\n"
    "1. Enter a word to search\n"
    "2.Find words with more than three Zs\n"
    "3.List all words that have a q without a following u\n"
    "4. Quit\n";

I find this layout much easier to work with and it also has the advantage of looking like what is put on the screen.

On line I noticed it line 2. Longer than the 1st line, but not long enough to cover the longest line. If you make line 2 longer you could center line 1 over it.

Right now it is a bit difficult to read the complete file and test the program not knowing how you want to handle the definition.

Andy
Hey Andy,

thank you so much for the in depth feedback, Its great to have it explained in such detail!
So now all i need to do is figure out a way of storing the definition so that it can be returned when the user searches for a word,
and complete the setters for both classes.

Thank you to yourself and Seeplus for responding to my questions, it's helped me out alot
Hi Andy,

I cleaned up my code and i've got the function reading my file into the vector sorted so that it omits the white space between the entries.

I'm confused as to how to set each element to the word / definition objects of the Word class. Should this be done during the same while loop in the loadDictionary function? or should that be done in the searchVector function? should it iterate over the vector, looking for the specified string, save the element to the word object, the following element to the def object, and then print them both?

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

class Word
{
private:
	//attributes
	string word;
	string def;
public:
	//methods
	void setWord(string w)
	{
		word = w;
	}
	void setDef(string d)
	{
		def = d;
	}
	string getWord()
	{
		return word;
	}
	string getDef()
	{
		return def;
	}
};

class Dictionary_part01
{	
private:
	vector<string> word;
public:
	/*void vectorSize()
	{
		cout << wordList.size() << endl;
	}*/
	void searchVector(string v)
	{
		if (find(word.begin(), word.end(), v) != word.end())
			cout << "Word found!" << endl;
		else
			cout << "Word not found" << endl;
	}
	//setters
	//loadDictionary function
	int loadDictionary()
	{
		Word set;
		const string myfile{ "dictionary2021.txt" }; 
		ifstream dict(myfile);  //Open file for reading 
		if (!dict)
		{
			cout << "Error reading file :( Please restart the program\n";
			return 4;  //Exit program if file fails to read 
		}
		string words;
        cout << "Attempting to read Dictionary....\n";
		while (getline(dict, words))
		{
			if (words != "")
			word.push_back(words);
		}
		return 0;  //everything is OK.
	}
};

int main()
{
	string value;
	Dictionary_part01 function;
	Word operators;
	function.loadDictionary();
	//function.vectorSize();
	int choice;
	do
	{
		cout <<
			"       Welcome to my Dictionary program!\n"
			"----------------------------------------------------\n"
			"     Please select an option from the menu:\n"
			"----------------------------------------------------\n"
			"1.Enter a word to search\n"
			"2.Find words with more than three Zs\n"
			"3.List all words that have a q without a following u\n"
			"4. Quit\n";
		cin >> choice;
		switch (choice)
		{
		case 1:
			cout << "Enter your word: \n";
			cin >> value;
			function.searchVector(value);
			return 0;
		case 2:
			cout << "Lets have a look!\n";
			return 0;
		case 3:
			cout << "This might be hard, lets find them!\n";
			return 0;
		case 4:
			cout << "Thanks for checking this out, see you next time!\n";
		}
	} 	
	while (choice!=4);
}
Last edited on
Hello ConfusedCoder90,

As I was working on your program this morning I came to the conclusion that the class Word is never used.

In your class "Dictionary_part01", not sure what the "part1" is for, you have a vector of strings for the word, but nothing for the type and definition. One thought would be to have a vector for the "type" and a 3rd for the "definition". A better choice would be std::vector<Word> dictionary;. The variables name can be whatever you like.

This will make use of the "Word" class and only need 1 vector. I would also suggest writing an overloaded ctor for "Word" and using the ".emplace_back" function to load the vector. The ".emplace_back" function will use the overloaded ctor to create an object of "Word" 1st before it puts it into the vector.

Playing around I did come up with this:
1
2
3
4
size_t pos = words.find('[');

wordList.push_back(words.substr(0, pos - 1));
mTypeList.push_back(words.substr(pos));

That is more for an example of breaking up a word and its type. If you use a vector of class "Word" you could use the "substr" to set a variable although it should work in the () of the ".emplace_back" function.

I could change the design of the program, but I am looking for your input of what you had in mint at the start and what you would like to do.

Andy
Without using a class and using a map instead of a vector, as a first step consider:

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <fstream>
#include <iostream>
#include <string>
#include <map>

struct Word {
	std::string type;
	std::string def;
};

struct Def {
	std::string name;
	Word word;
};

using Dict = std::map<std::string, Word>;

int getInt(const std::string& prm)
{
	int i {};

	while ((std::cout << prm) && (!(std::cin >> i) || std::cin.peek() != '\n')) {
		std::cout << "Not an integer\n";
		std::cin.clear();
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
	}

	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
	return i;
}

std::istream& operator>>(std::istream& is, Def& def)
{
	std::string line;

	for (; is && line.empty(); getline(is, line));

	const auto t {line.find(" [")};

	if (t != std::string::npos) {
		const auto te {line.find(']', t + 1)};

		def.name = line.substr(0, t);
		def.word.type = line.substr(t + 2, te - t - 2);

		std::getline(is, def.word.def);	// Definition is on one line
	}

	return is;
}

bool readdict(Dict& dict)
{
	std::ifstream ifs("dictionary.txt");

	if (!ifs)
		return false;

	for (Def def; ifs >> def; dict[def.name] = def.word);

	return true;
}

auto dictsearch(const std::string& value, const Dict& dict)
{
	return dict.find(value);
}

int main()
{
	Dict dict;

	if (!readdict(dict))
		return (std::cout << "Cannot open file\n"), 1;

	/*
	for (const auto& w : dict) {
		std::cout << w.first << "  " << w.second.type << '\n';
		std::cout << w.second.def << "\n\n";
	}
	*/

	int choice {};

	do {
		std::cout <<
			"\n       Welcome to my Dictionary program!\n"
			"----------------------------------------------------\n"
			"     Please select an option from the menu:\n"
			"----------------------------------------------------\n"
			"\n1. Enter a word to search\n"
			"2. Find words with more than three Zs\n"
			"3. List all words that have a q without a following u\n"
			"4. Quit\n";

		choice = getInt("\nEnter option: ");

		switch (choice) {
			case 1:
			{
				std::string value;

				std::cout << "Enter your word: ";
				std::getline(std::cin, value);

				if (const auto itr {dictsearch(value, dict)}; itr != dict.end())
					std::cout << "Type is " << itr->second.type << '\n' << itr->second.def << "\n\n";
				else
					std::cout << "Not found\n";
			}
				break;

			case 2:
				std::cout << "Lets have a look!\n";
				break;

			case 3:
				std::cout << "This might be hard, lets find them!\n";
				break;

			case 4:
				std::cout << "Thanks for checking this out, see you next time!\n";
				break;

			default:
				std::cout << "Invalid option\n";
				break;
		}
	} 	while (choice != 4);
}

Hello ConfusedCoder90,

A helpful tip:

When you make your 1st post include the full instructions that you were given. If necessary follow that with what the assignment is about and what it should cover based on what you have learned. This may not keep you from getting suggestions beyond what you have learned so fat, but it helps.

Along with that any input file that is needed, if large a good sample will work. Any part of the input file that is giving you a problem should be in the sample.

I did not see your last post until I finished mine and refreshed the page.

Looking at your code this is what I did:
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <iostream>
#include <string>
#include <vector>

#include <fstream>
#include <algorithm>

using namespace std;  // <--- Best not to use.

class Word
{
    private:
        //attributes
        string mWord;  // <--- Changed.
        string mDef;   // <--- Changed.

    public:
    //methods
        void setWord(string word)  // <--- Changed.
        {
            mWord = word;  // <--- Changed.
        } 

        void setDef(string definition)
        {
            mDef = definition;
        } 

        // <--- What about type? The part [type].

        string getWord()
        {
            return mWord;
        } 

        string getDef()
        {
            return mDef;
        }
};

class Dictionary_part01
{
    private:
        vector<string> word;
        // <--- Maybe std::vector<Word> dictionary;

    public:
        /*void vectorSize()
        {
            cout << wordList.size() << endl;
        }*/

        void searchVector(string v)
        {
            if (find(word.begin(), word.end(), v) != word.end())
                cout << "Word found!" << endl;
            else
                cout << "Word not found" << endl;
        }

        //setters

        //loadDictionary function
        int loadDictionary()
        {
            Word set;

            const string inFileNameDict{ "dictionary2021.txt" };  // <--- Changed.

            ifstream inFileDict(inFileNameDict);  //Open file for reading   // <--- Changed.

            if (!inFileDict)  // <--- Changed.
            {
                cout << "Error reading file :( Please restart the program\n";

                return 4;  //Exit program if file fails to read 
            }

            string words;

            cout << "Attempting to read Dictionary....\n\n";  // <--- Changed. Added a \n.

            while (getline(inFileDict, words))
            {
                if (words != "")
                    word.push_back(words);
            }

            return 0;  //everything is OK.
        }
};

int main()
{
    string value;

    Dictionary_part01 function;

    Word operators;

    function.loadDictionary();

    //function.vectorSize();

    int choice;

    do
    {
        cout <<
            "       Welcome to my Dictionary program!\n"
            "----------------------------------------------------\n"
            "     Please select an option from the menu:\n"
            "----------------------------------------------------\n"
            "1.Enter a word to search\n"
            "2.Find words with more than three Zs\n"
            "3.List all words that have a q without a following u\n"
            "4. Quit\n";
        cin >> choice;

        switch (choice)
        {
            case 1:
                cout << "Enter your word: \n";
                cin >> value;

                function.searchVector(value);

                break;  //return 0;  // <--- Bad idea. Should be a break and then let the while condition end the program.
            case 2:
                cout << "Lets have a look!\n";

                return 0;
            case 3:
                cout << "This might be hard, lets find them!\n";

                return 0;
            case 4:
                cout << "Thanks for checking this out, see you next time!\n";

            // <--- No default for invalid choice.
        }
    } while (choice != 4);
}

My point here that a few blank lines make the code more readable and along some good variable names more understandable. The variable names are just a suggestion. Its the idea that counts.

Try to avoid single letter variable names. It may be quick and easy, but 6 months from now you will have no idea what they mean.

Line 46 is a suggestion of how you could make use of the "Word" class.

Line 98 should use a better name than "function"

Line 102 should be written:
102
103
if (result = function.loadDictionary())
    return result;

This makes use of the return value of the function. Otherwise you program would continue even if it should not.

As you look over the code be sure to read the comments.

Andy
Hey guys,

thank you both so much for getting back to me again, i really appreciate all of the information.

This was from an assignment for a unit I had failed last semester, I'm retaking it again next semester but wanted to take the break in between to wrap my head around this. I even went as far as a course on Udemy, which is helpful but doesn't really cover what I need.

This is the assignment I failed to complete;

Write a program that when executed will parse the dictionary file, dictionary2021.txt,
provided with this assignment. It will load each record from the file into a new instance of a
Word class and add this instance to a list of Word objects contained in an instance of a
Dictionary class. Your software will then display a menu of tasks it can perform. It will then prompt
the user to enter a number corresponding to one of the following menu items:
Basic Tasks
1. Prompt the user to enter a word. If that exact word is in the dictionary, print the word’s
name, the word type using the following scheme: Noun (n.), Verb (v.), Adverb (adv.),
Adjective(adj.), Preposition(prep) MiscWords(misc.),ProperNouns (pn.), NounAndVerb (n.
v.), and the word’s definition. If the word is not in the dictionary print ‘word not found.’

a. For words with multiple definitions, these should be separated with a line-break.
b. Proper nouns should have their word name capitalised.
2. Find the word(s) with more than three ‘z’’s
3. List the words that have a 'q' without a following 'u' eg 'Iraqi'

Once a task has been executed, the program should return to the main menu.


It also explicitly states i should use a Word Class and a Dictionary Class

As you can see my idea was to load them all from the .txt file into a vector and then do simple operations on the elements within. I'd done a similar assignment about a year ago in Python. But the concept of Classes and OOP confuses me alot
Perhaps something like this. Word is a struct, not a class but if Word has to be a class, that's easily changed - but it's not really necessary.

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#include <fstream>
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>

const std::map<std::string, std::string> types {{"n", "Noun"}, {"v", "Verb"}, {"adv", "Adverb"}, {"adj", "Adjective"},
	{"prep", "Preposition"}, {"misc", "MiscWords"}, {"pn", "ProperNouns"}, {"nv", "NounAndVerb"}};

class Dictionary {
public:
	Dictionary(const std::string& fnam) {
		readdict(fnam);
	}

	const auto& dictsearch(const std::string& value) const
	{
		return dict.find(value);
	}

	size_t noWords() const {
		return dict.size();
	}

	auto endPos() const {
		return dict.end();
	}

	const auto& zzzs() const {
		return zzz;
	}

	const auto& Notqu() const {
		return notqu;
	}

private:
	struct Word {
		std::string type;
		std::string def;
	};

	struct Def {
		std::string name;
		Word word;
	};

	using Dict = std::map<std::string, Word>;
	using mitr = Dict::const_iterator;
	using Found = std::vector<mitr>;

	Dict dict;
	Found zzz;
	Found notqu;

	bool readdict(const std::string& fnam)
	{
		std::ifstream ifs(fnam);

		if (!ifs)
			return false;

		for (Def def; ifs >> def; ) {
			const auto& nam {def.name};
			const auto itr {dict.emplace(nam, def.word)};

			if (std::count(nam.begin(), nam.end(), 'z') >= 3)
				zzz.emplace_back(itr.first);

			for (size_t c = 0; c < nam.size(); ++c)
				if (nam[c] == 'q' && (c == nam.size() - 1 || nam[c + 1] != 'u')) {
					notqu.emplace_back(itr.first);
					break;
				}
		}

		return true;
	}

	friend std::istream& operator>>(std::istream& is, Def& def)
	{
		std::string line;

		for (; is && line.empty(); getline(is, line));

		if (const auto t {line.find(" [")}; t != std::string::npos) {
			const auto te {line.find(']', t + 1)};

			def.name = line.substr(0, t);
			def.word.type = line.substr(t + 2, te - t - 2);

			std::getline(is, def.word.def);	// Definition is on one line
		}

		return is;
	}
};

int getInt(const std::string& prm)
{
	int i {};

	while ((std::cout << prm) && (!(std::cin >> i) || std::cin.peek() != '\n')) {
		std::cout << "Not an integer\n";
		std::cin.clear();
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
	}

	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
	return i;
}

void showDef(const Dictionary& dict, const std::string& value)
{
	if (value.empty())
		return;

	if (const auto& itr {dict.dictsearch(value)}; itr != dict.endPos()) {
		std::cout << '\n';

		if (itr->second.type == "pn") {
			std::cout << static_cast<char>(std::toupper(static_cast<unsigned char>(value[0])));
			std::cout << value.substr(1);
		} else
			std::cout << value;

		if (const auto fnd {types.find(itr->second.type)}; fnd != types.end())
			std::cout << " [" << fnd->second << "]\n";
		else
			std::cout << " [Unknown type]\n";

		size_t pos {}, nl {};

		do {
			nl = itr->second.def.find("; ", pos);
			std::cout << itr->second.def.substr(pos, nl == std::string::npos ? nl : nl - pos) << '\n';
			pos = nl + 2;
		} while (nl != std::string::npos);

		std::cout << '\n';
	} else
		std::cout << "\nWord not found\n";
}

int main()
{
	Dictionary dict("dictionary.txt");

	if (dict.noWords() == 0)
		return (std::cout << "Cannot open file\n"), 1;

	int choice {};

	do {
		std::cout <<
			"\n       Welcome to my Dictionary program!\n"
			"----------------------------------------------------\n"
			"     Please select an option from the menu:\n"
			"----------------------------------------------------\n"
			"\n1. Enter a word to search\n"
			"2. Find words with more than three Zs\n"
			"3. List all words that have a q without a following u\n"
			"4. Quit\n";

		choice = getInt("\nEnter option: ");

		switch (choice) {
			case 1:
			{
				std::string value;

				std::cout << "Enter your word: ";
				std::getline(std::cin, value);

				showDef(dict, value);
			}
			break;

			case 2:
				std::cout << '\n';

				if (const auto& zzz {dict.zzzs()}; !zzz.empty())
					for (const auto& z : zzz)
						std::cout << z->first << '\n';
				else
					std::cout << "There are no such words!\n";

				break;

			case 3:
				std::cout << '\n';

				if (const auto& notqu {dict.Notqu()}; !notqu.empty())
					for (const auto& q : notqu)
						std::cout << q->first << '\n';
				else
					std::cout << "There are no such words!\n";

				break;

			case 4:
				std::cout << "Thanks for checking this out, see you next time!\n";
				break;

			default:
				std::cout << "Invalid option\n";
				break;
		}
	} while (choice != 4);
}

Hey Seeplus,

This returned the following errors, I tried playing around with it a bit but just kept creating more errors lol

Error (active) E0018 expected a ')' ConsoleApplication1 line 196

Error (active) E0018 expected a ')' ConsoleApplication1 line 87

Error (active) E0711 expression must have bool type (or be convertible to bool) ConsoleApplication1 line 119

Error (active) E0018 expected a ')' ConsoleApplication1 line 119

Error (active) E0711 expression must have bool type (or be convertible to bool) ConsoleApplication1 line 129

Error (active) E0018 expected a ')' ConsoleApplication1 line 129

Error (active) E0711 expression must have bool type (or be convertible to bool) ConsoleApplication1 line 185

Error (active) E0018 expected a ')' ConsoleApplication1 line 185

Error (active) E0711 expression must have bool type (or be convertible to bool) ConsoleApplication1 line 196
You need to compile as C++17. The code above compiles and runs OK as C++17 with VS2019.
Last edited on
Hi guys,

i modified my code so now my vector stores Word Objects as word and def correctly. It doesn't include the white space lines in between either. Its probably messy. My issue now is i can't seem to be able to make a function that searches the vector for an input value and returns the location of that value. I've tried toying around with Find and Find_if, but i usually end up with errors using != and ==.

I'm currently stuck on;
1
2
3
4
string searchVector(string v)
	{
		vector<string>::iterator result;
		auto result = find_if(word.begin(), word.end(), v);


am i heading in the right direction? or nowhere near it?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bool loadDictionary()
	{
		Word* w1 = new Word;
		const string myfile{ "dictionary2021.txt" }; 
		ifstream dict(myfile);  //Open file for reading 
		if (!dict)
		{
			cout << "Error reading file :( Please restart the program\n";
			return false;  //Exit program if file fails to read 
		}
		string words;
		string defs;
		while (!dict.eof())
		{
			getline(dict, words);
			w1->setWord(words);
			getline(dict, defs);
			w1->setDef(defs);
			word.push_back(*w1);
			dict.ignore();
		}
		return true;  //everything is OK.
	}
Hello ConfusedCoder90,

Add some blank lines and make you code easier to read.
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
bool loadDictionary()
{
    Word* w1 = new Word;

    const string myfile{ "dictionary2021.txt" };

    ifstream dict(myfile);  //Open file for reading 

    if (!dict)
    {
        cout << "Error reading file :( Please restart the program\n";
        return false;  //Exit program if file fails to read. Would work better as "true".
    }

    string words;
    string defs;

    while (!dict.eof())  // <--- Does not work the way that you are thinking.
    {
        getline(dict, words);

        w1->setWord(words);

        getline(dict, defs);

        w1->setDef(defs);

        word.push_back(*w1);

        dict.ignore();
    }

    return true;  //everything is OK. Would work better as "false".
}

Using a "bool" as the return value of the function is OK, but what is missing is the function call. I do not know how you are using the return value. Also I would reverse the return statements.

The return at the end of "main" would return (0)zero if everything is OK and a number other than (0) if there is a problem. Usually this number is a positive number.

Your while loop does not work the way that you are thinking. First the condition checks if "eof" is set then you enter the loop and try a read that sets "eof", but you continue to process a blank record.

For dealing with a file of unknown length a while loop is written as: while (getline(dict, words)). This way when the read sets "eof" the condition fails and you finish the loop.

Your function uses "new" to create some memory, but somewhere when you are finished with it you need to use "delete" for free the memory. Otherwise you have a memory leak and it mey not take many runs before you are out of memory.

If done correctly you should not have to use "new" in the program.

I will have to review the program to see what was. With the changes that you have made I will have to see how they fit.

Andy
1
2
3
4
5
6
7
vector<string>::iterator result;
		auto result = find_if(word.begin(), word.end(), v);

	vector<string>::iterator result;
		auto result = find_if(word.begin(), word.end(), v);

	


This needs to be:

 
auto result = find_if(word.begin(), word.end(), [&v](const auto& w) {return w.getWord() == v; });


What are you going to return as string from search_vector()? It's def or an empty string is not found?

1
2
3
4
5
6
string searchVector(const string& v)
{
	auto result {find_if(word.begin(), word.end(), [&v](const auto& w) {return w.getWord() == v; })};

	return result != word.end() ? result->getDef() : "";
}


Based upon your data structurers, loadDictionary would be something like (not tried) with a revised Word class:

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
class Word
{
private:
	//attributes
	string word;
	string def;
public:
	//methods
	Word() {}
	Word(const string& w, const string& d) : word(w), def(d) {}

	void setWord(const string& w) { word = w; }
	void setDef(const string& d) { def = d; }
	string getWord() const { return word; }
	string getDef() const { return def; }
};

bool loadDictionary()
{
	const string myfile {"dictionary2021.txt"};
	ifstream dict(myfile);  //Open file for reading

	if (!dict) {
		cout << "Error reading file :( Please restart the program\n";
		return false;  //Exit program if file fails to read
	}

	for (string words, defs; getline(dict, words) && getline(dict, defs); dict.ignore())
		word.emplace_back(words,defs);

	return true;  //everything is OK.
}

Last edited on
Hello ConfusedCoder90,

I have come up with a great idea.

Given the instructions:

Write a program that when executed will parse the dictionary file, dictionary2021.txt,
provided with this assignment.

1. It will load each record from the file into a new instance of a Word class and add this instance to a list of Word objects
   contained in an instance of a Dictionary class.

2. Your software will then display a menu of tasks it can perform.
  a. It will then prompt the user to enter a number corresponding to one of the following menu items:

Basic Tasks
3. Prompt the user to enter a word.
   If that exact word is in the dictionary, print the word’s
     name, the word type using the following scheme:
       Noun (n.), Verb (v.), Adverb (adv.), Adjective(adj.), Preposition(prep) MiscWords(misc.),ProperNouns (pn.), NounAndVerb (n.v.),
       and the word’s definition.
   If the word is not in the dictionary print ‘word not found.’

  a. For words with multiple definitions, these should be separated with a line-break.
  b. Proper nouns should have their word name capitalised.

4. Find the word(s) with more than three ‘z’’s
5. List the words that have a 'q' without a following 'u' eg 'Iraqi'

Once a task has been executed, the program should return to the main menu.


Let's start at 5 and work backwards.

Or you can concentrate on reading the file and properly storing the information for later use.

Based on 1 you have created the necessary "Word" class, but it is not complete. You have created the necessary "Dictionary" class, you are not using it correctly.

I would work on getting the classes correct then load the file using both classes ad you need to.

Until this is working how can you search for something that is not there? And what code you started with for the search may not work.

For the "Word" class this is what I am using:
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
class Word
{
    private:
        //attributes
        string mWord;       // <--- Changed.
        std::string mType;  // <--- Added.
        string mDef;        // <--- Changed.

    public:
    //methods
        // <--- Default and overloadedd ctors.
        Word() {}
        Word(std::string word, std::string type, std::string definition) :mWord(word), mType(type), mDef(definition) {}

        void setWord(string word)
        {
            mWord = word;
        } 

        void setDef(string definition)
        {
            mDef = definition;
        } 

        // <--- What about type? The part [type].

        string getWord()  // <--- This function is used, but the others are not, but they still need to be there
        {
            return mWord;
        } 

        string getDef()
        {
            return mDef;
        }

        void PrintResults()const
        {
            std::cout <<
                "\n" << mWord << ' '
                << mType << "\n\n"
                << mDef << "\n\n";
        }
};


And the "Dictionary" class starts with:
1
2
3
4
5
class Dictionary_part01
{
    private:
        //vector<string> word;
        std::vector<Word> dictionary;


Then in the load function I would read "a [misc]" and split that into "word" "a" and "type" "misc". I think loosing the []s would work better. Especially the output would have to change the []s to ().

I have not worked on printing the definition yet, but there is more involved there than just a "cout << definition;".

I do not know if you have studied "enum"s yet, but I had a thought that it might be useful.

Andy
Pages: 12