Read access violation? - c++

I am writing some C++ code to create an item of a class i have created inside a vector of another class. I seem to be able to create the items inside the vector but when i try to read a variable of the item inside the vector i get the error
Exception thrown: read access violation.
_Right_data was 0x8.
inside the document xstring.
I think it might have something to do with me not actually creating each team inside the vector.
the code i have written that is relavent is
for (int x = 1; x <= mainLeague.getNumTeams(); x++) {
std::cout << "please enter the name of team " << x << ":";
std::getline(std::cin, currLine);
parsed = parseText(currLine, &posResponsesTeamNames);
if (parsed == 2) {
prepForEnd();
return 1;
}
else if (parsed == 0) goto enterTeamNames;
mainLeague.createTeam(currLine);
}
std::cout << mainLeague.getName(5);
}
#pragma once
#include "team.h"
#include <string>
#include <vector>
#include <iostream>
class league
{
std::vector<team*> teams;
int numTeams, numInitTeams = 0;
const float sysCon = 0.5;
public:
league(int a);
int getNumTeams();
void initVector(int numTeams);
void createTeam(std::string name);
std::string getName(int num);
};
void league::createTeam(std::string name)
{
if (numInitTeams < teams.size()) {
team currTeam = team::team(name);
teams.at(numInitTeams) = &currTeam;
numInitTeams;
}
else {
std::cout << "error max amount of teams already created";
}
}
#pragma once
#include<string>
class team
{
float RD;
int rating;
std::string name;
public:
team(std::string name);
team();
std::string getName();
};
std::string team::getName()
{
return team::name;
}

Related

Create Multiple Objects in a loop c++

