c++ program crashing because of if statment [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
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.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
My c++ program is crashing i think because of an if statement. I am using MinGW compiler and am given no errors. I have no idea as to why i am getting the error. The if statement in my generate function looks fine to me. Im comparing a string with an instance of a vector string.
here is the cpp code:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
#include "Insultgenerator_0hl14.h"
using namespace std;
FileException::FileException(const string& m) : message(m){}
string& FileException::what(){ return message;}
NumInsultsOutOfBounds::NumInsultsOutOfBounds(const string& m) : message(m){}
string& NumInsultsOutOfBounds::what(){ return message;}
InsultGenerator::InsultGenerator(const InsultGenerator& ) {};
InsultGenerator::InsultGenerator(){};
void InsultGenerator::initialize() {
int cols(0);
srand ( time(NULL));
string words ;
string filename("InsultsSource.txt");
ifstream filetoread(filename.c_str());
if(filetoread.fail()){
throw FileException("File not read.");
}
while(filetoread >> words){
if(cols==0){
colA.push_back(words);
cols++;
} else if(cols==1){
colB.push_back(words);
cols++;
}else{
colC.push_back(words);
cols= cols -2;
}
}
//for (int i=0;i<50;i++){
// cout << " "<< colA[i];
//}
}
string InsultGenerator::talkToMe() const{
string Thou = "Thou";
string a= Thou + " " + colA[(rand()%50)] + " " + colB[rand()%50] + " " + colC[rand()%50] +"!" ;
//cout << a << endl;
return a;
};//end talkToMe
vector<string> InsultGenerator::generate(const int num){
if (num<0){
throw NumInsultsOutOfBounds("You must be insulted at least once");
} else if (num >10000 ){
throw NumInsultsOutOfBounds("You are being insulted too many times!");
}
vector<string> insultList;
string list;
for(int i=0; i<num;i++ ){
list = talkToMe();
if(list != insultList[i]){
//insultList.push_back(list);
//cout << insultList[i]<< endl;
}
}
return insultList;
};//end generate
//int InsultGenerator::generateAndSave(const string filename, const int n) const{
//};//end generateAndSave
int main(){
InsultGenerator ig;
ig.initialize();
ig.talkToMe();
ig.generate(10);
}
Here is the header file :
#ifndef INSULTGENERATOR_0HL14_H_
#define INSULTGENERATOR_0HL14_H_
#include <string>
#include <vector>
using namespace std;
class InsultGenerator{
public:
InsultGenerator();
InsultGenerator(const InsultGenerator&);
void initialize() ;
string talkToMe() const;
vector<string> generate(const int) ;
int generateAndSave (const string, const int) const;
private:
vector<string> colA;
vector<string> colB;
vector<string> colC;
};
class FileException{
public:
FileException(const string&);
string& what();
private:
string message;
};
class NumInsultsOutOfBounds{
public:
NumInsultsOutOfBounds(const string &);
string& what();
private:
string message;
};
#endif

As soon as you call the operator[] on your vector, you are trying to access an element of your vector. In this case the vector is empty, which cause an undefined behaviour.
if(list != insultList[i]){
Before trying to access your vector, make sure that this one is initialized with some values.
The index (i) you are looking for must be lower than the size of the vector insultList.size() (since the indexing start at 0)

You're declaring insultList to be of type vector<string>:
vector<string> insultList;
Then you're trying to access elements of insultList:
if(list == insultList[i]){
//insultList.push_back(list);
//cout << insultList[i]<< endl;
}
But nowhere in between do you actually add anything to insultList -- how many elements does it have? Trying to access insultList[i] refers to unallocated memory which is causing your program crash.

Related

Random string from vector C++ [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I have a question about this code. I got what I was expecting but I don't understand why sometimes I get the result and sometimes not.
In this case, the output suppose to show the word "dive" every time I run the code but sometimes the output is not giving me any value.
Is it because the if statement? How can I get always the result("dive") and not sometimes?
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
using namespace std;
int main()
{
srand(time(NULL));
vector <string> Words = {"dive", "friends", "laptop"};
string n_words = Words[rand() % Words.size()];
for(int i = 0; i < 1; i++)
{
if(n_words.length() <= 4)
{
cout << n_words << endl;
}
}
}
EDIT ANOTHER EXAMPLE:
I would like to pick up a random word not longer than 4 letters from a list of words with differents lengths. When I run my code sometimes I get "dive" sometimes "lego" and sometimes nothing. Is there any way to get always some of this two values ?
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
using namespace std;
int main()
{
srand(time(NULL));
vector <string> Words = {"dive", "table", "laptop", "lego", "friends"}
string n_words = Words[rand() % Words.size()];
for(int i = 0; i < 1; i++)
{
if(n_words.length() <= 4)
{
cout << n_words << endl;
}
}
}
Personally I would copy to a secondary temporary vector, shuffle it, and get the first element of that vector.
And I would have put it in a separate function.
In code something like this perhaps:
std::string select_random_short_word(std::vector<std::string> const& long_words)
{
// Create a vector and copy all "short" words to it
std::vector<std::string> short_words;
std::copy_if(begin(long_words), end(long_words), std::back_inserter(short_words),
[](std::string const& w) { return w.length() <= 4; });
// Make sure there are any short words
if (short_words.size() == 0)
{
return ""; // Nope, no short words
}
// Randomly shuffle the short words
std::random_device device;
std::default_random_engine engine(device());
std::shuffle(begin(short_words), end(short_words), engine);
// Return a random short word
return short_words[0];
}
This will reduce your main function to simply:
int main()
{
std::vector<std::string> words = {"dive", "table", "laptop", "lego", "friends"};
std::cout << select_random_short_word(words) << '\n';
}

What is the problem I am having with using arrays with classes?

I have been working on a project for my computer science class and have encountered an issue with the code working. I am shown no error except when I try to compile and I get an error that reads:
Exception thrown: write access violation.
_Left was 0xCCCCCCCC.
The purpose of my project is to take a list of names from an external file, read them into an array, sort said array and then output the sorted list all while using a class for the code.
Here is a copy of my code and I would like to extend my gratitude to whoever can help me through my issue:
**Header File**
#include <iostream>
using namespace std;
class person
{
public:
person();
bool get(ifstream&);
void put(ofstream&);
private:
int capacity = 0;
string first_name[CAPACITY];
string last_name[CAPACITY];
int age[CAPACITY];
};```
**Header function definitions cpp file**
#include<iostream>
#include<string>
#include<fstream>
#include<cstdlib>
const int CAPACITY=20;
using namespace std;
#include "Person.h"
//Names constructor
//Postcondition both first name and last name initialized to zero
person::person()
{
first_name[CAPACITY] = "";
last_name[CAPACITY] = "";
age[CAPACITY]=0;
}
bool person::get(ifstream& in)
{
in >> first_name[CAPACITY] >> last_name[CAPACITY] >> age[CAPACITY];
return(in.good());
}
void person::put(ofstream &out)
{
out << first_name[CAPACITY] << last_name[CAPACITY] << age[CAPACITY];
}
**cpp file which holds main**
#include<iostream>
#include<cstdlib>
#include<fstream>
#include<string>
const int CAPACITY = 20;
using namespace std;
#include "Person.h"
void pop(string *xp, string *yp);
void sort(string name[CAPACITY], int count);
int main()
{
class person names[CAPACITY];
ifstream infile;
ofstream outfile;
string filename;
string name[CAPACITY];
int n = 0;
cout << "Enter the file name you wish to open" << endl;
cin >> filename;
infile.open(filename + ".txt");
outfile.open("Person_New.txt");
if (infile.fail())
{
cout << "The file requested did not open" << endl;
exit(1);
}
while (!infile.eof())
{
names[n].get(infile);
n++;
}
sort(name, CAPACITY);
for (int i = 0; i < CAPACITY; i++)
{
names[i].put(outfile);
}
cout << "The file has been created" << endl;
infile.close();
}
void pop(string *xp, string *yp)
{
string temp = *xp;
*xp = *yp;
*yp = temp;
}
void sort(string name[CAPACITY], int count)
{
int i, j;
for (i = 0; i < count - 1; i++)
{
for (j = 0; j < count - i - 1; j++)
{
if (name[j] > name[j + 1])
{
pop(&name[j], &name[j + 1]);
}
}
}
}
Once again Thank you for any support
It sounds to me like the compiler is getting upset that you are trying to write (i.e. assign a value) at an address that you do not have permission to access. I believe your constructor for the class person might be at fault because of how this class stores its variables, as well as the class header:
Constructor for the class person:
`person::person(){
first_name[CAPACITY] = "";
last_name[CAPACITY] = "";
age[CAPACITY] = 0;
}`
Class header for the class person:
`class person{
public:
//stuff
private:
int capacity = 0;
std::string first_name[CAPACITY];
std::string last_name[CAPACITY];
int age[CAPACITY];
//more stuff
}`
C++ is very specific about its naming conventions, so it makes a distinction between capacity and CAPACITY. Because of this, the variable CAPACITY is not defined within the Person.h file.
Also, because CAPACITY is set to a fixed value in your Person.cpp file, whenever you use first_name[CAPACITY], last_name[CAPACITY], or age[CAPACITY] to assign new values, you are only updating the values at the index equal to CAPACITY unless you update the value of CAPACITY itself. In the code you provided, CAPACITY is equal to 20, so your program attempts to update exclusively index 20 with each method call. This will likely cause issues since the person class only attempts to make its arrays on the runtime stack, with a size of 0 each.
Separately, it seems like you want an array of people, but it appears that you are attempting to use a single person object to store the names and ages of multiple people by making these all arrays. Instead, I would recommend making first_name, last_name, and age not arrays, but rather single variables. Then, you can manipulate an array of type person using your CAPACITY variable. You got pretty close, but you can instead declare it as person myPersonArray[CAPACITY] (no need to mention "class" in front of it -- just be sure that you have #include "Person.h" in your main.cpp file). When you want to update a specific person, you can perform an operation like myPersonArray[updateThisIndexNum].update(newFirstName, newLastName, newAge) or some logical equivalent.
As a final note, I almost always highly recommend against using !infile.eof() to control your while loop when reading any file because eof() only indicates whether you have tried to read past the end of an input file. I would highly recommend checking out this post on Stack Overflow where people far more knowledgeable than I explain exactly why this is usually dangerous and how to avoid it.

C++ - List is not keeping its elements [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 4 years ago.
Improve this question
I have 2 classes; TestUnit and TestShot.
TestUnit needs to hold a list of TestShots, however when I reference the list later on all the elements I've given it have disappeared!
TestUnit.h
#include <string>
#include <list>
#include "TestShot.h"
using namespace std;
class TestUnit
{
public:
TestUnit(string);
string getName(void);
void addShot(TestShot);
list<TestShot> getShots(void);
bool operator == (const TestUnit& tu) const { return name == tu.name; }
bool operator != (const TestUnit& tu) const { return !operator==(tu); }
private:
string name;
list<TestShot> shots;
};
TestUnit.cpp
#include "TestUnit.h"
TestUnit::TestUnit(string name)
{
this->name = name;
}
string TestUnit::getName(void)
{
return name;
}
void TestUnit::addShot(TestShot shot)
{
shots.push_front(shot);
}
list<TestShot> TestUnit::getShots(void)
{
return shots;
}
TestShot.h
#include <string>
using namespace std;
class TestShot
{
public:
TestShot(string);
string getName(void);
private:
string name;
};
TestShot.cpp
#include "TestShot.h"
TestShot::TestShot(string name)
{
this->name = name;
}
string TestShot::getName(void)
{
return name;
}
MAIN
#include <string>
#include "exports.h"
#include "TestUnit.h"
using namespace std;
// Global Variables
list<TestUnit> testUnits;
int main()
{
int nShots1 = 0;
int nShots2 = 0;
// Create Unit
TestUnit *testUnit = new TestUnit("Name");
testUnits.push_front(*testUnit);
// Create Shot and add to Unit with same 'name'
TestShot *testShot = new TestShot("Name");
for (TestUnit unit : testUnits)
{
if (unit.getName() == (*testShot).getName())
{
unit.addShot(*testShot);
nShots1 = unit.getShots().size();
}
}
// Display number of Shots for each Unit
for (TestUnit unit : testUnits)
{
nShots2 = unit.getShots().size();
std::cout << nShots1 << ", " << nShots2 << std::endl;
}
system("PAUSE");
};
Output:
1, 0
So the list realises that it's been populated straight after adding to it, but it's then empty when I need to use it.
I'm guessing this is a scope problem, but I can't seem to figure it out.
All help is much appreciated!
In each of your for loops, you're accessing the list elements by value, so you're effectively making a copy of what's in the list, modifying that, and then destroying it. Change your loops to look like this:
for (TestUnit &unit : testUnits)
{
if (unit.getName() == (*testShot).getName())
{
unit.addShot(*testShot);
nShots1 = unit.getShots().size();
}
}
Since you're using C++11 or later, you could also use auto instead of explicit typing (e.g., auto &unit: testUnits).

First time writing header file and .cpp from existing main; no output [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
It's my first time creating a header and cpp file for an existing main. I can get the program to run, but there's no output. If anyone can help me troubleshoot, i would much appreciate it. The program is supposed to simulate an elevator. thanks!
Here is what i was given:
int main()
{
elevator aLift(1);
aLift.select(5);
aLift.select(3);
system("pause");
return 0;
}
Here is my header file.
#ifndef elevator_h
#define elevator_h
#include <string>
using namespace std;
class elevator {
public: //operations
elevator();
//coonstructors
elevator (int initFloor);
//modifiers
void select (int newFloor);
//my floor is increased/decreased by difference.
//accessors
int getFloor() const;
//gets current floor number
private: //state
int my_floor;
int selected_floor;
};
#endif // ifndef elevator_h
Lastly, here's my cpp file
#include "elevator.h"
#include <string>
#include <iostream>
using namespace std;
int selected_floor;
elevator;
elevator::elevator (int initFloor)
//coonstructors
{
my_floor=initFloor;
}
//modifiers
void elevator::select (int)
{
while(my_floor < selected_floor)
cout << "Going up to " << ++my_floor << endl;
}
//my floor is increased/decreased by difference.
//accessors
int elevator::getFloor() const
{
return selected_floor;
}
Global variables are initialized 0, see here.
So your selected_floor is 0 and smaller as my_floor.
Edit:
At first glance I missed you have a member selected_floor and a global one. I think you don't need the global one.
What you are missing is:
// don't forget the default constructor
elevator::elevator ()
: my_floor(0)
, selected_floor(0)
{}
elevator::elevator (int initFloor)
: my_floor(initFloor)
, selected_floor(0)
{}
//modifiers
void elevator::select (int newFloor)
//^^^^^^^^
{
selected_floor = newFloor; // set you selected_floor to the value you want to select
//^^^^^^^^^^^^^^^^^^^^^^^^^^
while(my_floor < selected_floor)
cout << "Going up to " << ++my_floor << endl;
}
There are couple of things not clear.
From the cpp.
int selected_floor; // You have a global variable with the same name as a private variable. Anything specific you intend to do?
elevator; //This should not even compile.
What is this ?
//modifiers
void elevator::select (int)
Maybe you wanted something like this.
void elevator::select (int floor) {
selected_floor = floor;
Get rid of the global variable and make the change to ::select, it should be ok.
It will not execute because you have not initiated selected_floor and you are using it , it has a value of 0 . So when you are running the loop the "my_floor" which has a initial value of 1 is being tested against zero which is already greater than zero , that is there is no output on the screen .
What you should do is , first assign a value to selected_floor and then call the select function . you can assign the value to selected_floor in the select function itself before executing the loop .
void elevator::select (int newFloor)
{
selected_floor = newFloor ;
while(my_floor < selected_floor)
cout << "Going up to " << ++my_floor << endl;
}

wrong answer from boolean function [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
My boolean function check_gift is not working properly.
I copied a txt file into the vector giftstore. Now I want to check if a given item is in the store. To test the function check_gift I took an item from the actual txt file but the function gives the wrong answer. It returns false instead of true.
What am I doing wrong?
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstdlib>
#include <string>
#include <cassert>
using namespace std;
typedef vector<string> Wishes;
int size(Wishes& w){ return static_cast<int>(w.size()); }
struct Wishlist
{
double budget;
Wishes wishes;
};
struct Gift
{
double price;
string name;
};
typedef vector<Gift> Giftstore;
int size(Giftstore& g) { return static_cast<int>(g.size()); }
void read_wishlist_into_struct(ifstream& infile, Wishlist& wishlist)
{
double b;
infile>>b;
wishlist.budget=b;
int i=0;
string name;
getline(infile,name);
while(infile)
{
wishlist.wishes.push_back(name);
i++;
getline(infile,name);
}
infile.close();
}
void show_wishlist(Wishlist wishlist)
{
cout<<"Budget: "<<wishlist.budget<<endl<<endl;
cout<<"Wishes: "<<endl;
for(int i=0; i<size(wishlist.wishes); i++)
{
cout<<wishlist.wishes[i]<<endl;
}
cout<<endl;
}
void read_giftstore_into_vector(ifstream& infile, Gift& gift, Giftstore& giftstore)
{
double p;
string name;
int i=0;
infile>>p;
while(infile)
{
gift.price=p;
getline(infile,name);
gift.name=name;
giftstore.push_back(gift);
i++;
infile>>p;
}
infile.close();
}
void show_giftstore(Giftstore giftstore)
{
cout<<"All possible gifts in giftstore: "<<endl<<endl;
for(int i=0; i<giftstore.size(); i++)
{
cout<<giftstore[i].price<<"\t"<<giftstore[i].name<<endl;
}
cout<<endl;
}
bool check_gift(Giftstore giftstore, string giftname)
{
int i=0;
while(i<size(giftstore))
{
if(giftstore[i].name==giftname)
{
cout<<"Yes"<<endl;
return true;
}
else
{
i++;
}
}
return false;
}
void clear(Wishlist& b)
{
b.budget=0;
while(!b.wishes.empty())
{
b.wishes.pop_back();
}
}
void copy(Wishlist a, Wishlist& b)
{
b.budget=a.budget;
for (int i=0; i<size(b.wishes); i++)
{
b.wishes.push_back(a.wishes[i]);
}
}
int main ()
{
ifstream infile2("giftstore.txt");
Gift gift;
Giftstore giftstore;
read_giftstore_into_vector(infile2, gift, giftstore);
show_giftstore(giftstore);
string giftname;
giftname="dvd Up van Pixar";
bool x;
x=check_gift(giftstore, giftname);
cout<<"in store?: "<<x<<endl;
return 0;
}
Learn how to debug. If you cannot trace line-by-line through your code, then try to keep some kind of log.
For now at least output this to the console.
In your case
1. Verify the input file opened successfully
2. Print out each gift as you read it in.
would be a good way to start.
If you want to be able to put multiple log statements in and then remove them later, you can use a macro which can be turned off in one place.
Logging is a fairly tricky skill to be effective for large projects which continue to run into production, however you should learn how to do it in the short-term to debug your program.
We here cannot even see what is in your input file. This is why people are downvoting your question.
Ok: Now you've told me your issue is you need to trim whitespace from the front of each string you read in.
There are multiple ways to do that but
trimmed = s.substr( s.find_first_not_of(" \n\r\t" ) );
will probably work for now.
However my original answer still holds: please learn to debug. If you'd outputted the strings as you read them in, you would have seen these leading spaces.