Call to function is ambiguous in C++. Candidate functions are the Prototype and the function itself - c++

I am working through Stanford CS106B C++ assignments and I have a 'semantic issue' with an assignment.
It seems as if the compiler cannot deduce whether the call is to a function or to the prototype of the function. I don't understand why a call would ever be made to the prototype. How can I make it so that the call is made to the function rather than the prototype? The error message I get it "Call to 'humansTurn' is ambiguous".
The error messages relate to the calls of the humansTurn(Lexicon,Lexicon) function, within the humansTurn(Lexicon,Lexicon) function, at the bottom of the page. The prototype for this function is above the main function.
Any help would be greatly appreciated.
Kind regards,
Mehul
/*
* File: Boggle.cpp
* ----------------
*/
#include <iostream>
#include "gboggle.h"
#include "graphics.h"
#include "grid.h"
#include "vector.h"
#include "lexicon.h"
#include "random.h"
#include "simpio.h"
using namespace std;
/* Constants */
const int BOGGLE_WINDOW_WIDTH = 650;
const int BOGGLE_WINDOW_HEIGHT = 350;
const string STANDARD_CUBES[16] = {
"AAEEGN", "ABBJOO", "ACHOPS", "AFFKPS",
"AOOTTW", "CIMOTU", "DEILRX", "DELRVY",
"DISTTY", "EEGHNW", "EEINSU", "EHRTVW",
"EIOSST", "ELRTTY", "HIMNQU", "HLNNRZ"
};
const string BIG_BOGGLE_CUBES[25] = {
"AAAFRS", "AAEEEE", "AAFIRS", "ADENNN", "AEEEEM",
"AEEGMU", "AEGMNN", "AFIRSY", "BJKQXZ", "CCNSTW",
"CEIILT", "CEILPT", "CEIPST", "DDLNOR", "DDHNOT",
"DHHLOR", "DHLNOR", "EIIITT", "EMOTTT", "ENSSSU",
"FIPRSY", "GORRVW", "HIPRRY", "NOOTUW", "OOOTTU"
};
/* Function prototypes */
void welcome();
void giveInstructions();
// Create random board
static Grid <char> randomBoard();
// Create custom board
static Grid<char> customBoard();
static void drawAndFillBoard(Grid<char>);
static void humansTurn(Lexicon,Lexicon);
int main() {
initGraphics(BOGGLE_WINDOW_WIDTH, BOGGLE_WINDOW_HEIGHT);
welcome();
giveInstructions();
string custom = getLine("Type y to create custom board:" );
Grid<char> gridData;
if (custom=="y"){
gridData = customBoard();
} else {
gridData = randomBoard();
}
drawAndFillBoard(gridData);
Lexicon english("EnglishWords.dat");
// Lexicon holds words previously encountered
Lexicon previousWords;
humansTurn(english, previousWords);
return 0;
}
/*
* Function: welcome
* Usage: welcome();
* -----------------
* Print out a cheery welcome message.
*/
void welcome() {
cout << "Welcome! You're about to play an intense game " << endl;
}
/*
* Function: giveInstructions
* Usage: giveInstructions();
* --------------------------
* Print out the instructions for the user.
*/
void giveInstructions() {
cout << endl;
cout << "The boggle board is a grid onto which I ";
cout << "or triple your paltry score." << endl << endl;
cout << "Hit return when you're ready...";
getLine();
}
static Grid<char> randomBoard(){
Vector<string> standardCubes;
for(int i = 0; i<16;i++){
standardCubes.add(STANDARD_CUBES[i]);
}
// Shuffle cubes
for (int i = 0; i < standardCubes.size(); i++) {
int r = randomInteger(i, standardCubes.size()-1);
if (i!=r){
string stringToMove1 = standardCubes.get(i);
string stringToMove2 = standardCubes.get(r);
standardCubes.set(r, stringToMove1);
standardCubes.set(i, stringToMove2);
}
}
// Update grid with random side of cube
Grid<char> gridData(4, 4);
int counter = 0;
for (int columnNo = 0; columnNo <4; columnNo++){
for (int rowNo = 0; rowNo<4; rowNo++) {
string s = standardCubes.get(counter);
int r = randomInteger(0, 5);
gridData[columnNo][rowNo] = s[r];
counter++;
}
}
return gridData;
}
static Grid<char> customBoard(){
Grid<char> gridData(4,4);
string s = getLine("Please enter 16 characters to make up the custom board. Characters will fill the board left to right, top to bottom: ");
for (int i = 0; i < s.length(); i++) {
s[i] = toupper(s[i]);
}
if (s.length()<16){
cout << "String has to be 16 characters long, try again" << endl;
customBoard();
}
int i =0;
for (int columnNo = 0; columnNo <4; columnNo++){
for (int rowNo = 0; rowNo<4; rowNo++) {
gridData[columnNo][rowNo] = s[i];
i++;
}
}
return gridData;
}
static void drawAndFillBoard(Grid<char> gridData){
drawBoard(4, 4);
for (int columnNo = 0; columnNo <4; columnNo++){
for (int rowNo = 0; rowNo<4; rowNo++) {
labelCube(rowNo, columnNo, gridData[rowNo][columnNo]);
}
}
}
static void humansTurn(Lexicon englishWords, Lexicon &previousWords){
/*
Human’s turn (except for finding words on the board). Write the loop that allows the user to enter words. Reject words that have already been entered or that don’t meet the minimum word length or that aren’t in the lexicon. Use the gboggle functions to add words to the graphical display and keep score.
*/
string humanGuess = getLine("Please enter your guess: ");
for (int i = 0; i < humanGuess.length(); i++) {
humanGuess[i] = tolower(humanGuess[i]);
}
if (humanGuess.length()<4){
cout << "Min guess length is four characters" << endl;
humansTurn(englishWords, previousWords);
}
if (!englishWords.contains(humanGuess)) {
cout << "That word is not English, please try another word" << endl;
humansTurn(englishWords, previousWords);
}
if (previousWords.contains(humanGuess)){
cout << "That word has already been guessed, please try another word" << endl;
humansTurn(englishWords, previousWords);
}
// check if word can be made using data on board
}