I'm a beginner and was researching to find out if you can grab a name from an array to then put that name as the name of the object in a for loop.
The code a specifically created for this question is represented below:
#include <iostream>
using namespace std;
class YourMum{
public:
string name;
YourMum(string aName){
name = aName;
}
};
int main()
{
string names[5] = {"Jeremy_Clarkson", "Boris_Johnson", "Vladmir_Putin", "Peter_Griffin", "MeAndYourMum"};
for(int i = 0; i < 4; i++) {
YourMum names[i];
cout << names[i].name << endl;
cout << "You are great if you answer my question!";
}
return 0;
}
Okay, it's not clear what you're trying to do, but you've got a few things that aren't a good idea.
First, you defined string names[5] and then inside loop you hid names by making a second variable with the same name. While that's legal, it's a bad practice.
Second, you're using the second one (YourMum names) illegally:
You declared it as length i (using a non-standard feature of the compiler) but then reference element i. The elements of an array of length i range from 0..i-1, so [i] is one element past the end.
And you haven't initialized it anyway.
I'm not really clear what you're trying to do, so I can't even provide example code of how to do it.
The YourMum class you have shown is not default constructible, so YourMum names[size]; will not work. Every object of YourMum needs to be passed a parameter in order to create it. You can use placement-new for that, eg:
#include <iostream>
#include <type_traits>
using namespace std;
class YourMum{
public:
string name;
YourMum(string aName){
name = aName;
}
};
int main()
{
string names[5] = {"Jeremy_Clarkson", "Boris_Johnson", "Vladmir_Putin", "Peter_Griffin", "MeAndYourMum"};
std::aligned_storage<sizeof(YourMum), alignof(YourMum)>::type arr[5];
YourMum *mums = reinterpret_cast<YourMum*>(arr);
for(int i = 0; i < 5; i++) {
new (&mums[i]) YourMum(names[i]);
}
for(int i = 0; i < 5; i++) {
cout << mums[i].name << endl;
cout << "You are great if you answer my question!";
}
for(int i = 0; i < 5; i++) {
mums[i].~YourMum();
}
return 0;
}
Or, you can use std::vector instead:
#include <iostream>
#include <vector>
using namespace std;
class YourMum{
public:
string name;
YourMum(string aName){
name = aName;
}
};
int main()
{
string names[5] = {"Jeremy_Clarkson", "Boris_Johnson", "Vladmir_Putin", "Peter_Griffin", "MeAndYourMum"};
std::vector<YourMum> mums;
mums.reserve(5);
for(int i = 0; i < 5; i++) {
mums.emplace_back(names[i]);
}
for(int i = 0; i < 5; i++) {
cout << mums[i].name << endl;
cout << "You are great if you answer my question!";
}
return 0;
}
First of all, you should rename the name variable to something like _name or name_ for lisibility (to differenciate it from variables that aren't in the class), and you should also use the private section of your class to declare it and use getters/setters functions to edit it. Secondly, in your code you are declaring the object inside a loop, so it will get destroyed as soon as the loop iterates again, so if you want to create n objects in a loop and interact with them after you should either use a container class (like std::vector) or use a default constructor (which is better). Here is an updated version of your code:
#include <iostream>
#include <string>
class YourMum
{
public:
YourMum(void) : _name() { }
YourMum(std::string name) : _name(name) { }
std::string getName(void) const { return _name; }
void setName(std::string name) { _name = name; }
private:
std::string _name;
};
int main()
{
std::string names[5] = { "Jeremy_Clarkson", "Boris_Johnson", "Vladmir_Putin", "Peter_Griffin", "MeAndYourMum" };
YourMum mums[5];
for (int i = 0; i < 5; i++)
{
mums[i].setName(names[i]);
std::cout << mums[i].getName() << std::endl
<< "You are great if you answer my question!" << std::endl;
}
// this way you can still access mums here if you want to
return 0;
}
If you want to access to a class by it's name as index what you can also do is using std::map like this
#include <map>
int main()
{
std::string names[5] = { "Jeremy_Clarkson", "Boris_Johnson", "Vladmir_Putin", "Peter_Griffin", "MeAndYourMum" };
std::map <std::string, YourMum> mums;
for (int i = 0; i < 5; i++)
mums[names[i]] = YourMum(names[i]);
std::cout << mums["Jeremy_Clarkson"].getName() << std::endl;
return 0;
}
Try This
> for(int i = 0; i < 4; i++) {
> YourMum name(names[i]);
>
> cout << name.name << endl;
> cout << "You are great if you answer my question!";
> }

Trouble with how to declare (or define) a function in a header

I'm struggling with implementation of a function that I define in my header file of my c++ program. I think I am misunderstanding how it works, but most reading on the web doesn't spell it out clear enough for my peon brain to understand.
I'm trying to make a 'sort_name' function that sorts an array of private classes based on the c-string "name" when the function is invoked.
Unfortunately I keep running into errors when trying to use it.
Here's my courses_main.cpp's main function:
int main()
{
Course* courses[10] = {};
int selection;
int size = 0;
do
{
selection = menu();
if (selection == 1)
{
if (size < 10)
add(courses, size);
else
std::cout << "\nUnable to add more classes.";
}
else if (selection == 2)
{
edit(courses, size);
}
else if (selection == 3)
{
}
else if (selection == 4)
{
sort_name(courses, size);
for (int i = 0; i < size; i++)
{
courses[i]->display();
}
}
else if (selection == 5)
{
}
else if (selection == 6)
{
}
else if (selection == 7)
{
break;
}
else
{
std::cout << "\nInvalid selection.";
}
} while (selection != 7);
std::cout << "\nPress any key to exit.";
(void)_getch();
return 0;
}
Here is my courses_functions.cpp where I define the sort_name function:
void swap_ptrs(Course*& pt1, Course*& pt2) //Passes the pointers by reference
{
Course* tmp = pt1;
pt1 = pt2;
pt2 = tmp;
}
void Course::sort_name(Course* co_ptr[], int size) //has to be apart of the class (Course::) to have access to the name data
{
bool swap;
do
{
swap = false;
for (int i = 0; i < size - 1; i++)
{
if (strcmp(co_ptr[i]->name, co_ptr[i + 1]->name) > 0) //We're now comparing and swapping pointers
{
swap_ptrs(co_ptr[i], co_ptr[i + 1]);
swap = true;
}
}
} while (swap);
}
And here is my courses.h header where I define(?) the function:
#ifndef COURSE_H
#define COURSE_H
#include <iostream>
#include <conio.h>
#include <iomanip>
#include <stdio.h>
#include <string.h>
#include <ctime>
#include <fstream>
#include <cstdlib>
class Course
{
private:
char name[10] = "", grade;
int units;
public:
Course()
{
name;
grade;
units = 0;
}
void read() //Initializes course and collects information from user
{
std::cout << "\nEnter course name: ";
std::cin.getline(name, 10, '\n');
std::cout << "\nEnter number of units: ";
std::cin >> units;
std::cout << "\nEnter grade received: ";
std::cin >> grade;
std::cin.ignore();
}
void display() const //Displays course to user
{
std::cout << name << ' ' << units << ' ' << grade << std::endl;
}
~Course() //Destructor frees allocated dynamic memory
{
std::cout << "\nDeleting any dynamically created object";
}
void sort_name(Course* co_ptr[], int size);
};
#endif // COURSE_H
I'm not understanding much about classes outside of how they're extremely similar to structs, so any direction would be welcome thanks!
A better code organization would be to declare the functions in the .h file and implement them in the.cpp.
Here is a working sample without .cpp for simplification. Only Courses.h and main.
With .cpp your program should be somethong like this:
Course.h
#ifndef COURSE_H
#define COURSE_H
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std; //<-- for test pusposes, you should use std:: scope
class Course
{
private:
string name;
int units, grade;
public:
Course(); //<-- the code you have inside the constructor, only units = 0,
// does somenthing, you should initialize all the members.
Course(string name);
void read();
void display() const;
~Course(); //<-- to dealocate dynamic memory you need to really dealocate it with delete.
string getName() const;
};
#endif // COURSE_H
And in your .ccp the implementation:
Course.cpp
#include "Course.h"
Course::Course(){ /*do stuff*/ }
Course::Course(string name) : name(name) { /*do stuff*/ } //<-- initializing name here
void Course::read() {/*do stuff*/ }
void Course::display() const {/*do stuff*/ }
Course::~Course() {/*do stuff*/ }
string Course::getName() const { return name; }
For sorting you don't need anything fancy you have sorting tools and data structures in the C++ libraries that make your job easy, like vector for objects container and sort for sorting.
Main
#include "Course.h"
bool sorting(Course course1, Course course2) { //conditional function for sort (#include <algorithm>)
return course1.getName() < course2.getName();
}
int main() {
vector<Course> courses = { Course("zed"), Course("albert")}; // adding courses
courses.push_back(Course("mary")); // adding some more
courses.push_back(Course("john"));
courses.push_back(Course("ana"));
courses.push_back(Course("charles"));
sort(courses.begin(), courses.end(), sorting); //<-- sorting
for (Course c : courses) {
cout << c.getName() << " ";
}
}
Output:
albert ana charles john mary zed

Completing the body of a function in a separate header file in C++?

I have a homework task where I should complete the body of a function located in a separate file Find.h which should be completed in such a way that the code written below should compile successfully:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include "Find.h"
using namespace std;
class Company {
std::string name;
int id;
public:
std::string getName() const {
return this->name;
}
int getId() const {
return this->id;
}
friend std::istream& operator>>(std::istream& stream, Company& company);
};
std::istream& operator>>(std::istream& stream, Company& company) {
return stream >> company.name >> company.id;
}
std::ostream& operator<<(std::ostream& stream, const Company& company) {
return stream << company.getName() << " " << company.getId();
}
int main() {
using namespace std;
vector<Company*> companies;
string line;
while (getline(cin, line) && line != "end") {
istringstream lineIn(line);
Company* c = new Company();
lineIn >> *c;
companies.push_back(c);
}
string searchIdLine;
getline(cin, searchIdLine);
int searchId = stoi(searchIdLine);
Company* companyWithSearchedId = find(companies, searchId);
if (companyWithSearchedId != nullptr) {
cout << *companyWithSearchedId << endl;
}
else {
cout << "[not found]" << endl;
}
for (auto companyPtr : companies) {
delete companyPtr;
}
return 0;
}
And here is my incomplete attempt for completion of the Find.h file (the program should output the id and the name of the company that matches the given id):
#ifndef FIND_H
#define FIND_H
#include "Company.h"
#include <vector>
using namespace std;
Company* find(vector<Company*> vc, int id) {
for (int i = 0; i < vc.size(); i++) {
if (vc[i]->getId() == id) {
//I do not know what to write here as to return a pointer
//to the required element so as to fulfil the requirement?
}
}
return nullptr;
}
#endif // !FIND_H
One alternative is to define a functor or function object and use the std::find algorithm:
struct Find_By_ID
{
int id_to_find;
bool operator==(const Company& a)
{
return a->getId() == id_to_find;
}
}
//...
std::vector<Company> database; // Note, not a vector of pointers
//...
Find_By_ID functor;
functor.id_to_find = searchId;
std::vector<Company>::iterator iter = std::find(database.begin(), database.end(),
functor);
Edit 1: No new necessary
You don't need to use new when building your database:
Company c;
std::vector<Company> database;
while (std::cin >> c)
{
database.push_back(c);
}
The std::vector::push_back() method will make a copy and append it to the vector. The vector will allocate memory for the item as necessary.
Edit 2: Brute force
You could use a custom brute force method instead of a functor:
const std::vector<Company>::const_iterator iter_begin(database.begin());
const std::vector<Company>::const_iterator iter_end(database.end());
std::vector<Company>::const_iterator iter;
for (iter = iter_begin; iter != iter_end; ++iter)
{
if (iter->getId() == searchId)
{
break;
}
}
if (iter != iter_end)
{
std::cout << "Customer found by ID.\n";
}
If you want to modify the found Customer, change the iterator types to:
std::vector<Customer>::iterator
as appropriate.
For the specific issue in the .h file for loop try:
return vc[i]; //vc is a vector of Company pointers, this returns the pointer at vc index i
For the output part consider:
cout << companyWithSearchedId->getId() << " " << companyWithSearchId->getName() << endl;
There are more issues here at as a whole, take your time and work through it.

EXC_BAD_ACCESS when adding object to array

I am new programming and C++. I am trying to create a Roster of Person objects using an array and then printing the attributes of the People in the Roster.
When I attempt to add a Person to the personArray, I am getting an
Exception = EXC_BAD_ACCESS (code=1, address=0x0).
I think this has to do with the scope of my personArray but I can't seem to figure it out.
Here is the code I am using:
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
class Person
{
public:
Person(string name, int age);
string getName() {
return name;
}
void setName(string n) {
name = n;
}
int getAge() {
return age;
}
void setAge(int a) {
age = a;
}
private:
string name;
int age;
};
class Roster {
public:
void addToPersonArray(string name, string age) {
Person person(name, stoi(age));
personArray[personCount] = &person;
}
void printPersonArray() {
for (int i = 0; i < 5; i++)
cout << personArray[i]->getName() << '\t' << personArray[i]->getAge() << '\n';
}
private:
Person *personArray[5];
int personCount = 0;
};
int main() {
const string studentData[] = {"Dan,45", "Mark,33", "Mary,22",
"April,17", "Jill,22"};
Roster roster;
stringstream ss(studentData[0]); // just testing the first entry
vector<string> result;
while (ss.good()) {
string substr;
getline(ss, substr, ',');
result.push_back(substr);
}
roster.printPersonArray();
}
The problem is here:
void addToPersonArray(string name, string age) {
Person person(name, stoi(age));
personArray[personCount] = &person;
}
person is a local variable in the member function addToPersonArray(), which will be destroyed after the function scope.
Hence, storing the address of a local variable(and trying to accessing it latter in printPersonArray()) will give you, nothing but an undefined behavior.
You are lucky that your programme got the exception.
One more thing to note that, you are not actually using your roster to test the program. Instead, all you do is parsing and saving to result vector. You can add this after the while loop, to make it actually work.
if (result.size() == 2) {
roster.addToPersonArray(result[0], result[1]);
}
Suggestion: Since you have a fixed array size, you probably wanna do it with std::array<Person, 5> or with std::vector<Person> by reserving the memory for 5 Person in the c'tor of Roster.
See a sample output: https://wandbox.org/permlink/tAGqqnhCfwz1wPrH
#include <iostream>
#include <sstream>
#include <vector>
#include <array>
class Person {
public:
Person(const std::string& name, int age): name(name), age(age) {}
std::string getName()const { return name; }
void setName(const std::string& n){ name = n; }
int getAge()const { return age; }
void setAge(int a) { age = a; }
private:
std::string name;
int age;
};
class Roster {
public:
Roster() { personArray.reserve(5); } // reserve some memory
void addToPersonArray(const std::string& name, const std::string& age) {
personArray.emplace_back(name, stoi(age));
}
void printPersonArray() {
// use range loop, which will assure, access what you have.
for (const Person& person: personArray)
std::cout << person.getName() << '\t' << person.getAge() << '\n';
}
private:
std::vector<Person> personArray;
//int personCount = 0; --------------> no need anymore
};
int main() {
std::array<std::string,5> studentData{ "Dan,45", "Mark,33", "Mary,22", "April,17", "Jill,22" };
Roster roster;
for(const std::string& str: studentData)
{
std::stringstream ss(str);
std::vector<std::string> result;
while (ss.good()) {
std::string substr;
std::getline(ss, substr, ',');
result.emplace_back(substr);
}
if (result.size() == 2) {
roster.addToPersonArray(result
[0], result[1]);
}
}
roster.printPersonArray();
return 0;
}
Output:
Dan 45
Mark 33
Mary 22
April 17
Jill 22
In addition to storing pointers to local variables in your addToPersonArray() function, your main() function does not add any entries to the personArray.
Instead, main creates a Roster object, and after some code that doesn't affect anything with Roster, you go straight into calling roster.printPersonArray, which does this:
void printPersonArray()
{
for (int i = 0; i < 5; i++) // <-- This will loop for all 5 entries
cout << personArray[i]->getName() << '\t' << personArray[i]->getAge() << '\n';
}
Since personArray was never initialized to contain valid pointers to Person objects, that loop will cause undefined behavior.
The issue is that you have a personCount member variable, but fail to make use of it to control how many valid entries there are in the array. The loop should have been written as below:
void printPersonArray()
{
for (int i = 0; i < personCount; i++)
cout << personArray[i]->getName() << '\t' << personArray[i]->getAge() << '\n';
}
In addition to the storage of pointers to local variables, your Roster::addToPersonArray() doesn't check if personCount is greater than 4, thus this is another place in your code where you failed to use personCount to control how many Person objects are being referenced.

Unable to remove missing ; before variable name error

#ifndef PRODUCTS_H
#define PRODUCTS_H
#include "Products.h"
class Products
{
protected:
static int count;
string name_;
float cost_;
public:
Products() // default ctor
{
name_ = "";
cost_ = 0.0f;
count++;
}
Products(string name , float cost) //parametorized ctor
{
name_ = name;
cost_ = cost;
count++;
}
Products(Products &p )
{
name_ = p -> name_;
cost_ = p -> cost_;
}
~Products()
{}
string getName()
{
return name_;
}
void setName(string name)
{
name_=name;
}
float getCost()
{
return cost_;
}
void setCost(float cost)
{
cost_=cost
}
float CalcTotal(Products *p_products) //Not made yet!
{
float total=0.0f;
for(int i = 0 ; i < count; i++)
{
total += p_products->cost_;
p_products ++;
}
return total;
}
Products read()
{
Products size,*p_products;
cout << "Enter Number of Items To Enter:";
cin >> size;
cout << endl;
p_products = new Products[size];
for(int i = 0 ; i < size; i++)
{
cout << "Enter Name:";
cin >> p_products -> name_;
cout << endl << "Enter Cost";
cin >> p_products -> cost_;
cout << endl;
p_products ++;
}
return p_products;
}
void write(Products *p_products)
{
for(int i = 0 ; i < count ; i++,p_products++)
{
cout<<"Products Name:\t\t"<<p_products->name_<<endl;
cout<<"Products Price:\t\t"<<p_products->cost_<<endl;
}
}
};
#endif
My source code is:
#include <iostream>
#include <string>
#include "Products.h"
using namespace std;
static int Products::count;//declaring static variable
int main()
{
Products *p_products,temp;
*p_products=temp.read();
//temp.write();
system("pause");
delete[] Product;
return 0;
}
But I am getting this error which I can not remove:
error C2146: syntax error : missing
';' before identifier 'name_'
Please help me out!Thanks
You should include the string header file in your first file. It looks like it's complaining that it doesn't know what a string is.
You need to add
#include <string>
and change the type of name_ to
std::string name_;
In Products &p, p is a reference to an object of type Products, it's not a pointer.
You have to use operator ., instead of operator -> in order to access reference fields:
Products(Products &p )
{
name_ = p -> name_;
cost_ = p -> cost_;
}
Try moving this line:
using namespace std;
Above the line where you #include "Products.h". But if you're using string in products.h, you should probably be including etc there instead. Also, I believe "using namespace std" is kinda frowned upon.
in your include file, you must declare the string name_ as std::string name_
You need:
std::string name_;
Also, looks like a missing semicolon here:
void setCost(float cost)
{
cost_=cost
}
You're missing a semicolon in this function:
void setCost(float cost)
{
cost_=cost
}