Problems returning vector stack reference - c++

I am working on an application that builds a vector of structs for items in a given directory and returns a reference of the vector for it to be read, I receive the following errors when attempting to compile the example code below:
1. 'class std::vector<indexStruct, std::allocator<indexStruct> >' has no member named 'name'
2. no matching function for call to `std::vector<indexStruct, std::allocator<indexStruct> >::push_back(std::vector<indexStruct, std::allocator<indexStruct> >&)'
exampleApp.cpp
#include "exampleApp.h"
exampleApp::exampleApp()
{
this->makeCatalog();
}
char* findCWD()
{
char* buffer = new char[_MAX_PATH];
return getcwd(buffer, _MAX_PATH);
}
void exampleApp::makeCatalog()
{
char* cwd = this->findCWD();
vector<indexStruct> indexItems;
this->indexDir(cwd, indexItems);
}
void exampleApp:indexDir(char* dirPath, vector<indexStruct>& indexRef)
{
DIR *dirPointer = NULL;
struct dirent *dirItem = NULL;
vector<indexStruct> indexItems;
vector<indexStruct> indexItem;
try
{
if ((dirPointer = opendir(dirPath)) == NULL) throw 1;
while (dirItem = readdir(dirPointer))
{
if (dirItem == NULL) throw 2;
if (dirItem->d_name[0] != '.')
{
indexItem.name = dirItem->d_name;
indexItem.path = dirPath;
indexItems.push_back(indexItem);
indexItem.clear();
}
}
indexRef.swap(indexItems);
closedir(dirPointer);
}
catch(int errorNo)
{
//cout << "Caught Error #" << errorNo;
}
}
exampleApp.h
#ifndef EXAMPLEAPP_H
#define EXAMPLEAPP_H
#include <iostream.h>
#include <dirent.h>
#include <stdlib.h>
#include <vector.h>
using namespace std;
struct indexStruct
{
char* name;
char* path;
};
class exampleApp
{
public:
exampleApp();
private:
char* findCWD();
void makeCatalog();
void indexDir(char* dirPath, vector<indexStruct>& indexRef);
};
#endif
What am I doing wrong here, and is there a better way going about this?

You've made 'indexItem' a vector, you probably just want it to be the type you want to put in 'indexItems'. Also, I'd create the new struct in your loop:
while (dirItem = readdir(dirPointer))
{
if (dirItem == NULL) throw 2;
if (dirItem->d_name[0] != '.')
{
indexStruct indexItem;
indexItem.name = dirItem->d_name;
indexItem.path = dirPath;
indexItems.push_back(indexItem);
}
}

You are defining a vector called indexItem:
vector<indexStruct> indexItem;
This is just an array. So the following lines must be changed to reference a specific element of the vector:
indexItem.name = dirItem->d_name;// should be indexItem[..].name or indexItem.at(..).name
indexItem.path = dirPath; // same as above!

Related

C++, Weird behavior of cout when trying to print integers

Im trying to write a class that stores an id and a value in an container class.
Im using an nested class as my data structure.
When im compiling the code sometimes it prints perfectly, sometimes it prints nothing and sometimes it prints half of the data then stops.
When i debug the code the same weird behavior occours, when it fails during debug it throws an error "Map.exe has triggered a breakpoint.", the Error occours in the print method when im using cout.
cmap.h
#pragma once
class CMap
{
public:
CMap();
~CMap();
CMap& Add(int id, int value);
void print() const;
private:
class container
{
public:
~container();
int container_id = 0;
int container_value = 0;
};
container* p_komp_;
int dim_ = -1;
void resize();
};
cmap.cpp
#include "cmap.h"
#include <iostream>
using namespace std;
CMap::CMap()
{
p_komp_ = new container[0];
}
CMap::~CMap()
{
p_komp_ = nullptr;
cout << "destroy cmap";
}
CMap& CMap::Add(int id, int value)
{
resize();
p_komp_[dim_].container_id = id;
p_komp_[dim_].container_value = value;
return *this;
}
void CMap::resize()
{
container* temp_array = new container[++dim_];
if (dim_ == 0)
{
temp_array[0].container_id = p_komp_[0].container_id;
temp_array[0].container_value = p_komp_[0].container_value;
}
for (unsigned i = 0; i < dim_; i++)
{
temp_array[i].container_id = p_komp_[i].container_id;
temp_array[i].container_value = p_komp_[i].container_value;
}
p_komp_ = temp_array;
}
void CMap::print() const
{
for (unsigned i = 0; i <= dim_; i++)
{
cout << p_komp_[i].container_id;
cout << p_komp_[i].container_value;
}
}
CMap::container::~container()
{
cout << "destruct container";
}
Map.cpp
#include "cmap.h"
#include <iostream>
using namespace std;
void main(void)
{
CMap m2;
m2.Add(1, 7);
m2.Add(3, 5);
m2.print();
}
These two things are a possible reason for your problem:
int dim_ = -1;
and
container* temp_array = new container[++dim_];
When you allocate, you increase dim_ from -1 to 0. That is you create a zero-sized "array", where every indexing into it will be out of bounds and lead to undefined behavior.
You also have memory leaks since you never delete[] what you new[]. I didn't look for more problems, but there probably a more.
And an "array" (created at compile-time or through new[]) will have indexes from 0 to size - 1 (inclusive). You seem to think that the "size" you provide is the top index. It's not, it's the number of elements.
It seems to me that you might need to take a few steps back, get a couple of good books to read, and almost start over.

Macro for auto destroy heap objects

This is not the actual code what I'm working. but this code can be used to explain my problem in clear.
I have a function called "OnCallFunction" with some new'd objects as inputs that should be deleted inside the "OnCallFunction". In each and every point i should return, i need to add the deletion code there. I think this is not the correct way of doing this. In this way this should be remembered and put in each return which will be done in future as well. If the code is not simple as below, I may forget to insert the deletion part as well.
#include <iostream>
#include <stdlib.h>
using namespace std;
class Student
{
public:
Student(){}
~Student(){}
int GetID(){return rand();}
};
int OnCallFunction(Student* pStudent)
{
int iValue = pStudent->GetID();
if (iValue == 5)
{
delete pStudent;
return 90;
}
if (iValue == 67)
{
delete pStudent;
return 8709;
}
if (iValue == 234)
{
delete pStudent;
return 78;
}
if (iValue == 343)
{
delete pStudent;
return 9832;
}
if (iValue == 678)
{
delete pStudent;
return 876;
}
delete pStudent;
return -1;
};
int main(int argc, const char** argv)
{
Student* pStudent = new Student();
OnCallFunction(pStudent);
};
So, I played around and developed a macro for auto destroy the heap objects.
This is the modified code using the macro (AUTO_DESTROY)
#include <iostream>
#include <stdlib.h>
using namespace std;
#define AUTO_DESTROY(ClassType, Variable, DeleteStatement)\
class AD##ClassType##Variable\
{\
public:\
AD##ClassType##Variable(ClassType* pData) {Variable=pData;};\
~AD##ClassType##Variable() {DeleteStatement;};\
private:\
ClassType* Variable;\
};\
AD##ClassType##Variable oAD##ClassType##Variable(Variable)
class Student
{
public:
Student(){}
~Student(){}
int GetID(){return rand();}
};
int OnCallFunction(Student* pStudent)
{
AUTO_DESTROY(Student, pStudent, delete pStudent);
int iValue = pStudent->GetID();
if (iValue == 5)
{
return 90;
}
if (iValue == 67)
{
return 8709;
}
if (iValue == 234)
{
return 78;
}
if (iValue == 343)
{
return 9832;
}
if (iValue == 678)
{
return 876;
}
return -1;
};
int main(int argc, const char** argv)
{
Student* pStudent = new Student();
OnCallFunction(pStudent);
};
Now my questions are,
1) Does this has any performance/maintainability/code quality impact rather than deleting in each return?
2) In this macro it creates a class inside the function. So will than cause multiple declarations if we use the same macro, same class type, same variable name in multiple cpp files? Agree that I can test it.
3) Are there any ideas or pre-built things to do this in easier way?
NB:
Please do not propose to create "Student" as a stack variable in heap or keep the function output in a variable and return only at the end. :)
Don't use a macro, and don't use raw pointers. Use a unique_ptr to hold the allocated object, and change your function to:
int OnCallFunction(std::unique_ptr<Student> pStudent)
{
int iValue = pStudent->GetID();
if (iValue == 5)
{
return 90;
}
if (iValue == 67)
{
return 8709;
}
if (iValue == 234)
{
return 78;
}
if (iValue == 343)
{
return 9832;
}
if (iValue == 678)
{
return 876;
}
return -1;
};
int main(int argc, const char** argv)
{
std::unique_ptr<Student> pStudent(new Student());
OnCallFunction(std::move(pStudent));
};
Proper deletion of the managed Student object will be automatically done when OnCallFunction() exits.
boost's scope exit has implemented the functionality you want. You can look into that implementation or use it out of the box.
Example :
#include <boost/scope_exit.hpp>
#include <cstdlib>
#include <cstdio>
#include <cassert>
int main()
{
std::FILE* f = std::fopen("example_file.txt", "w");
assert(f);
BOOST_SCOPE_EXIT(f) {
// Whatever happened in scope, this code will be
// executed and file will be correctly closed.
std::fclose(f);
} BOOST_SCOPE_EXIT_END
// Some code that may throw or return.
// ...
}
Using this functionality, you'd be practically specifying freestanding "RAII destructor actions".
Use where it makes your code clearer and cleaner and avoid when all functionality would be more easily incorporated (or already is) inside a class' destructor.

Vector losing contents between files in C++

I have some methods in lexer.h which make use of a Vector made of Tokens.
In this method void getNextToken() I am making use of the said vector where I am adding new tokens to it.
The problem is, that when I go to a different file, I am trying to access ANOTHER method which makes use of this vector, but it is crashing with an out of bounds error (most probably it's being deferenced or something)
Is there a way how I can fix this?
The methods in concern are:
Token* nextToken()
{
if (it!= tokensUsed.end())
{
// we Assigned what is found in the iterator it (of the vector)
// so we get the data found in that pointer
itrToken = &*it;
//Move Iterator forward
it ++;
return itrToken;
}
}
/*
Used in Parser to go get the PREVIOUS Tokens
*/
Token* prevToken()
{
itrToken --;
if (it!= tokensUsed.begin())
{
itrToken = &*this->it;
return itrToken;
}
}
void getNextToken()
{
//CODE ADDING TOKENS
//EXAMPLE
if (ch == '"')
{
addAndGetNext(ch);
cout << "STRING: " << strBuffer << endl; //TEST
//create new token and push it into the vector
tk = new Token (Token::ttString, strBuffer, row, col);
tokensUsed.push_back(*tk); //Add the new token to the Vector
startNewString(); //Clear the string
}
tokenMatch = true;
}
The above is just partial code, to show an example.
Now in Parser.h I am using this method to call the lexer.h:
void relOpP()
{
Token* tk = nextToken();
if (tk -> getType() == Token::ttString)
{
cout << "Ture";
}
}
which calls the Lexer's nextToken() it crashes, and when I tried checking it's contents it goes outofBounds error (and CodeBlocks giving me a SIGSEGV error)
I know it's something from the pointers that it's going awry, but how can I fix it?
Edit:
These are the global variables I have declared:
vector<Token>::iterator it;
vector<Token> tokensUsed;
Token* itrToken; // used for iterator
bool checkQuote = false;
Token* tk = new Token (syNewToken, "", 1,0);
Token token; // Creates an instance of the class Token found in the file token.h
Token* t;
SAMPLE CODE:
main.cpp
#include <iostream>
#include "lexer.h"
#include "parser.h"
using namespace std;
int main()
{
Lexer* l;
l -> getNextToken();
Parser p(l);
p.relOpP();
}
Token (int type, string sBuffer, int rRow, int cCol)
{
this->tType = type;
this->strBuffer = sBuffer;
this->row = rRow;
this->col = cCol;
}
parser.h
#ifndef PARSER_H_INCLUDED
#define PARSER_H_INCLUDED
#include <string>
#include <vector>
#include "lexer.h"
#include "token.h"
using namespace std;
class Parser{
private:
Lexer* lexer;
string tree = "";
public:
Parser (Lexer* l)
{
this -> lexer = l;
}
Token nextToken()
{
Token tk = lexer -> nextToken();
return tk;
}
void relOpP()
{
Token tk = nextToken();
if (tk.getType() == 1)
{
cout << "Ture";
}
}
#endif // PARSER_H_INCLUDED
};
token.h
#ifndef TOKEN_H_INCLUDED
#define TOKEN_H_INCLUDED
#include <iostream>
using namespace std;
class Token
{
private:
int tType; //identifier or reserved by compiler?
string strBuffer; //string found in buffer at that moment
int row;
int col;
public:
enum tokenType
{
tkString
};
Token()
{
}
// The instance of a token with 4 parameters resulting the type, the contents of the string that represents that type
// the row it is found in and the column.
Token (int type, string sBuffer, int rRow, int cCol)
{
this->tType = type;
this->strBuffer = sBuffer;
this->row = rRow;
this->col = cCol;
}
Token (Token* getT)
{
this-> tType = getT -> tType;
this->strBuffer = getT -> strBuffer;
this->row = getT -> row;
this->col = getT -> col;
}
int getType ()
{
return this->tType;
}
//return the string contents
string getBuffer()
{
return this->strBuffer;
}
//return row
int getRow()
{
return row;
}
//return col
int getCol ()
{
return col;
}
};
#endif // TOKEN_H_INCLUDED
Lexer.h
#ifndef LEXER_H_INCLUDED
#define LEXER_H_INCLUDED
#include "token.h"
#include <vector>
using namespace std;
class Lexer
{
private:
Token tk = new Token (1, "", 1,0);
vector<Token>::iterator it;
vector<Token> tokensUsed;
Token itrToken; // used for iterator
public:
Token nextToken()
{
if (it!= tokensUsed.end())
{
// we Assigned what is found in the iterator it (of the vector)
// so we get the data found in that pointer
itrToken = &*it;
//Move Iterator forward
it ++;
return &itrToken;
}
else
{
cout << "ERROR" << endl;
}
return nullptr;
}
void getNextToken()
{
cout << "Test" << endl;
string strBuffer = "test";
int row = 0;
int col = 0;
tk = new Token (1,strBuffer,row,col);
}
};
#endif // LEXER_H_INCLUDED
In nextToken() and prevToken() there is no return for the case the if evaluates to false. The return value in that case is not very likely to be something (it could be anything...) that you can then dereference.
If you want to keep the current design you should return nullptr or (NULL if you don't have C++11 support) in that case. Then you need to change any code that uses the result of those functions to check if the pointer is valid before dereferencing it.
You would probably be better changing your design to not involve so much manual pointer manipulation. But to fix up your current version you should change your prevToken and nextToken to be something along the lines of:
Token* nextToken()
{
if (it!= tokensUsed.end())
{
...
return itrToken;
}
else
{
return nullptr;
}
}
Then if tk is the result of calling one of these functions you must not use tk-> or *tk if it is nullptr. Any code wanting to work with the result will need to check first.
So for example you could change you if statement to be:
if (tk && // Make sure tk is not nullptr
tk -> getType() == Token::ttString)
{
...
There are too many problems with your code for me to address them all in this post. The first, and most obvious one is this.
In the main function:
Lexer* l;
l -> getNextToken();
Here, you did not create a Lexer object. You just created an uninitialized pointer to one. Then you called a member function as if it pointed to an object. This is undefined behavior. You then pass this pointer to your Parser class, which continues to treat it as a valid object, resulting in more undefined behavior.
There are many other problems with your code, but most of them have to do with your mishandling of pointers, indicating a lack of understanding of how they work. The best suggestion for you is to stop using them entirely. There is no reason you need to use any pointers whatsoever to do what you are doing. If you can't figure out how to do what you are trying to do without pointers, it is because of a lack of fundamental understanding of the language. You need to read a C++ book, to completion. Here's a list of some good ones.
The Definitive C++ Book Guide and List

Error assigning object to pointer c++

Me and my friend are making a text based game in c++ for fun, and to learn a little more. I have been trying to use pointers to classes, but am having no luck, and some errors are occurring which make absolutely no sense to me at all, and am hoping someone can help me.
Code:
//Map.h
#include "Player.h"
class Map
{
//Virtual functions
};
class StartMap : public Map
{
//Code
}Start;
class JungleMap : public Map
{
//Code
}Jungle;
class RiverMap : public Map
{
//Code
}River;
//Player.h
#ifndef MAP_H
#define MAP_H
#endif
class Player
{
private:
Map *PlayerMap;
//Other variables
public:
void Initialize()
{
//Initialize variables
PlayerMap = &Start; //This is where the error occurs, says there's a
//<error-type>*Player::PlayerMap. Tried putting
//this->PlayerMap = &Start, didn't help
//There's no error when I make the pointer
}
//Bunch of other functions
}Player;
Okay, here's my code since I decided to add .cpp files:
//Command.h
class Command
{
private:
string GameCommand;
void Trim();
public:
Command (string command) {GameCommand = command;}
Command () {}
void operator = (string command) {GameCommand = command;}
void ReadCommand();
string Print();
}
//Command.cpp
#include <iostream>
#include <string>
#include "Command.h"
#include "Parameter.h"
using namespace std;
void Command::Trim()
{
int LeadingPos = 0, MidCount = 0, TrailingPos = GameCommand.length()-1, Size = 0;
string TempCommand = "";
while (GameCommand[LeadingPos] == ' '){LeadingPos += 1;}
while (GameCommand[TrailingPos] == ' '){TrailingPos -= 1;}
Size = ((TrailingPos+1)-LeadingPos);
for (int loops = 0; loops < Size; loops++)
{
if (MidCount > 0 && GameCommand[LeadingPos] == ' ')
{
LeadingPos += 1;
}
else
{
if (GameCommand[LeadingPos] == ' ')
{
MidCount += 1;
}
TempCommand += GameCommand[LeadingPos];
LeadingPos += 1;
}
}
GameCommand = TempCommand;
}
void Command::ReadCommand()
{
Trim();
string Parameter;
if (GameCommand.substr(0,3) == "go ")
{
Parameter = GameCommand.substr(3,string::npos);
CommandParameter.Go(Parameter);
}
else if (GameCommand.substr(0,4) == "dig ")
{
Parameter = GameCommand.substr(4,string::npos);
CommandParameter.Dig(Parameter);
}
else if (GameCommand.substr(0,4) == "eat ")
{
Parameter = GameCommand.substr(4,string::npos);
CommandParameter.Eat(Parameter);
}
else if (GameCommand.substr(0,4) == "exit" || GameCommand.substr(0,4) == "quit")
{
exit(0);
}
else if (GameCommand.substr(0,4) == "use ")
{
Parameter = GameCommand.substr(4,string::npos);
CommandParameter.Use(Parameter);
}
else if (GameCommand.substr(0,5) == "drop ")
{
Parameter = GameCommand.substr(5,string::npos);
CommandParameter.Drop(Parameter);
}
else if (GameCommand.substr(0,5) == "grab " || GameCommand.substr(0,5) == "take ")
{
Parameter = GameCommand.substr(5,string::npos);
CommandParameter.Pickup(Parameter);
}
else if (GameCommand.substr(0,5) == "help ")
{
Parameter = GameCommand.substr(5,string::npos);
CommandParameter.Help(Parameter);
}
else if (GameCommand.substr(0,5) == "look ")
{
Parameter = GameCommand.substr(5,string::npos);
CommandParameter.Look(Parameter);
}
else if (GameCommand.substr(0,5) == "sleep")
{
CommandParameter.Sleep();
}
else if (GameCommand.substr(0,6) == "check ")
{
Parameter = GameCommand.substr(6,string::npos);
CommandParameter.Check(Parameter);
}
else if (GameCommand.substr(0,6) == "climb ")
{
Parameter = GameCommand.substr(6,string::npos);
CommandParameter.Climb(Parameter);
}
else if (GameCommand.substr(0,6) == "throw ")
{
Parameter = GameCommand.substr(6,string::npos);
CommandParameter.Throw(Parameter);
}
else if (GameCommand.substr(0,7) == "attack ")
{
Parameter = GameCommand.substr(7,string::npos);
CommandParameter.Attack(Parameter);
}
else if (GameCommand.substr(0,7) == "search ")
{
Parameter = GameCommand.substr(7,string::npos);
CommandParameter.Search(Parameter);
}
else
{
cout << "Not a valid command.\n";
}
}
string Print()
{
return GameCommand;
}
The string GameCommand is what's not working.
class StartMap : public Map;
is syntactically incorrect. You need
class StartMap : public Map
{
// Details of class
} Start;
You need to make similar changes to JungleMap and RiverMap.
First thing I noticed was the semi-colon after each inheritance declaration..
class XXXXX : public Map; <-- that semi-colon shouldn't be there..
In the initialize function, I'm fairly certain you mean PlayerMap = new StartMap();
You'll need a destructor to delete it and a copy, move constructor as well as an assignment operator in order to assign, move or copy the class.
You can follow this to make the class conform to RAII: What is the copy-and-swap idiom?
There are lots of problems with your code layout.
This doesn't do anything:
//Player.h
#ifndef MAP_H
#define MAP_H
#endif
I guess you are trying to do an include guard. The proper layout is:
#ifndef PLAYER_H
#define PLAYER_H
// all your code for the header file goes here
class Player
{
// ....
};
#endif // no more code after this line
The next issue is that Player.h should include Map.h, not the other way around. Imagine you are the compiler. You are processing Player.h. You get down as far as Map *PlayerMap; . But you don't know what Map is because you haven't seen Map.h yet. So you have to give an error and stop compiling.
The map definitions in Map.h should look like:
class StartMap : public Map
{
//Code
};
The Start; you had on the end is poor style. It would cause undefined behaviour if two different .cpp files included Map.h because there would be two different global variables with the same name.
Moving onto the void Map::Initialize() function. You're supposed to use the constructor for initialization. Either way, my suggestion is that you don't implement this in Player.h. Instead, just have void Initialize();, and then in Map.cpp you could have:
// the global variables
StartMap start_map;
JungleMap jungle_map;
void Map::Initialize()
{
player_map = &start_map;
}
It's a good idea to use a different naming convention for classes than for variables. So that when someone sees StartMap for example, they know immediately whether it is a class name or a variable name.

Decoder implementing a stack as a linked structure

This program I am writing will use a special implementation of a stack as a linked structure. An encoded message input my the user will be parsed and decoded using the stack. What I have written compiles find and runs without crashing. The program asks the user for the string to be decoded. However, the encoded message is not decoded with result printed on the screen. I can't figure out why my program isn't decoding and printing the user's input. Any help is greatly appreciated. Thanks.
My header file :
#ifndef DECODER_H
#define DECODER_H
#include <iostream>
#include <stdlib.h>
using namespace std;
// ---------------------------
// Structure which will serve
// as the link on the stack.
// ---------------------------
struct StackNode {
char ch;
StackNode* next;
};
// -------------------------------
// Class which will contains the
// functions for appropriate use
// of the stack.
// -------------------------------
class Decoder
{
private:
StackNode* top;
public:
Decoder();
~Decoder();
int EmptyStack();
int FullStack();
void Push(char ch);
char Pop();
void Decode(char *encMsg, char *decMsg);
};
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#endif // End of stack header.
My .cpp file:
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "Decoder.h"
// ------------------------------
// Function: Decoder()
//
// Purpose: Class constructor.
// ------------------------------
Decoder::Decoder()
{
top = NULL;
}
// ------------------------------
// Function: Decoder()
//
// Purpose: Class destructor.
// ------------------------------
Decoder::~Decoder()
{
// TODO
// Destroy anything remaining in the stack
}
// -----------------------------------
// FullStack()
//
// Return TRUE if the stack is full.
// -----------------------------------
int Decoder::FullStack()
{
return TRUE;
}
// -----------------------------------
// EmptyStack()
//
// Return TRUE if the stack is empty
// -----------------------------------
int Decoder::EmptyStack()
{
return (top == NULL);
}
// ------------------------------------------------
// Function: void Push(char ch)
//
// Purpose: Dynamically creates a structure of type
// StackNode (see Decoder.h), stores the character
// in the structure and pushes the structure onto
// the stack.
// ------------------------------------------------
void Decoder::Push(char ch)
{
// Make a new node whose reference is
// the existing list
StackNode* newNode = new (StackNode);
newNode->ch = ch;
// newNode->next = NULL;
if (top == NULL)
top = newNode; // top points to new node
else
{
newNode->next = top;
top = newNode;
}
}
// --------------------------------------------------
// Function: char Pop()
//
// Purpose: Remove (pop) the top node from the stack,
// copy the character, from this node, delete and
// return the character.
// --------------------------------------------------
char Decoder::Pop()
{
StackNode* temp;
char ch;
if (!EmptyStack())
{
ch = top->ch;
temp = top;
top = top->next;
delete(temp);
return ch;
}
else {
cout << "Warning: Overuse of Pop()" << endl;
return '\0';
}
}
// ----------------------------------------------------
// Function: void Decode(char* encMsg, char* decMsg)
//
// Purpose: Parse and decode the message stored in the
// character array encMsg using the stack functions
// and return the decoded message in the char array
// decMsg.
// ----------------------------------------------------
void Decoder::Decode(char* encMsg, char* decMsg)
{
int StackCount = 0;
char num[2] = " ";
for (int i = 0; i < strlen(encMsg); i++)
{
// check whether 1 is an even number of input
if ((encMsg[i] == '1') && (encMsg[i-1] != '2')) // every other index will be a command number
{
Push(encMsg[i+1]);
StackCount++;
}
if (encMsg[i] == '2' && ((encMsg[i+1] >= '0') && (encMsg[i+1 ] <= '9'))) // every other index will be a command number
{
num[0] = encMsg[i+1];
// pop as many as the argument states to pop
for (int j = 0; j < atoi(num); j++)
{
Pop();
StackCount--;
}
}
}
//cout << StackCount << endl;
// Place the remaining characters from the stack into decMsg
int i;
for (i = 0; i < StackCount; i++)
{
decMsg[i] = Pop();
}
decMsg[i] = '\0';
return;
}
My Main .cpp:
#include <iostream>
#include <string>
#include "Decoder.h"
using namespace std;
int main (void)
{
char quit[] = "QUIT";
char en[2048];
char dec[512];
Decoder d;
do {
cout << "\nEnter a message to be decoded" << endl;
cin.getline(en, 1024);
d.Decode(en, dec);
cout << dec << endl;
} while (strcmp(en,quit) != 0);
return 0;
}
This line of code
if ((encMsg[i] == '1') && (encMsg[i-1] != '2'))
Maybe a problem there when i is zero.
It is guaranteed to try endMsg[-1] every time since i=0 is followed immediately by encMsg[i-1] which is always checked since && is present.
for (int i = 0; i < strlen(encMsg); i++)
{
// check whether 1 is an even number of input
if ((encMsg[i] == '1') && (encMsg[i-1] != '2')) // every other index will be a command number
{