I've been following some tutorials for allegro 5 and Im trying to load a tile map and I keep getting a vector subscript out of range error. I've been trying for so long to get this fixed but I cannot figure it out. The filemanager is supposed to read from a map.txt then go through layer.cpp then actually make the map.
EDIT:
It stops after the 5th loop of contents[i][j]
FileManager.CPP
#include "FileManager.h"
FileManager::FileManager()
{
identifierFound = false;
}
FileManager::~FileManager()
{
}
void FileManager::LoadContent(const char *filename, std::vector<std::vector<std::string>> &attributes, std::vector<std::vector<std::string>> &contents)
{
std::ifstream openFile(filename);
std::string line, newLine;
if(openFile.is_open())
{
while(std::getline(openFile, line))
{
std::stringstream str;
if(line.find("Load=") != std::string::npos)
{
type = LoadType::Attributes;
line = line.erase(0, line.find("=") + 1);
tempAttributes.clear();
}
else
{
type = LoadType::Contents;
tempContents.clear();
}
str << line;
while(std::getline(str, newLine, ']'))
{
newLine.erase(std::remove(newLine.begin(), newLine.end(), '['), newLine.end());
std::string erase = " \t\n\r";
newLine.erase(newLine.find_last_not_of(erase) + 1);
if(type == LoadType::Attributes)
tempAttributes.push_back(newLine);
else
tempContents.push_back(newLine);
std::cout << newLine << std::endl;
}
if(type == LoadType::Contents && tempContents.size() > 0)
{
attributes.push_back(tempAttributes);
contents.push_back(tempContents);
}
}
}
else
{
}
}
void FileManager::LoadContent(const char *filename, std::vector<std::vector<std::string>> &attributes, std::vector<std::vector<std::string>> &contents, std::string identifier)
{
std::ifstream openFile(filename);
std::string line, newLine;
if(openFile.is_open())
{
while(std::getline(openFile, line))
{
std::stringstream str;
if(line.find("EndLoad=") != std::string::npos && line.find(identifier) != std::string::npos)
{
identifierFound = false;
break;
}
else if(line.find("Load=") != std::string::npos && line.find(identifier) != std::string::npos)
{
identifierFound = true;
}
if(identifierFound)
{
if(line.find("Load=") != std::string::npos)
{
type = LoadType::Attributes;
line = line.erase(0, line.find("=") + 1);
tempAttributes.clear();
}
else
{
type = LoadType::Contents;
tempContents.clear();
}
str << line;
while(std::getline(str, newLine, ']'))
{
newLine.erase(std::remove(newLine.begin(), newLine.end(), '['), newLine.end());
std::string erase = " \t\n\r";
newLine.erase(newLine.find_last_not_of(erase) + 1);
if(type == LoadType::Attributes)
tempAttributes.push_back(newLine);
else
tempContents.push_back(newLine);
std::cout << newLine << std::endl;
}
if(type == LoadType::Contents && tempContents.size() > 0)
{
attributes.push_back(tempAttributes);
contents.push_back(tempContents);
}
}
}
}
else
{
std::cout << "Error reading file!" << std::endl;
}
}
Layer.CPP
#include "Layer.h"
Layer::Layer(void)
{
}
Layer::~Layer(void)
{
}
std::pair<int, int> Layer::SetTiles(std::string tileString)
{
std::pair<int, int> tile;
tile.first = atoi(tileString.substr(0, tileString.find(',')).c_str());
tile.second = atoi(tileString.substr(tileString.find(',') + 1).c_str());
return tile;
}
void Layer::LoadContent(std::string layerID, std::string mapID)
{
std::string fileName = "Maps/"+mapID+".txt";
fileManager.LoadContent(fileName.c_str(), attributes, contents, layerID);
int indexY = 0;
for(int i = 0; i < attributes.size(); i++)
{
for(int j = 0; j < contents[i].size(); j++)
{
std::cout << attributes[i][j] << std::endl << std::endl;
std::cout << contents[i][j] << std::endl << std::endl;
if(attributes[i][j] == "SolidTiles")
solidTiles.push_back(SetTiles(contents[i][j]));
else if(attributes[i][j] == "TileSheet")
{
tileSheet = al_load_bitmap(contents[i][j].c_str());
}
else if(attributes[i][j] == "StartLayer")
{
for(int k = 0; k < contents[i].size(); k++)
{
if(contents[i][k] != "---")
{
std::cout << contents[i][k] << std::endl << std::endl;
ALLEGRO_BITMAP *tileImage;
Tile::State tempState = Tile::State::Passive;
std::pair<int, int> tile = SetTiles(contents[i][k]);
if(std::find(solidTiles.begin(), solidTiles.end(), tile) != solidTiles.end())
{
tempState = Tile::State::Solid;
}
tileImage = al_create_sub_bitmap(tileSheet, tile.first * 32, tile.second * 32, 32, 32);
std::pair<float, float> position(k * 32, indexY * 32);
Tile tileInstance;
tiles.push_back(tileInstance);
tiles[tiles.size()-1].SetContent(tileImage, tempState, position);
}
}
indexY++;
}
}
}
}
void Layer::UnloadContent()
{
for(int i = 0; i < tiles.size(); i++)
tiles[i].UnloadContent();
al_destroy_bitmap(tileSheet);
}
void Layer::Update()
{
}
void Layer::Draw(ALLEGRO_DISPLAY *display)
{
for(int i = 0; i < tiles.size(); i++)
tiles[i].Draw(display);
}
map1.txt
Load=[MapProperties]
EndLoad=[MapProperties]
Load=[Layer1]
Load=[SolidTiles]
[2,0]
[1,0]
Load=[TileSheet]
[TileSheets/tilesheet1.png]
Load=[StartLayer]
[2,0][---][---][---][---][---][---][---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---][2,0][2,0][2,0][---][---][---][---]
[---][---][---][---][---][---][---][2,0][---][---][---][---][---][---][---]
[---][---][---][---][---][---][2,0][---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---][---][---][---][---][---][---][---]
[---][---][2,0][2,0][2,0][---][---][---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---][---][---][---][---][---][---][---]
[1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0]
Load=[EndLayer]
[dummy]
EndLoad=[Layer1]
Load=[PlayerPosition]
[0,0]
Related
I'm creating a custom language parser in C++, I'm struggling with a runtime error, where I have a std::vector<std::string> member of a class with a constructor.
The full error is:
The procedure entry point
_ZSt28__throw_bad_array_new_lengthv could no be located
in the dynamic link library
"path_to_executable"
This error is throw whenever I try to use std::vector::push_back in my code, but shouldn't std::vector be a dynamically sized data container? Why is this error occurring?
Some of my codes:
//"lib/cursor.h"
#ifndef T_CURSOR
#define T_CURSOR
#include <iostream>
struct Cursor
{
private:
std::string input;
int inputLength;
char getChar(int p);
public:
char character;
int pos;
int line;
int column;
bool eof;
bool lineBreak;
Cursor(std::string i);
void walk(bool back = false);
void walkTimes(int times, bool back = false);
void move(int toPos);
void skipIgnore();
std::string toString();
};
#endif
//"lib/cursor.cpp"
#include <sstream>
#include "cursor.h"
Cursor::Cursor(std::string i)
{
this->input = i;
this->inputLength = i.length();
this->character = i.at(0);
this->pos = 0;
this->line = 0;
this->column = 0;
this->eof = false;
this->lineBreak = false;
}
char Cursor::getChar(int pos)
{
if (pos < 0 || pos >= this->inputLength)
{
return EOF;
}
return this->input.at(pos);
}
void Cursor::walk(bool back)
{
if (back)
{
this->pos--;
this->column--;
if (this->lineBreak)
{
this->line--;
this->column = 0;
for (int i = this->pos - 1; i >= 0; i--)
{
if (this->getChar(i) == '\n')
break;
this->column++;
}
}
}
else
{
this->pos++;
this->column++;
if (this->lineBreak)
{
this->line++;
this->column = 0;
}
}
this->character = this->getChar(this->pos);
this->eof = this->character == EOF;
this->lineBreak = this->character == '\n';
}
void Cursor::walkTimes(int times, bool back)
{
for (int i = 0; i < times; i++)
{
this->walk(back);
}
}
void Cursor::move(int pos)
{
if (pos < 0)
pos = 0;
if (pos > this->inputLength - 1)
pos = this->inputLength - 1;
this->pos = 0;
this->character = this->input.at(0);
this->line = 0;
this->column = 0;
this->eof = false;
this->lineBreak = this->character == '\n';
while (this->pos < pos)
this->walk();
}
void Cursor::skipIgnore()
{
while (this->character == ' ' ||
this->character == '\n' ||
this->character == '\t')
this->walk();
if (this->character == '#')
{
while (!this->eof && this->character != '\n')
this->walk();
}
while (this->character == ' ' ||
this->character == '\n' ||
this->character == '\t')
this->walk();
}
std::string Cursor::toString()
{
std::stringstream ss("");
ss << "(P:" << this->pos;
ss << " L:" << this->line;
ss << " C:" << this->column;
ss << " \"" << this->character << "\")";
return ss.str();
}
//"lib/lexer.h"
#ifndef T_LEXER
#define T_LEXER
#include <iostream>
#include <vector>
#include "cursor.h"
class Lexer
{
private:
std::string input;
protected:
Cursor cursor;
std::vector<std::string> matchStack;
std::vector<std::vector<Cursor>> cursorStack;
public:
Lexer(std::string input);
std::string getStr(int pos);
void setStr(int pos, std::string str);
Cursor getCursorStart(int pos);
Cursor getCursorEnd(int pos);
bool match(std::string str);
};
#endif
//"lib/lexer.cpp"
#include "lexer.h"
Lexer::Lexer(std::string input) : cursor(input)
{
this->input = input;
}
std::string Lexer::getStr(int pos)
{
if (this->matchStack.size() == 0)
return this->input;
while (pos < 0)
pos += this->matchStack.size();
while (pos >= this->matchStack.size())
pos -= this->matchStack.size();
return this->matchStack[pos];
}
void Lexer::setStr(int pos, std::string str)
{
if (this->matchStack.size() == 0)
return;
while (pos < 0)
pos += this->matchStack.size();
while (pos >= this->matchStack.size())
pos -= this->matchStack.size();
this->matchStack[pos] = str;
}
Cursor Lexer::getCursorStart(int pos)
{
if (this->cursorStack.size() == 0)
return Cursor(this->input);
while (pos < 0)
pos += this->cursorStack.size();
while (pos >= this->cursorStack.size())
pos -= this->cursorStack.size();
return this->cursorStack[pos][0];
}
Cursor Lexer::getCursorEnd(int pos)
{
if (this->cursorStack.size() == 0)
return Cursor(this->input);
while (pos < 0)
pos += this->cursorStack.size();
while (pos >= this->cursorStack.size())
pos -= this->cursorStack.size();
return this->cursorStack[pos][1];
}
bool Lexer::match(std::string str)
{
this->cursor.skipIgnore();
const std::string ss = this->input.substr(this->cursor.pos, str.length());
if (ss == str)
{
this->matchStack.push_back(ss); // Getting error if I include this line
const Cursor startCursor = this->cursor;
this->cursor.walkTimes(str.length());
const Cursor endCursor = this->cursor;
this->cursorStack.push_back({startCursor, endCursor});
return true;
}
return false;
}
//"test.cpp"
#include "lib/cursor.h"
#include "lib/lexer.h"
#include <iostream>
using namespace std;
int main()
{
string input = "Something to test";
Lexer lexer = Lexer(input);
cout << "Start" << endl;
cout << lexer.match("Something") << endl;
return 0;
}
I'm compiling my program with g++ on Windows: g++ test.cpp lib/cursor.cpp lib/lexer.cpp -o test.exe
I got the same error when compiling in command line using g++. But it works well in code blocks. To solve this problem try compiling with -static-libstdc++. It should solve the problem.
I am stuck with the error "string subscript out of range".
After testing, I am pretty sure that it's because of this function, which is used for reading values in a file, but have no idea what's wrong:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string read(string value) {
ifstream input;
string line="", output="";
size_t pos;
bool a = true;
int i = 0;
input.open("pg_options.txt");
if (!input.is_open()) {
cout << "pg_options.txt missing.";
return "error";
}
while (getline(input, line)) { //get file lines
pos = line.find(value);
if (pos == string::npos) { //if value in line
while (a == true) {
if (line[i] == '=') { //after "="
i++;
break;
}
else {
i++;
}
}
for (i; line[i] != ' '; i++) {
output += line[i]; //put value to output
}
}
}
input.close();
return output;
}
pg_options.txt:
include_special_characters=true
include_upper_case=true
include_lower_case=true
include_numbers=true
digits=10
cout << read("digits") returns the error mentioned above.
Thank you for your comments. I solved this by editing the for loop:
string read(string value) {
ifstream input;
int olength;
string line = "", output = "";
size_t pos;
bool a = true;
int i = 0;
input.open("pg_options.txt");
if (!input.is_open()) {
cout << "pg_options.txt missing.";
return "error";
}
while (getline(input, line)) {
pos = line.find(value);
if (pos != string::npos) {
while (a == true) {
if (line[i] == '=') {
i++;
break;
}
else {
i++;
}
}
olength = line.length() - value.length() - 1;
for (int i2 = 0; i2 < olength; i2++) {
output += line[i];
i++;
}
}
}
input.close();
return output;
}
I am trying previous year's codejam question of round 1A
link to question
i have submitted this code(start reading from main method, for ease)-
#include <bits/stdc++.h>
using namespace std;
#define range(t) for (int i = 0; i < t; i++)
#define rangeG(i, t) for (i = 0; i < t; i++)
#define printVec(vec) \
for (auto c : vec) \
{ \
cout << c << endl; \
}
vector<string> separate(string s)
{
vector<string> result;
range(s.size())
{
if (s[i] == '*')
{
string temp = s.substr(0, i + 1);
if (temp.size() > 1)
{
result.push_back(temp);
}
s = s.substr(i, s.size());
i = 0;
}
else if (i == (s.size() - 1))
{
string temp = s.substr(0, i + 1);
result.push_back(temp);
s = s.substr(i, s.size());
}
}
return result;
}
void removeAsterisk(string &s)
{
s.erase(remove(s.begin(), s.end(), '*'), s.end());
}
bool setStart(string s, string &start)
{
bool possible = 1;
removeAsterisk(s);
range(min(s.size(), start.size()))
{
if (s[i] != start[i])
{
possible = 0;
}
}
if (possible)
{
if (s.size() >= start.size())
{
start = s;
}
}
return possible;
}
bool setEnd(string s, string &end)
{
bool possible = 1;
removeAsterisk(s);
range(min(s.size(), end.size()))
{
if (s[s.size() - 1 - i] != end[end.size() - 1 - i])
{
possible = 0;
}
}
if (possible)
{
if (s.size() >= end.size())
{
end = s;
}
}
return possible;
}
void solve()
{
int n;
cin >> n;
vector<string> allS;
bool possible = 1;
string start = "";
string end = "";
string middle = "";
string result = "";
while (n--)
{
string str;
cin >> str;
if (count(str.begin(), str.end(), '*') == 0)
{
result = str;
}
vector<string> temp = separate(str);
for (string s : temp)
{
if (s[0] != '*')
{
possible = setStart(s, start);
}
if (s[s.size() - 1] != '*')
{
possible = setEnd(s, end);
}
if (possible && count(s.begin(), s.end(), '*') == 0)
{
result = s;
break;
}
if (s[0] == '*' && s[s.size() - 1] == '*')
{
removeAsterisk(s);
middle += s;
}
}
}
if (possible)
{
if (result.size() == 0)
{
result = start + middle + end;
}
cout << result << "\n";
}
else
{
cout << "*\n";
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t = 0;
cin >> t;
range(t)
{
cout << "Case #" << i + 1 << ": ";
solve();
}
return 0;
}
it seems correct to me and i have tested many times for many examples, but it is losing in test set-1(exactly one * (asterisk) character and and always the first character of string). Can anyone tell what's wrong?
you can consider code of first ranked here (it has all solutions,check only for "pattern matching" task) for help. I know that the wrong answer is an edge case and if it passes test set 1 then it will pass others.
I'm doing a console checkers in C++. The problem is I can't refer to methods of forward-declared class.
Here's a header of Board class.
#define BOARD_H
#include "Square.h"
#include <vector>
#include <map>
class Man;
typedef std::vector<Square*> Column;
class Board
{
const int BOARD_SIZE = 8;
std::vector<Column> squares;
std::map<Location, Square*> locationSquareMap; //still kinda secret for me
public:
Board();
~Board();
//Board(Board& board);
void printBoard();
std::map<Location, Square*> getLocationSquareMap();
};
#endif
And it's implementation.
Here (printBoard()) I try to access man object via pointer, but I cannot do this because of incomplete type error.
#include "Board.h"
Board::Board()
{ //white black
for (int row = 0; row < BOARD_SIZE; row++)
{
squares.push_back(Column());
for (int column = 0; column < BOARD_SIZE; column++)
{
Location currentLocation(File(column), row);
SquareColor currentSquareColor = SquareColor::WHITE;
if ((column + row) % 2 == 0) //lol the bug was here, forgot about brackets
{
currentSquareColor = SquareColor::BLACK;
}
Square* currentSquare = new Square(currentLocation, currentSquareColor);
locationSquareMap.insert(std::make_pair(currentSquare->getLocation(), currentSquare));
squares.at(row).push_back(currentSquare);
}
}
}
Board::~Board()
{
}
void Board::printBoard()
{
for (int i = squares.size() - 1; i != -1; i--)
{
for (int g = squares.at(i).size() - 1; g != -1; g--)
{
std::cout << *(squares.at(i).at(g)) << std::endl;
}
}
std::cout << " ";
for (int i = 0; i < BOARD_SIZE; i++)
{
switch (File(i))
{
case File::A : std::cout << "A "; break;
case File::B : std::cout << "B "; break;
case File::C : std::cout << "C "; break;
case File::D : std::cout << "D "; break;
case File::E : std::cout << "E "; break;
case File::F : std::cout << "F "; break;
case File::G : std::cout << "G "; break;
case File::H : std::cout << "H "; break;
default: std::cout << " "; break;
}
}
std::cout << std::endl << std::endl;
for (int i = squares.size() - 1; i != -1; i--)
{
std::cout << i << " ";
for(int g = 0; g < squares.at(i).size(); g++)
{
Man* currentMan;
if (squares.at(i).at(g)->getIsOccupied())
{
currentMan = squares.at(i).at(g)->getCurrentMan();
//currentMan-> can't refer to methods
}
else
{
std::cout << "_ ";
}
}
std::cout << std::endl;
}
}
std::map<Location, Square*> Board::getLocationSquareMap()
{
return locationSquareMap;
}
Man's header:
#ifndef MAN_H
#define MAN_H
#include "ManColorEnum.cpp"
#include "Square.h"
#include <iostream>
#include <string>
#include <vector>
#include "LocationFactory.h"
#include "Board.h"
class Man
{
ManColor color;
Square* currentSquare;
bool isKing;
public:
Man(ManColor color, Square* square);
~Man();
//Man(Man& man);
Square* getCurrentSquare();
void setCurrentSquare(Square* square);
bool getIsKing();
void setIsKing();
ManColor getColor();
void makeMove(Square* square);
std::vector<Location> getValidMoves(Board* board);
friend std::ostream& operator<<(std::ostream& ostream, const Man& man);
};
#endif
Man's .cpp file:
#include "Man.h"
Man::Man(ManColor color, Square* square)
{
this->color = color;
this->currentSquare = square;
this->isKing = false;
}
Man::~Man()
{
//dtor
}
ManColor Man::getColor()
{
return color;
}
std::vector<Location> Man::getValidMoves(Board* board)
{
std::vector<Location> moveCandidates{};
if (!isKing)
{
Location currentLocation = this->currentSquare->getLocation();
std::map<Location, Square*> squareMap = board->getLocationSquareMap();
moveCandidates.push_back(LocationFactory::createLocation(currentLocation, 1, 1)); //move one right forward
moveCandidates.push_back(LocationFactory::createLocation(currentLocation, -1, 1)); //move one left forward
moveCandidates.push_back(LocationFactory::createLocation(currentLocation, 2, 2)); //capture forward right
moveCandidates.push_back(LocationFactory::createLocation(currentLocation, -2, 2)); //capture forward left
moveCandidates.push_back(LocationFactory::createLocation(currentLocation, 2, -2)); //capture backwards right
moveCandidates.push_back(LocationFactory::createLocation(currentLocation, -2, -2)); //capture backwards left
//TODO have to capture
for (int i = 0; i < moveCandidates.size(); i++)
{
//here I filter for moves to exist on the board
if (squareMap.count(moveCandidates.at(i)) == 0)
{
moveCandidates.erase(moveCandidates.begin() + i);
}
//here I filter occupied squares
if (squareMap[moveCandidates.at(i)]->getIsOccupied())
{
moveCandidates.erase(moveCandidates.begin() + i);
}
//here I filter capture moves
File currentFile = moveCandidates.at(i).getFile();
int currentRank = moveCandidates.at(i).getRank();
Square* preSquare = nullptr;
for (std::map<Location, Square*>::iterator it = squareMap.begin(); it != squareMap.end(); it++)
{
//check capture forward right
if (int(it->first.getFile()) == int(currentFile) + 2 && it->first.getRank() == currentRank + 2)
{
for (std::map<Location, Square*>::iterator itr = squareMap.begin(); itr != squareMap.end(); itr++)
{
if (int(itr->first.getFile()) == int(currentFile) + 1 && itr->first.getRank() == currentRank + 1)
{
preSquare = itr->second;
break; //check to be careful here
}
}
//if (it->second->getIsOccupied()
// || (preSquare->getIsOccupied() && preSquare->getCurrentMan()->color == color)
// || (!it->second->getIsOccupied() && !preSquare->getIsOccupied()))
//{
// moveCandidates.erase(moveCandidates.begin() + i);
// break; //check to be careful here
//}
}
//check capture backward right
else if (int(it->first.getFile()) == int(currentFile) + 2 && it->first.getRank() == currentRank - 2)
{
for (std::map<Location, Square*>::iterator itr = squareMap.begin(); itr != squareMap.end(); itr++)
{
if (int(itr->first.getFile()) == int(currentFile) + 1 && itr->first.getRank() == currentRank - 1)
{
preSquare = itr->second;
break;
}
}
}
//check capture forward left
else if (int(it->first.getFile()) == int(currentFile) -2 && it->first.getRank() == currentRank + 2)
{
for (std::map<Location, Square*>::iterator itr = squareMap.begin(); itr != squareMap.end(); itr++)
{
if (int(itr->first.getFile()) == int(currentFile) - 1 && itr->first.getRank() == currentRank + 1)
{
preSquare = itr->second;
break;
}
}
}
//check capture backwards left
else if (int(it->first.getFile()) == int(currentFile) - 2 && it->first.getRank() == currentRank - 2)
{
for (std::map<Location, Square*>::iterator itr = squareMap.begin(); itr != squareMap.end(); itr++)
{
if (int(itr->first.getFile()) == int(currentFile) - 1 && itr->first.getRank() == currentRank - 1)
{
preSquare = itr->second;
break;
}
}
}
if (it->second->getIsOccupied()
|| (preSquare->getIsOccupied() && preSquare->getCurrentMan()->color == color)
|| (!it->second->getIsOccupied() && !preSquare->getIsOccupied()))
{
moveCandidates.erase(moveCandidates.begin() + i);
break; //check to be careful here
}
}
}
}
return moveCandidates;
}
Square* Man::getCurrentSquare()
{
return currentSquare;
}
void Man::setCurrentSquare(Square* square)
{
this->currentSquare = square;
}
bool Man::getIsKing()
{
return isKing;
}
void Man::setIsKing()
{
isKing = true;
}
void Man::makeMove(Square* square)
{
this->currentSquare->reset();
this->currentSquare = square;
}
std::ostream& operator<<(std::ostream& ostream, const Man& man)
{
std::string colorStr;
switch (man.color)
{
case ManColor::BLACK: colorStr = "BLACK"; break;
case ManColor::WHITE: colorStr = "WHITE"; break;
default: colorStr = "COLOR";
}
return std::cout << "Man { color=" << colorStr << " } " << std::endl;
}
Put forward class declarations in header files and include headers in source files.
I'm new to C++. I'm trying to make inverted index but I can't understand the cord. I want to count the frequency of the word. Can you explain this code and how to count the frequency of the word? Please help me to solve this problem.
class node{
public:
node() {
clear();
}
node(char z) {
clear();
}
~node() {
for (int x = 0; x < MAX_NODES; x++) {
if (next[x]) {
delete next[x];
}
}
}
void clear() {
for (int x = 0; x < MAX_NODES; x++){
next[x] = 0;
isWord = false;
}
}
bool isWord;
int count;//frq
std::vector<std::string> files;
node* next[MAX_NODES];
map<string, int> counts;
};
class index {
public:
void add(std::string s, std::string fileName) {
std::transform(s.begin(), s.end(), s.begin(), tolower);
std::string h;
int freq=0;
for (std::string::iterator i = s.begin(); i != s.end(); i++) {
if (*i == 32) {
pushFileName(addWord(h), fileName);
h.clear();
continue;
}
h.append(1, *i);
}
if (h.length()){
pushFileName(addWord(h), fileName);
}
}
void findWord(std::string s, map<string, int> counts) {
std::vector<std::string> v = find(s);
if (!v.size()) {
std::cout <<"'"<< s + "' is not found!\n";
return;
}
std::cout << "'" << s << "' is found in:\n";
for (std::vector<std::string>::iterator i = v.begin(); i != v.end(); i++) {
std::cout << *i << "\n";
}
std::cout << "frequency is : ";
}
private:
void pushFileName(node* n, std::string fn) {
std::vector<std::string>::iterator i = std::find(n->files.begin(), n->files.end(), fn);
if (i == n->files.end()){
n->files.push_back(fn);
n->count;
}
}
const std::vector<std::string>& find(std::string s) {
size_t idx;
std::transform(s.begin(), s.end(), s.begin(), tolower);
node* rt = &root;
for (std::string::iterator i = s.begin(); i != s.end(); i++) {
idx = _CHARS.find(*i);
if (idx < MAX_NODES) {
if (!rt->next[idx]){
return std::vector<std::string>();
}
rt = rt->next[idx];
}
}
if (rt->isWord) return rt->files;
return std::vector<std::string>();
}
node* addWord(std::string s) {
size_t idx;
node *rt = &root, *n;
for (std::string::iterator i = s.begin(); i != s.end(); i++) {
idx = _CHARS.find(*i);
if (idx < MAX_NODES) {
n = rt->next[idx];
if (n){
rt = n;
continue;
}
n = new node(*i);
rt->next[idx] = n;
rt = n;
}
}
rt->isWord = true;
rt->count++;
return rt;
}
node root;
};
class index {
public:
void add(std::string s, std::string fileName) {
std::transform(s.begin(), s.end(), s.begin(), tolower);
std::string h;
int freq=0;
for (std::string::iterator i = s.begin(); i != s.end(); i++) {
if (*i == 32) {
pushFileName(addWord(h), fileName);
h.clear();
continue;
}
h.append(1, *i);
}
if (h.length()){
pushFileName(addWord(h), fileName);
}
}
void findWord(std::string s, map<string, int> mFilesFreq) {
std::vector<std::string> v = find(s);
if (!v.size()) {
std::cout <<"'"<< s + "' is not found!\n";
return;
}
std::cout << "'" << s << "' is found in:\n";
for (std::vector<std::string>::iterator i = v.begin(); i != v.end(); i++) {
std::cout << *i << "\n";
}
std::cout << "frequency is : ";
}
If you are counting the number of times add was called for a given word, you probably want to replace rt->isWord = true; with rt->count++; and in your struct node replace bool isWord with int count.