Your function humansTurn definition has different signature with declaration
function declaration:
static void humansTurn(Lexicon,Lexicon);
Function definition:
static void humansTurn(Lexicon englishWords, Lexicon &previousWords)
^^
//Here

Related

c++ String returning with an extra char

I have tested my program and am certain right before being returned the string in my function equals "card001". But the returned value equals "card0011". I have no idea how this even happens. Help me before I lose my mind. ;)
std::string function_cardTexture(int card) {
//removes the last 1
card = card - 10000;
int ctr = 0;
card = floor(card / 10);
std::cout << card << std::endl;
//turn int card into a string
std::string a = static_cast<std::ostringstream*>(&(std::ostringstream() << card))->str();
//combines card and string a into one string
std::string nametext = "card00" + a;
std::cout << nametext << std::endl;
return (nametext);
}
void function_Battle(tempPlayer &Player, tempCard &card001) {
if (Player.Start == true) {
//Draw hand
for (int i = 0; i < Player.numDrawn; i++) {
int x = rand() % Player.deckSize + 0; ;
Player.Hand[i] = Player.Deck[x];
Player.Discarded[x] = 1;
}
Player.Start = false;
}
std::map<std::string, tempCard> Vars;
//draw hand
for (int i = 0; i < Player.handMax;i++) {
if (Player.Hand[i] != 0) {
sf::RectangleShape Card(sf::Vector2f(80.0f, 128.0f));
std::string nametext = function_cardTexture(Player.Hand[i]);
std::cout << nametext;
sf::Texture texture = Vars[nametext].Art;
Card.setTexture(&texture);
window.draw(Card);
}
}
}
Your problem is how you're printing things out without a newline in the function_Battle() function, so you're likely "smashing together" your new value with an old one. If you replace your main function with just a loop with clearer printing of values, you can see you don't have a problem:
http://coliru.stacked-crooked.com/a/8d1e4f51643b84b9
That link will go to an online compiler where I just replaced the calling function with a loop that makes numbers. It even supplies a negative one.

