I'm doing a project with C++ and my program keeps crashing down when I try to run it...here is my code (two files: main.cpp and PlacementHead.cpp):
main.cpp:
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>
#include <climits>
#include "PlacementHead.h"
// Main
int main (int argc, char * const argv[]) {
PlacementHead h1(4,2,1,"aabcbbca");
PlacementHead h2(4,2,1,"babcabca");
return 0;
}
PlacementHead.cpp:
#include "PlacementHead.h"
#include <string>
#include <iostream>
#include <string.h>
PlacementHead::PlacementHead(int width, int height, int gap, char* s) {
width_ = width;
height_ = height;
gap_ = gap;
size_ = width*height;
set_ = new char[size_];
from_ = new int[size_];
original_ = new char[size_];
strcpy(set_,s);
strcpy(original_,s);
}
PlacementHead::~PlacementHead() {
}
int PlacementHead::getSize() { return size_; }
int PlacementHead::getHeight() { return height_; }
int PlacementHead::getWidth() { return width_; }
int PlacementHead::getGap() { return gap_; }
char PlacementHead::getNozzle(int i) {
return set_[i-1];
}
void PlacementHead::setNozzle(int i, char c) {
set_[i-1] = c;
}
void PlacementHead::markNozzle(int i, int bankPos) {
set_[i-1] = ' ';
from_[i-1] = bankPos;
}
int PlacementHead::getNextUnmarkedPos() {
for (int i=0; i<size_; i++) {
if (set_[i]!=' ') {
return i+1;
}
}
return 0;
}
int PlacementHead::getBankPos(int i) {
return from_[i-1];
}
void PlacementHead::reset() {
//for (int i=0; i<size_; i++) {
// set_[i] = original_[i];
//}
strcpy(set_,original_);
}
void PlacementHead::print() {
std::cout << "placementhead:\n";
for (int h=height_; h>0; h--) {
for (int w=width_; w>0; w--) {
int i = ((h-1)*width_)+w;
std::cout << getNozzle(i);
}
std::cout << "\n";
}
}
If I try to run the main.cpp, I get this:
Once I got this also (I don't get this every time, which bugs me...):
Now here is also one thing to take into account: If I comment out the second line where PlacementHead h2-object is created the code runs okay, but IF I create more than one PlacementHead-objects the program crashes again...
Any advices what might be causing this?
Thank you for any help!! =)
P.S.
My platform is Windows 7, Codeblocks 12.11 and GNU GCC Compiler
UPDATE:
In case you couldn't see the text on the second picture here it is:
You should
increase size_ by +1 too avoid buffer overrun (or, use std::vector instead, see below)
disable copy construction/assignment
add a proper destructor
use initialization lists
check the order in which members are declared (since this is also the order in which members are initialized!)
remove the default constructor, since it doesn't initialize a single member
include <cstring> instead of <string.h> on modern compilers (so you get namespaces C standard library functions)
Consider using std::vector instead of manual arrays. This will save you much trouble. Think of how you are going to get your constructor exception safe?
Here is a sample fixing all of the above:
#include <iostream>
#include <vector>
#include <cstring>
struct PlacementHead {
int width_, height_, gap_;
size_t size_;
std::vector<char> set_, original_;
std::vector<int> from_;
PlacementHead(int width, int height, int gap, const char* s) :
width_(width),
height_(height),
gap_(gap),
size_(width * height),
set_(s, s + std::min(strlen(s), size_)),
original_(set_),
from_(size_)
{
set_.resize(size_);
original_.resize(size_);
}
size_t getSize() { return size_; }
int getHeight() { return height_; }
int getWidth() { return width_; }
int getGap() { return gap_; }
char getNozzle(int i) { return set_[i - 1]; }
void setNozzle(int i, char c) { set_[i - 1] = c; }
void markNozzle(int i, int bankPos) {
set_[i - 1] = ' ';
from_[i - 1] = bankPos;
}
int getNextUnmarkedPos() {
for(unsigned i = 0; i < size_; i++) {
if(set_[i] != ' ') {
return i + 1;
}
}
return 0;
}
int getBankPos(int i) { return from_[i - 1]; }
void reset() {
//for (int i=0; i<size_; i++) {
// set_[i] = original_[i];
//}
set_ = original_;
}
void print() {
std::cout << "placementhead:\n";
for(int h = height_; h > 0; h--) {
for(int w = width_; w > 0; w--) {
int i = ((h - 1) * width_) + w;
std::cout << getNozzle(i);
}
std::cout << "\n";
}
}
};
// Main
int main (int argc, char * const argv[]) {
PlacementHead h1(4,2,1,"aabcbbca");
PlacementHead h2(4,2,1,"babcabca");
return 0;
}
size_ = width*height; should be size_ = (width*height)+1; so the string can be null terminated. Currently you are writing to unallocated memory causing undefined behaviour
You have an off-by-one error in your constructor, as the strings you try to copy are not 8 characters, they are 9. The reason is that all string literals are also containing an extra special string termination character.
If you're using strings in C++, use std::string, it will help you tremendously with problems like these.
Related
Trying to get this to work, but CodeBlocks gives me this error:
error: no matching function for call to 'max(char[4][10], int)'
Tried getting rid of template <>, made function to receive char*, nothing works.
How do I make this function to receive an array of strings (char[]), and spit out the longest one?
EDIT: Yeah, I missed that thing with index, now corrected. The problem is not gone.
#include <iostream>
#include <cstring>
template<class number>
number max(number numbers[], int n)
{
number maximum = numbers[0];
for (int i = 1; i < n; i++)
{
if (numbers[i] > maximum)
maximum = numbers[i];
}
return maximum;
}
template<>
char* max (char** strings, int n)
{
int maxlen = strlen(strings[0]);
int maxind = 0;
for (int i = 1; i < n; i++)
{
if (strlen(strings[i]) > maxlen)
{
maxlen = strlen(strings[i]);
maxind = i;
}
}
return strings[maxind];
}
int main()
{
char strings[4][10] = {"Cat", "Dog", "CANNIBALS", "Witch"};
int test_int[4] = {1, 2, 3, 4};
double test_dble[5] = {1.2, 3.1, 5223e11, 23, -1000.0};
std::cout << "int max(): " << max(test_int, 4) << std::endl;
std::cout << "double max(): " << max(test_dble, 5) << std::endl;
std::cout << "char** max(): " << max(strings, 4) << std::endl;
return 0;
}
If we simplify your code a lot we can boil it down to this:
#include <cstring>
char* max(char** strings, int n) { return nullptr; }
int main() {
char strings [4][10] = {"Cat","Dog","CANNIBALS","Witch"};
max(strings, 4);
return 0;
}
As Avi Berger pointed out char[4][10] isn't convertible to char**. The following would compile:
#include <cstring>
char* max(char (&strings)[4][10], int n) { return nullptr; }
int main() {
char strings [4][10] = {"Cat","Dog","CANNIBALS","Witch"};
max(strings, 4);
return 0;
}
Obviously this is only useful for char[4][10], you could make it more generic like this:
#include <cstring>
template <int a, int b>
char* max(char (&strings)[a][b], int n) { return nullptr; }
int main() {
char strings [4][10] = {"Cat","Dog","CANNIBALS","Witch"};
max(strings, 4);
return 0;
}
Now that we have a and b there is no point in passing in n, it might as well reduce to this:
#include <cstring>
template <int a, int b>
char* max(char (&strings)[a][b]) { return nullptr; }
int main() {
char strings [4][10] = {"Cat","Dog","CANNIBALS","Witch"};
max(strings);
return 0;
}
I have problem only with the push_back function, the compiler said:
CRT detected that the application wrote to memory after end of heap buffer
I want to make a push_back function, that adds a new element to the vector's end.
#pragma once
#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstdlib>
class tomb {
private:
double *adat;
int szam;
public:
tomb(){
adat = NULL;
szam = 0;
}
int meret()const {
return szam;
}
~tomb() {
delete[] adat;
}
double & operator[](int n) {
return adat[n];
}
const double & operator[](int n)const {
return adat[n];
}
void push_back(const double &a) {
double *tmp;
int pos = szam + 1;
tmp = new double[szam+1];
for (int i = 0; i < szam; i++)
{
tmp[i] = adat[i];
}
tmp[pos] = a;
delete[] adat;
adat = tmp;
++szam;
}
void Kiir()const {
for (int i = 0; i < szam; i++)
{
std::cout << adat[i] << "\n";
}
}
};
pos should be szam not szam+1. You are willing to insert at the last position, which in 0-based indexing is n-1.
The problem is in this line:
tmp[pos] = a;
Since pos is initialized to szam + 1, that is equivalent to:
tmp[szam + 1] = a;
which is one out of the array limit.
The solution is to get rid of pos altogether and just do:
tmp[szam] = a;
BTW, your class is using the default copy constructor and assignment operator, and those will not work properly. You should really do something about that.
I am making a console game and I am making a map. The map is an array of vectors. The vectors contain the characters that I am printing to the console. My code:
"Window.h"
#include <string>
#include <vector>
class Row {
public:
std::vector<char> row;
int id;
Row();
void printRow();
void resetRow();
void insertStringIntoRow(std::string toInsert, int startIndex);
std::vector<char> getRow() {
return row;
}
};
class Window {
public:
void showMap();
void writeToMap(std::string stringToInsert, int rowNum, int startIndex);
void writeInRectangle(std::string stringToWrite, int rowNum, int startIndex);
void setCursorToPosition(int x, int y);
void resetMap();
Row getRowAt(int index);
};
void initColors();
void setWindow(Window windowToSet);
Window getGameWindow();
"Window.cpp"
#include "Window.h"
#include <iostream>
#include <Windows.h>
#include <WinBase.h>
#include <stdlib.h>
#include "color.h"
using namespace eku;
Row map[25];
//Class Window
void Window::showMap() {
setCursorToPosition(0, 0);
for (int i = 0; i < 25; i++) {
getRowAt(i).printRow();
}
}
void Window::writeToMap(std::string stringToInsert, int rowNum, int startIndex) {
Row r = getRowAt(rowNum);
r.insertStringIntoRow(stringToInsert, startIndex);
}
void Window::writeInRectangle(std::string stringToWrite, int rowNum, int startIndex) {
if (startIndex != 0) {
std::string topbar = "~";
for (int i = 0; i < stringToWrite.length() + 2; i++) {
topbar += ' ';
}
topbar += '^';
getRowAt(rowNum - 1).insertStringIntoRow(topbar, startIndex - 1);
}
std::string toInsert = "~ ^" + stringToWrite + "~ ^";
getRowAt(rowNum).insertStringIntoRow(toInsert, startIndex - 1);
if (startIndex != 25) {
std::string bottombar = "~";
for (int i = 0; i < stringToWrite.length() + 2; i++) {
bottombar += ' ';
}
bottombar += '^';
getRowAt(rowNum + 1).insertStringIntoRow(bottombar, startIndex - 1);
}
}
void Window::setCursorToPosition(int x, int y) {
HANDLE hOut;
COORD Position;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
Position.X = x;
Position.Y = y;
SetConsoleCursorPosition(hOut, Position);
}
void Window::resetMap() {
for (Row row : map) {
row.resetRow();
}
}
Row Window::getRowAt(int index)
{
return map[index];
}
//Class Row
const char WHITEBACKCOL = '~';
const char DEFCOL = '^';
int i = 0;
Row::Row() {
row.resize(80, ' ');
id = i;
i++;
}
void Row::printRow() {
for (int i = 0; i < row.size(); i++) {
switch (row[i]) {
case WHITEBACKCOL:
setcolor(black, white);
case DEFCOL:
setcolor(white, black);
default:
std::cout << row[i];
}
}
}
void Row::resetRow() {
row.resize(80);
for (int i = 0; i < 80; i++) {
row[i] = ' ';
}
}
void Row::insertStringIntoRow(std::string toInsert, int startIndex) {
int endIndex = (startIndex + toInsert.length());
int stringPos = 0;
for (int i = startIndex; i < endIndex; i++) {
if (i < row.size() - 1) {
row.at(i) = toInsert[stringPos];
}
else {
row.push_back(toInsert[stringPos]);
}
stringPos++;
}
}
Window defWindow;
void initColors() {
concolinit();
setcolor(white, black);
}
void setWindow(Window windowToSet) {
defWindow = windowToSet;
}
Window getGameWindow() {
return defWindow;
}
"Main.cpp"
#include <iostream>
#include "GameEngine.h"
#include "Window.h"
int main() {
setWindow(Window());
initColors();
getGameWindow().writeInRectangle("Hia", 1, 10);
getGameWindow().showMap();
}
Whenever I call showMap() all I get is a blank console. It seems to be only printing the default map of spaces instead of the text I entered. I also tried using just printRow() to print the single rows that I edited but they also showed only spaces.
I was able view changes to the vector row in the insertStringIntoRow() method but then even though the changes should there they didn't show anywhere else. It almost seems like my Row object is being created every time I access it. I am new to C++ so any help is appreciated. Thanks in advance!
This function is being used incorrectly. Warning signs are that it is non-const, yet used as an accessor. It returns a copy of the vector, not a reference.
std::vector<char> getRow() {
return row;
}
The way you are calling it, you are expecting it to modify the row in-place, but all you are actually doing is modifying a copy of the row, which is then immediately discarded. Example:
getRowAt(rowNum).insertStringIntoRow(toInsert, startIndex - 1);
The easy fix for this behaviour is to return a reference from getRow():
std::vector<char> & getRow() {
return row;
}
The other thing to fix is where you assign this to a temporary variable instead of using it inline. In that case, you can make the temporary a reference:
Row & r = getRowAt(rowNum);
r.insertStringIntoRow(stringToInsert, startIndex);
The correct way to implement this is to also provide a const-version, so that it can still be called on const objects where the caller does not want to modify it.
const std::vector<char> & getRow() const {
return row;
}
I've only put this extra bit in here because it is good practice, but you should not do it in this program. It would clutter your code which is already full of worse practices =)
send a reference to writeToMap() instead of variables.
This will make changes to the original map objects instead of copy-variables.
this my Library.h file, before the Library used to do All the dirty work: in term of manipulating the arrays and stuff, but now I am trying to make the Library the middle man that just invoke the call that has to do with any array manipulations. My problem is I am trying to have one instance of Patron array, that would hold all the patrons in the Library.
#ifndef LIBRARY_H
#define LIBRARY_H
#include <string>
#include "types.h"
#include "Book.h"
#include "Patron.h"
#include "PatronArray.h"
//class PatronArray
class Library
{
public:
Library();
~Library();
void init();
int addBook(Book*);
int addPatron(Patron*);
int remPatron(int);
int findBook(int, Book**, int*);
int findPatron(string, string, Patron**, int*);
int getMaxCollIndex();
int getMaxPatronsIndex();
Book* getBook(int);
Patron* getPatron(int);
private:
Book* collection[MAX_COLL_SIZE];
PatronArray* patrons;
int maxCollIndex;
int maxPatronsIndex;
};
#endif
This is my Library.cc file
#include "Library.h"
Library::Library()
: maxCollIndex(0)
{
patrons = new PatronArray;
for (int i=0; i<MAX_COLL_SIZE; ++i) {
collection[i] = 0;
}
}
Library::~Library()
{
delete patrons;
for (int i=0; i<maxCollIndex; ++i)
delete collection[i];
}
int Library::getMaxCollIndex() { return maxCollIndex; }
int Library::getMaxPatronsIndex()
{
return patrons->getMaxPatronsIndex();
}
Book* Library::getBook(int index)
{
if (index < 0 || index >= maxCollIndex)
return 0;
return collection[index];
}
Patron* Library::getPatron(int index)
{
return patrons->getPatron(index);
}
void Library::init()
{
Book* newBook;
Patron* newPatron;
newBook = new Book("Ender's Game", "Orson Scott Card", 1985);
addBook(newBook);
newBook = new Book("Dune", "Frank Herbert", 1965);
newBook->setStatus(LOST);
addBook(newBook);
newBook = new Book("Foundation", "Isaac Asimov", 1951);
addBook(newBook);
newBook = new Book("Hitch Hiker's Guide to the Galaxy", "Douglas Adams", 1979);
addBook(newBook);
newPatron = new Patron("Jack", "Shephard");
addPatron(newPatron);
}
int Library::addBook(Book* book)
{
if (maxCollIndex >= MAX_COLL_SIZE - 1) {
return C_NOK;
}
collection[maxCollIndex++] = book;
return C_OK;
}
int Library::addPatron(Patron* patron)
{
// the lbrary is the middle ma that invokesthe calls
//return patronArray->addPatron(patron);
return patrons->addPatron(patron);
}
int Library::remPatron(int index)
{
return patrons->remPatron(index);
}
int Library::findPatron(string fn, string ln, Patron** patron, int* index)
{
return patrons->findPatron(fn,ln,patron,index);
}
int Library::findBook(int id, Book** book, int* index)
{
for (int i=0; i<maxCollIndex; ++i) {
if (collection[i] == 0)
continue;
if (collection[i]->getId() == id) {
*book = collection[i];
*index = i;
return C_OK;
}
}
*book = 0;
*index = -1;
return C_NOK;
}
This is my PatronArray.h that holds all the Patrons registered within the Library.
#ifndef PATRONARRAY_H
#define PATRONARRAY_H
#include "Patron.h"
#include "Book.h"
#include "types.h"
//class Patron;
class PatronArray
{
public:
PatronArray();
~PatronArray();
int addPatron(Patron*);
int remPatron(int);
int findPatron(string, string, Patron**, int*);
int getMaxPatronsIndex();
Patron* getPatron(int);
private:
Patron* patrons[MAX_COLL_SIZE];
int maxPatronsIndex;
};
#endif
and this is the PatronArray.cc file and please, I know there is better way of doing this by doing templating which I currently dont understand yet plus this way helps me understand the whole object oriented style.
#include<iostream>
#include<string>
#include "PatronArray.h"
/*
* Default constructor: recheck this later
*/
PatronArray::PatronArray()
:maxPatronsIndex(0)
{
for (int i = 0; i < MAX_COLL_SIZE; ++i) {
patrons[i] = 0;
}
}
/*
* Destructor: recheck this later
*/
PatronArray::~PatronArray()
{
for (int i = 0; i < maxPatronsIndex; ++i)
delete patrons[i];
}
//get the maxindex
int PatronArray::getMaxPatronsIndex() { return maxPatronsIndex; }
/*
* Adds the given Patron to the given patrons Array
*/
int PatronArray::addPatron(Patron* patron)
{
if (maxPatronsIndex >= MAX_COLL_SIZE - 1) {
return C_NOK;
}
patrons[maxPatronsIndex++] = patron;
return C_OK;
}
/*
* Used for removing a patron in the patrons array
*/
int PatronArray::remPatron(int index)
{
if (index < 0 || index >= maxPatronsIndex)
return C_NOK;
delete patrons[index];
patrons[index] = 0;
return C_OK;
}
/*
* Searches for the patron; if found, sets the contents of the second
* parameter to that patron pointer, sets the contents of the third parameter to
* its index in the collection, and returns C_OK; if not found, sets the
* contents of the second parameter to zero, the theird to -1, and returns C_NOK
*/
int PatronArray::findPatron( string fn, string ln, Patron** patron, int* index)
{
for (int i = 0; i < maxPatronsIndex; ++i) {
if (patrons[i] == 0)
continue;
if (patrons[i]->getFname() == fn && patrons[i]->getLname() == ln) {
*patron = patrons[i];
*index = i;
return C_OK;
}
}
*patron = 0;
*index = -1;
return C_NOK;
}
Patron* PatronArray::getPatron(int index)
{
if (index < 0 || index >= maxPatronsIndex)
return 0;
return patrons[index];
}
I forgot to link my PatronArray.cc to Library.cc in my makefile, thank you Jack!
I'm a C++ noob, currently trying to create a text based maze game for degree. I'm replacing my currently working array with a vector (for dynamic size) and reading a txt file of chars to it.
PROBLEM: I get no IDE errors, but get RUNTIME ERROR: Debug assertion Failed! Expression: vector subscript out of range!
I have used the pushback instead of RoomFile=data, but I don't know if I need to amend other functions. I read the array/vector data in another class (player) and will include code if needed.
I have searched everywhere to find solution, but can't find any projects using a similar vector structure. What am I doing wrong?
Room.h
#pragma once
#include <vector>
#include "stdafx.h"
class Room
{
private: //data acceessed by functions
char floor;
char wall;
char door;
int width;
int height;
public:
std::vector <char> data;
Room* North;
Room* East;
Room* South;
Room* West;
Room* Next;
int NorthX;
int NorthY;
int EastX;
int EastY;
int SouthX;
int SouthY;
int WestX;
int WestY;
char RoomFile;
//where functions go
Room(void);
void CreateRoom(int RoomNo);
void PrintRoom();
~Room(void);
};
Room.cpp
#include <iostream>
#include <fstream>
#include <streambuf>
#include <string>
#include <sstream>
#include "Room.h"
#include <cstdlib>
using namespace std;
Room::Room(void)
{
floor = ' ';
wall = '#';
door = 'X';
width = 11;
height = 11;
North=0;
East=0;
South=0;
West=0;
Next=0;
NorthX=0;
NorthY=0;
EastX = 0;
EastY = 0;
SouthX= 0;
SouthY=0;
WestX=0;
WestY=0;
}
void Room::CreateRoom(int RoomNo)
{
std::vector<char> data;
char RoomFile[255];
ifstream infile;
stringstream ss;
//LOAD CURRENT ROOM FROM FILE
ss << RoomNo;
string str = ss.str();
string fname = ("Room");
fname.append(str);
fname.append(".txt");
infile.open(fname);
infile.clear();
infile.seekg(0);
if(infile.is_open())
{
while(!infile.eof()) // To get you all the lines.
{
int i;
for(int row = 0; row < width; row++)
{
infile.getline(RoomFile, 256);
i = 0;
for(int col = 0; col < height; col++)
{
data.push_back(RoomFile[i]);
i++;
}
}
}
}
else
{
cout << "ERROR: infile not open" << endl;
}
infile.close();
//ASSIGN DOORS TO ROOMS IF NEEDED
// treating the array as being one-dimensional.
for(int row = 0; row < width; row++)
{
for(int col = 0; col < height; col++)
{
if(North!=NULL)
{
if(data[row*height+col]=='X')
{
//data[row*height+col] = door;
NorthX=row;
NorthY=col;
}
}
if(East!=NULL)
{
if(data[row*height+col]=='X')
{
//data[row*height+col] = door;
EastX = row;
EastY = col;
}
}
if(South!=NULL)
{
if(data[row*height+col]=='X')
{
//data[row*height+col] = door;
SouthX = row;
SouthY = col;
}
}
if(West!=NULL)
{
if(data[row*height+col]=='X')
{
//data[row*height+col] = door;
WestX = row;
WestY = col;
}
}
}
}
}
void Room::PrintRoom()
{
for(int row = 0; row < width; row++)
{
for(int col = 0; col < height; col++)
{
cout << data[col * height + row];
}
cout << "\n";
}
cout << endl;
}
Room::~Room(void)
{
}
Stack Trace
// throw -- terminate on thrown exception REPLACEABLE
#define _HAS_EXCEPTIONS 0
#include <cstdio>
#include <cstdlib>
#include <exception>
#include <crtdbg.h>
_STD_BEGIN
#ifdef _DEBUG
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _Debug_message(const wchar_t *message, const wchar_t *file, unsigned int line)
{ // report error and die
if(::_CrtDbgReportW(_CRT_ASSERT, file, line, NULL, L"%s", message)==1)
{
::_CrtDbgBreak();
}
}
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _Debug_message(const unsigned short *message, const unsigned short *file, unsigned int line)
{ // report error and die
_Debug_message((wchar_t *) message, (wchar_t *) file, line);
}
#endif
_STD_END
I think this is the error: What you are printing in PrintRoom is the std::vector<char> data inside your class, while the std::vector<char> data that you filled up is local to CreateRoom method.
void Room::CreateRoom(int RoomNo)
{
std::vector<char> data; // remove this to solve
In your PrintRoom() function, you have
cout << data[col * height + row];
instead of
cout << data[row * height + col];