Shopping List program: In VIM "Segmentation fault (core dumped)", but Codeblocks works [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Hope your day is going well.
I am a bit of a noobie when it comes to programming so please bear with me. I have two problems. I am attempting to create a program consisting of 5 files: items.h, items.cpp, list.h, list.cpp, and main. There is an Item class and a List class. The object of this program is to create a shopping list that allows the user to enter an Item Name, the Item Unit, cost per Unit, and then add it to the list. The program also allows you to remove an item by its name. We cannot use vectors.
Problem 1: What I have so far will run in Codeblocks, but when I run it in VIM, I get the error "Segmentation fault (core dumped)."
Problem 2: I also come across an error when I attempt to add another variable to use in main, such as amountToBuy (contains the int number of Items user wants to buy)--when added, the program in Codeblocks won't run, stating "std::bad_alloc". I've commented some things out so the program will run.
I am at a complete loss and don't know which lines are causing the issues or how I would go about fixing things. Any input would be greatly appreciated. Thank you very much!
list.h
#ifndef LIST_H_INCLUDED
#define LIST_H_INCLUDED
#include "items.h"
#include <string>
class List
{
private:
int arrayPosition;
int arraySize;
Item* itemsOnList = new Item[arraySize];
public:
List();
void addItem(Item);
void removeItem(std::string ri);
void displayList();
};
#endif // LIST_H_INCLUDED
list.cpp
#include "list.h"
#include "items.h"
#include <string>
#include <iostream>
/*******************************************************************
List::List()
Constructor initializes List size to 4 as default
*******************************************************************/
List::List()
{
arraySize = 4;
arrayPosition = 0;
}
/*******************************************************************
void List::addItem(Item)
This function adds the specified Item to the List
*******************************************************************/
void List::addItem(Item i)
{
//x2 arraySize when arrayPosition gets too close to arraySize
if (arrayPosition == arraySize)
{
//doubling arraySize since we need more space
arraySize *= 2;
//tempList to hold the old List's items
Item* tempList = new Item[arraySize];
//transferring information to tempList
for (int a = 0; a < arrayPosition; a++)
{
tempList[a] = itemsOnList[a];
}
delete[] itemsOnList;
//transferring data from temp List back to Old list
itemsOnList = tempList;
delete[] tempList;
//adding next item to list
itemsOnList[arrayPosition++] = i;
}
else
{
//adding next item to list
itemsOnList[arrayPosition++] = i;
}
}
/*******************************************************************
void List::removeItem(std::string)
This function removes the specified Item to the List
*******************************************************************/
void List::removeItem(std::string ri)
{
for (int a = 0; a < arrayPosition; a++)
{
if (itemsOnList[a].getItemName() == ri)
{
//moving the rest of the items down one position
//to take the removed item's spot
for (int b = a; b < arrayPosition; b++)
{
itemsOnList[b] = itemsOnList[b+1];
}
//decreasing arrayPosition by one because Item was removed
--arrayPosition;
}
}
}
/*******************************************************************
void List::displayList()
This function displays the List
*******************************************************************/
void List::displayList()
{
std::cout << "The following Items are on your Grocery List\n\n";
for (int i = 0; i < arrayPosition; i++)
{
std::cout << "Item name: " << itemsOnList[i].getItemName() << std::endl;
//std::cout << "Number to buy: " << itemsOnList[i].getNumberToBuy() << std::endl;
}
std::cout << std::endl;
}
items.h
#ifndef ITEMS_H_INCLUDED
#define ITEMS_H_INCLUDED
#include <string>
class Item
{
private:
std::string itemName;
//int numberToBuy;
public:
Item();
Item(std::string);
//setters
void setItemName(std::string);
//void setNumberToBuy(int);
//getters
std::string getItemName();
};
#endif // ITEMS_H_INCLUDED
items.cpp
#include "items.h"
Item::Item()
{
itemName = "empty";
//numberToBuy = 0;
}
//this constructor accepts a string and an int
Item::Item(std::string in)
{
itemName = in;
//numberToBuy = ntb;
}
//setters
void Item::setItemName(std::string in)
{
itemName = in;
}
/*
void Item::setNumberToBuy(int ntb)
{
numberToBuy = ntb;
}
*/
//getters
std::string Item::getItemName()
{
return itemName;
}
main.cpp
#include "list.h"
#include "items.h"
#include <iostream>
int main()
{
int menuChoice, subMenuChoice;
std::string itemName, removeItem;
bool exit = false;
List newList;
//introduction
std::cout << "Welcome to your Grocery List!\n\n";
do
{
//menu
std::cout << "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \n\n";
std::cout << "To select a menu item, please select its corresponding number.\n\n";
//menu prompts and storing the choice
std::cout << "1. Add items to Grocery List\n";
std::cout << "2. Remove items from Grocery List\n";
std::cout << "3. Display Grocery List\n";
std::cout << "4. Exit\n\n";
std::cout << "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \n\n";
std::cout << "Menu choice: ";
std::cin >> menuChoice;
std::cout << std::endl;
//menu choice break-away section
if (menuChoice == 1)
{
do
{
std::cout << "Please enter the name of the item: ";
std::cin >> itemName;
//std::cout << "Please enter the unit (cans, lbs, oz): ";
//std::cin >> itemUnit;
//std::cout << "Please enter number to buy: ";
//std::cin >> amountToBuy;
Item theItem(itemName);
newList.addItem(theItem);
std::cout << "Would you like to add another item? For YES type 1 | For NO type 0: ";
std::cin >> subMenuChoice;
std::cout << std::endl;
}
while(subMenuChoice == 1);
}
else if (menuChoice == 2)
{
std::cout << "Please enter the name of the item you want to remove: ";
std::cin >> removeItem;
std::cout << std::endl;
newList.removeItem(removeItem);
}
else if (menuChoice == 3)
{
newList.displayList();
}
else if (menuChoice == 4)
{
exit = true;
std::cout << "Goodbye!" << std::endl;
}
}
while (exit == false);
return 0;
}
In
class List
{
private:
int arrayPosition;
int arraySize;
Item* itemsOnList = new Item[arraySize];
public:
List();
void addItem(Item);
void removeItem(std::string ri);
void displayList();
};
Item* itemsOnList = new Item[arraySize]; will execute before the body of the constructor so by the time
List::List()
{
arraySize = 4;
arrayPosition = 0;
}
runs and arraySize is set to 4, itemsOnList has already been assigned an array of unknown size or the program has crashed.
A simple fix for this is
class List
{
private:
int arrayPosition;
int arraySize;
Item* itemsOnList;
public:
List();
void addItem(Item);
void removeItem(std::string ri);
void displayList();
};
and
List::List()
{
arraySize = 4;
arrayPosition = 0;
itemsOnList = new Item[arraySize]
}
or
List::List():
arrayPosition(0),
arraySize(4),
itemsOnList(new Item[arraySize])
{
}
The second uses the unfortunately under-taught Member Initializer List. This is often the best approach because it ensures that the object is fully constructed before entering the body of the constructor. For complex objects this prevents having to redo any work performed by default constructors that are used to make certain the object is valid before use.
Edit: A note on the Member Initializer List link above. The first third might look as though written in Martian. Skip down to the Explanation section and start reading there, then go back up to the specifics, if needed.
In addItem the following will also cause problems:
Item* tempList = new Item[arraySize]; //created new array
//transferring information to tempList
for (int a = 0; a < arrayPosition; a++)
{
tempList[a] = itemsOnList[a]; //copying old to new
}
delete[] itemsOnList; //free old list storage
//transferring data from temp List back to Old list
itemsOnList = tempList; // assign new list to old list
delete[] tempList; // whoops. Freed new list storage
For a brief period of time tempList and itemsOnList point to the same storage, so deleteing either pointer will free the storage for both. Solution: Don't delete[] tempList;
In RemoveItem:
for (int b = a; b < arrayPosition; b++)
{
itemsOnList[b] = itemsOnList[b+1];
}
b can range up to arrayPosition - 1, so itemsOnList[b+1] can be written as itemsOnList[arrayPosition-1+1] or as itemsOnList[arrayPosition]. arrayPosition may be one past the end of the end of the list if the list was full.
Your code has three stand-out issues.
No initialization of 'arraySize' and 'arrayPosition'.
You don't specify an initial value for 'arraySize' but you do specify
Item* itemsOnList = new Item[arraySize];
Because of the way you have specified this, at best it will always produce a zero-length (nullptr) itemsOnList, at worst it will use some uninitialized and thus random value to create a randomly sized array, and arrayPosition will also be randomly smaller or larger than the arraySize value.
size *= 2
if (arrayPosition == arraySize)
{
//doubling arraySize since we need more space
arraySize *= 2;
In the best-case scenario, your arraySize starts as zero. Thus when you double it, you get: zero.
Deletion of everything.
In addItem, you do the following:
delete[] itemsOnList;
//transferring data from temp List back to Old list
itemsOnList = tempList;
at this point, both itemsOnList and tempList point to the same array. So the next statement:
delete[] tempList;
deletes your second copy - now both the old and new arrays are deleted.

How can I trace back the error

I was assigned to create an array check (to see if the array is increasing, decreasing, or neither [then exiting if neither]) and a recursive binary search for one of my assignments. I was able to do these things after some help from my peers, but I need help in finding what seems to be causing the error
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Aborted
when running the code. I Googled this error and this error seems to be vague or I just am not understanding. It compiles without errors, but I need help in what finding what I did wrong. It is able to run without the binarySearchR function and its associating code, as the array check on its own was the previous assignment. Below is the code, and I thank you so much in advance!
#include <iosteam>
#include <string>
#include <cstdlib>
#include <fstream>
using namespace std;
int checkArraySort (string *fileLines, int numberOfLines);
int binarySearchR (string *fileLines, string searchKey, int iMin, int iMax);
int main ()
{
int numberOfLines = 0;
string searchKey = 0;
cout << "Input search key: ";
cin >> searchKey;
ifstream fileIn;
fileIn.open("words_in.txt");
string line;
if (fileIn.eof()) /* Checks file to see if it is blank before proceeding */
{
exit (EXIT_SUCCESS);
}
else
{
while(!(fileIn.eof()))
{
fileIn >> line;
numberOfLines++;
}
fileIn.close(); /* closes fileIn, need to reopen to reset the line location */
fileIn.open("words_in.txt");
string *fileInLines;
fileInLines = new string[numberOfLines];
for (int i = 0; i < numberOfLines; i++)
{
fileIn >> line;
fileInLines[i] = line;
}
fileIn.close(); /* closes fileIn */
int resultingCheck = checkArraySort(fileInLines, numberOfLines);
if (resultingCheck == -1)
{
cout << "The array is sorted in descending order." << endl;
}
else if (resultingCheck == 1)
{
cout << "The array is sorted in ascending order." << endl;
}
else
{
cerr << "ERROR: Array not sorted!" << endl;
exit (EXIT_FAILURE);
}
int searchResult = binarySearchR (fileInLines, searchKey, 0, numberOfLines);
if (!searchResult == -1)
{
cout << "Key found at index " << searchResult << "." << endl;
}
else
{
cout << "Key not found at any index." << endl;
}
exit (EXIT_SUCCESS);
}
}
int checkArraySort (string *fileLines, int numberOfLines)
{
int result = 1; /* Ascending by default */
for (int i = 1; i < numberOfLines; i++) /* Checks if decending */
{
if (fileLines[i] < fileLines[i-1])
{
result = -1;
}
}
if (result == -1) /* Makes sure it is descending (or if it is neither) */
{
for (int i = 1; i < numberOfLines; i++)
{
if (fileLines[i] > fileLines[i-1])
{
result = 0;
}
}
}
return result;
}
int binarySearchR (string *fileLines, string searchKey, int iMin, int iMax)
{
// so, its gotta look at the center value and each times, it discards half of the remaining list.
if (iMax < iMin) /* If the minimum is greater than the maximum */
{
return -1;
}
else
{
int iMid = (iMin + iMax) / 2;
if (fileLines[iMid] > searchKey) /* If the key is in the lower subset */
{
return binarySearchR (fileLines, searchKey, iMin, iMid - 1);
}
else if (fileLines[iMid] < searchKey) /*If the key is in the upper subset */
{
return binarySearchR (fileLines, searchKey, iMin, iMid + 1);
}
else /*If anything else besides the two */
{
return iMid;
}
}
}
The easy way: add a bunch of cout s to see where you program goes and what the values are.
Pros
Easy to do
Cons
Requires a recompile each time you want to add more info
The hard way: Learn to use a debugger
Pros
Can inspect "on the fly"
Don't need to rebuild
Can use what you learn in every other C++ program
Cons
Requires a bit of research to learn how to do it.

How to correctly create a ofstream of a struct vector? (abort() is called)

I'm currently building a game and in this part my goal is to update a previously created file of High Scores ("rank.txt")
To do so, I've created a couple of functions so they can read what's in the txt file and so it can update it. Though the reading is ok, while adding the update function it gives me an error and tells me abort() has been called.
void highScoresUpdate(vector<PlayerInfo> player)
{
// This function is responsible for updating the High Scores Table present in the RANK.TXT file
vector<HighScoresStruct> highScores_temp;
HighScoresStruct temp;
ofstream out_file_3("rank.txt");
highScores_temp = readHighScores("rank.txt");
for (int k = 0; k < player.size(); k++)
{
player[k].name = temp.name;
player[k].score = temp.score;
player[k].time = temp.time;
highScores_temp.push_back(temp);
}
sort(highScores_temp.begin(), highScores_temp.end(), compareByScore);
for (int i = 0; i < highScores_temp.size(); i++)
{
out_file_3 << highScores_temp[i].name << endl << highScores_temp[i].score << endl << highScores_temp[i].time << endl;
}
out_file_3.close();
}
For background information, so i don't spam this thread with code all you need to know is that readHighScores is the function responsible for extracting information from the txt file and placing it on a vector .
The structs and comparebyScore funtion are listed below.
bool compareByScore(const HighScoresStruct &a, const HighScoresStruct &b)
{
if (a.score < b.score)
return true;
else if (a.score == b.score)
{
if (a.time > b.time)
return true;
else
return false;
}
else
return false;
}
struct PlayerInfo
{
string name;
unsigned int score;
vector<char> hand;
bool inGame;
unsigned int time;
};
struct HighScoresStruct
{
string name;
unsigned int score;
unsigned int time;
};
So... Can anyone help me?

Dynamic Memory Allocation for Dictionary

Hi there I need to Build something like a dictionary and each word according to my code can have 100 meanings, but maybe it has only 5 meanings then I will be allocating 95 extra space for nothing or maybe it has more than 100 meanings then the program will crash, I know the vector class is very easy and could be good use of, but the task is almost building my own vector class, to learn how it works. Thus **meanings and some other stuff remain the same and here is my code, Also I know I am causing memory leakage, how can I delete properly? :
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
class Expression {
char *word_with_several_meanings; // like "bank", "class"
char **meanings; // a pointer to a pointer stores all meanings
int meanings_ctr; // meanings counter
//-----------FUNCTIONS------------------------------------------------
public:
void word( char* = NULL );
void add_meaning(char* = NULL);
char* get_word();
int get_total_number_of_meanings();
char* get_meaning(int meanx = 0);
Expression(int mctr = 0); // CTOR
~Expression(); // DTOR
};
Expression::Expression(int mctr ) {
meanings_ctr = mctr; // Setting the counter to 0
meanings = new char * [100]; // Allocate Space for 100 meanings
}
Expression::~Expression() {
delete [] meanings; // Deleting the memory we allocated
delete [] word_with_several_meanings; // Deleting the memory we allocated
}
void Expression::word( char *p2c )
{
word_with_several_meanings = new char[strlen(p2c)+1];
// copy the string, DEEP copy
strcpy(word_with_several_meanings, p2c);
}
void Expression::add_meaning(char *p2c)
{
//meanings = new char * [meanings_ctr+1];
meanings[meanings_ctr] = new char[strlen(p2c)+1];
strcpy(meanings[meanings_ctr++],p2c);
}
char * Expression::get_meaning( int meanx )
{
return *(meanings+meanx);
}
char * Expression::get_word()
{
return word_with_several_meanings;
}
int Expression::get_total_number_of_meanings()
{
return meanings_ctr;
}
int main(void) {
int i;
Expression expr;
expr.word("bank ");
expr.add_meaning("a place to get money from");
expr.add_meaning("b place to sit");
expr.add_meaning("4 letter word");
expr.add_meaning("Test meaning");
cout << expr.get_word() << endl;
for(int i = 0; i<expr.get_total_number_of_meanings(); i++)
cout << " " << expr.get_meaning(i) << endl;
Expression expr2;
expr2.word("class");
expr2.add_meaning("a school class");
expr2.add_meaning("a classification for a hotel");
expr2.add_meaning("Starts with C");
cout << expr2.get_word() << endl;
for( i = 0; i<expr2.get_total_number_of_meanings(); i++)
cout << " " << expr2.get_meaning(i) << endl;
Expression expr3;
expr3.word("A long test ... ");
char str[] = "Meaning_ ";
for (int kx=0;kx<26;kx++)
{
str[8] = (char) ('A'+kx);
expr3.add_meaning(str);
}
cout << expr3.get_word() << endl;
for(i = 0; i < expr3.get_total_number_of_meanings(); i++)
cout << " " << expr3.get_meaning(i) << endl;
return 0;
}
When you are allocating a multi dimensional array with new then you are allocating it with a loop, e.g.
char **x = new char*[size]
for (int i = 0; i < N; i++) {
x[i] = new int[size];
}
So you also have to delete it in this fashion:
for (int i = 0; i < N; i++) {
delete[] x[i];
}
delete[] x;
Thus when you're having arbitrary sizes of your array you'll have to store them somewhere for using them within the destructor.
delete [] meanings; // Deleting the memory we allocated
won't get rid of your memory allocated, only the pointers themselves.
To free up the actual memory, you will need to iterate through your meanings array, and delete [] each element in it.
Something like:
for (int i = 0; i < meanings_ctr; ++i)
{
delete [] meanings[meanings_ctr];
meanings[meanings_ctr] = NULL;
}
delete [] meanings;
--
For the problem of what to do if you get more than 100 meanings (or in general when your collection is full), the standard technique is to allocate a new array that is double the size (which you can do since it is dynamic), copy your existing collection into that one, and then dispose of your existing one.
I'd use a simple linked list (this is simplified, not complete and untested; also there should be proper getters/setters and stuff):
class Meaning {
char text[20];
Meaning *next;
Meaning(const char *text) : next(0) {
strcpy(this->text, text);
}
}
class Word {
char text[20];
Meaning *first;
Meaning *last;
Word(const char *text) : first(0), last(0) {
strcpy(this->text, text);
}
~Word() {
Meaning *m = first, *n;
while(m) {
n = m->next;
delete m;
m = n;
}
}
void AddMeaning(const char *text) {
if (last) {
last = last->next = new Meaning(text);
}
else {
first = last = new Meaning(text);
}
}
void print() {
printf("%s:\n\t", text);
Meaning *m = first;
while (m) {
printf("%s, ", m->text);
m = m->next;
}
}
}