writing file in header c++ - c++

I have 3 files, book.h, book.cpp, bookdriver.cpp. I want to know if the ISBNs in a list are found in the array using binary search.
book.h:
using namespace std;
ofstream fout("output2.txt");
class Book
{
string author; // A string for the name of the author
string title; //A string for the book title
int ISBN; //A long integer for the ISBN
public:
Book(); //A default constructor
void print();
int getISBN() const; //A const function GetISBN that returns the integer containing the ISBN.
int binary_search(Book, int, int, int);
};
book.cpp- also includes print function which uses fout
#include "book.h"
//iterative binary search function, returns location of ISBN in array if present
int Book::binary_search(Book arr[], int x, int n, int ISBN)
{
while (n >= x)
{
int midpt = x + (n - x) / 2;
//if ISBN is in midpoint
if (arr[midpt].getISBN() == ISBN)
{
return midpt;
}
//if ISBN is greater than midpoint, ignore left side of array
if (arr[midpt].getISBN() < ISBN)
{
x = midpt + 1;
}
//if ISBN is smaller, ignore right side of array
else
{
n = midpt - 1;
}
}
//if ISBN not present
return -1;
}
bookdriver.cpp
#include "book.h"
const int num = 10; //number of book objects the array should hold *can be changed*
int main()
{
Book book_array[num] = {}; //array can hold num book objects
for (int c = 0; c < num; c++)
{
book_array[c] = Book();
book_array[c].getData(data); //reading book information
}
//read file
ifstream fin("bookISBN.txt");
int find_ISBN;
while (fin >> find_ISBN)
{
bool match = false;
int count = 0;
int result = binary_search(book_array[10], 0, num - 1, find_ISBN); //error here
if (result == -1) //if ISBN not found
{
fout << "Sorry, the ISBN " << find_ISBN << " is not found." << endl;
}
else
{
fout << "The ISBN " << find_ISBN << " is found in the system!" << endl;
}
count++;
}
return 0;
}
I'm using fout in both book.cpp and bookdriver.cpp so I have ofstream fout (output2.txt) in the header but I'm getting linker errors(Error LNK2005) in vs.
I think because of the one definition rule, fout is defined twice?

Here's a start:
#include <iostream>
#include <fstream>
using namespace std;
const int num = 2;
class Book
{
public:
Book(){};
string author;
string title;
int ISBN = 0;
int data;
};
int binary_search (Book arr[num], int x, int n, int ISBN, int overflow)
{
int mid = (x + n) / 2;
if (x == mid || n == mid)
overflow++;
if (overflow > 100)
return false;
if (arr[mid].ISBN > ISBN)
return binary_search(arr, x , mid, ISBN, overflow);
else if (arr[mid].ISBN < ISBN)
return binary_search(arr, mid, n , ISBN, overflow);
return true;
}
int main() {
ofstream fout("output2.txt");
ifstream fin("bookISBN.txt");
int find_ISBN;
Book book1;
book1.title = "Alice in Wonderland";
book1.author = "C.S. Lewis";
book1.ISBN = 1;
Book book2;
book2.title = "Wuthering Heights";
book2.author = "Emily Bronte";
book2.ISBN = 2;
Book book3;
book3.title = "Moby Dick";
book3.author = "Herman Melville";
book3.ISBN = 25;
Book book_array[num] = {book1, book2};
while (fin >> find_ISBN)
{
int result = binary_search(book_array, 0, num, find_ISBN, 0);
if (result == false)
{
fout << "Sorry, the ISBN " << find_ISBN << " is not found." << endl;
}
else
{
fout << "The ISBN " << find_ISBN << " is found in the system!" << endl;
}
}
fin.close();
fout.close();
return 1;
}

Related

Part of the char array?

I got a task in which I receive babies' firstname and weight in kilogram in a character array (for example: Johnny, 2 kg). I must store them in an array that can hold maximum 1000 elements and must be a struct type, storing the baby's firstname and weight.
Every actions must be done in functions - however, when I tried to get the name until the comma, str.copy() didn't work for me. Its specific problem was something with the last parameter, the position. Could someone help me out with that? Also, I'm kinda new to C++ and imagining how to separately, in two functions ask in the char arrays until empty line and do the copying in the other... if someone could help me out, I'd be grateful for that ^^'
Thanks for the help in advance!
#include<iostream>
#include<string>
#define M 1000
struct baby{
std::string baby_name;
float weight;
};
int readIn(baby* baby_datapair, int max);
// int maxWeight(baby* baby_datapair);
// int minWeight(baby* baby_datapair);
// void descendingOrder(baby* baby_datapair, int num);
int main(){
baby baby_array[M];
int n = readIn(baby_array, M);
return 0;
}
int readIn(baby* baby_datapair, int max){
int n = 0;
char name[12];
while (n < max){
std::cout << "Baby" << n+1 << "'s datas (Nickname, weight in kg): ";
std::getline(std::cin, name);
//~ std::cin.ignore(1);
if (neve == ""){
std::cout << "Wrong input!\n";
break;
}else{
std::size_t pos = name.find(',');
std::size_t until = name.copy(baby_datapair[n].baby_name, 0, pos);
}
n++;
}
return n;
}
// int maxWeight(baby* baby_datapair){
// }
// int minWeight(baby* baby_datapair){
// }
// void descendingOrder(baby* baby_datapair, int num){
// }
You must use std::string name; instead of char name[12]; as std::getline 's parameter. BTW, It make better for memory management. After input data, check pos value for valid value.
#include<iostream>
#include<string>
#define M 1000
struct baby {
std::string baby_name;
float weight;
};
int readIn(baby* baby_datapair, int max);
// int maxWeight(baby* baby_datapair);
// int minWeight(baby* baby_datapair);
// void descendingOrder(baby* baby_datapair, int num);
int main() {
baby baby_array[M];
int n = readIn(baby_array, M);
return 0;
}
int readIn(baby* baby_datapair, int max) {
int n = 0;
//char name[12];
std::string name;
while (n < max) {
std::cout << "Baby" << n + 1 << "'s datas (Nickname, weight in kg): ";
std::getline(std::cin, name);
//~ std::cin.ignore(1);
if (name == "") {
std::cout << "Wrong input!\n";
break;
}
else {
std::size_t pos = name.find(',');
if (pos <= 0) {
std::cout << "Invalid input structure!\n";
continue;
}
//std::size_t until = name.copy(baby_datapair[n].baby_name, 0, pos);
baby_datapair[n].baby_name = name.substr(0, pos);
baby_datapair[n].weight =(float)atof(name.substr(pos+1).c_str());
//std::cout << std::endl;
//std::cout << baby_datapair[n].baby_name;
//std::cout << ", " << baby_datapair[n].weight;
}
n++;
}
return n;
}
// int maxWeight(baby* baby_datapair){
// }
// int minWeight(baby* baby_datapair){
// }
// void descendingOrder(baby* baby_datapair, int num){
// }
You are taking it the wrong size. You should not try to copy to, but just copy from. BTW, name must be a std::string for you program to compile, and you should check for possible end of file. So a minally fixed version could be:
std::string name;
while (n < max) {
std::cout << "Baby" << n + 1 << "'s datas (Nickname, weight in kg): ";
std::getline(std::cin, name);
//~ std::cin.ignore(1);
if ((! std::cin) || name == "") {
std::cout << "Wrong input!\n";
break;
}
else {
std::size_t pos = name.find(',');
baby_datapair[n].baby_name = std::string(name.c_str(), pos);
baby_datapair[n].weight = strtof(name.c_str() + pos + 1, nullptr);
}
But using a std::stringstream would be more idiomatic in C++. Above code is rather C-ish...

How does one correctly pass on ofstream object?

I am writing code to have input student and grade objects, sort them, calculate an average gpa, and output them to a file. My current problem is that the output of my student objects are given after I sort them and print them, but the code does not seem to leave the loop once I do that. I have a print function in which I am passing an ofstream. From debugging, I know that the out ofstream object reads everything, but then it seems to freeze, and not output anything else into it. Can somebody tell me if I passed by reference incorrectly, or if I need to do something else? The error where the compiler didn't keep going through is marked in the code.
Sorry, so for more information, below is a snip it of what is run
output code in text file
Notice how "got through it" is only displayed once. I know that it's not an issue opening the file and outputting, because it actually did output the right stuff. Also, for correction, the compiler actually compiles everything fine. It is at runtime where the terminal stalls and nothing more is output.
#include <vector>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <string>
#include "Grade.h"
#include "Student.h"
using namespace std;
const double A_NUM = 4.0, B_NUM = 3.0, C_NUM = 2.0, D_NUM = 1.0, E_NUM = 0.0, B_PLUSSNUM = 3.4, C_PLUSSNUM = 2.4, D_PLUSSNUM = 1.4;
const double A_MINUSNUM = 3.7, B_MINUSNUM = 2.7, C_MINUSNUM = 1.7, D_MINUSNUM = 0.7;
const int FIRST_INDEX= 0;
const int START_NUM = 0;
const int LESS_ONE = 1, ABOVE_ONE = 1;
const int START_GRADE = 0;
void calcgrades(vector<Grade>& grades)//function that calculates gpa based on letter grades
{
const string A = "A", A_MINUS = "A-", B_PLUSS = "B+", B = "B", B_MINUS = "B-", C_PLUSS = "C+", C = "C", C_MINUS = "C-", D_PLUSS = "D+", D = "D", D_MINUS = "D-", E = "E";
int counter = START_NUM;//used to keep track of current student and current total grade
double current_grade = START_NUM;
for(int i = 0; i < grades.size();i++)
{
//while loop to get the student's current total grade if the next student id is different than the first one.
while(i < grades.size()-LESS_ONE && grades[i].getid() == grades[i+ABOVE_ONE].getid())
{
if (grades[i].getgrade() == A)
{
current_grade == A_NUM + current_grade;
}
if (grades[i].getgrade() == B)
{
current_grade == B_NUM + current_grade;
}
if (grades[i].getgrade() == C)
{
current_grade == C_NUM + current_grade;
}
if (grades[i].getgrade() == D)
{
current_grade == D_NUM + current_grade;
}
if (grades[i].getgrade() == E)
{
current_grade == E_NUM + current_grade;
}
if (grades[i].getgrade() == B_PLUSS)
{
current_grade == B_PLUSSNUM + current_grade;
}
if (grades[i].getgrade() == C_PLUSS)
{
current_grade == C_PLUSSNUM + current_grade;
}
if (grades[i].getgrade() == D_PLUSS)
{
current_grade == D_PLUSSNUM + current_grade;
}
if (grades[i].getgrade() == A_MINUS)
{
current_grade == A_MINUSNUM + current_grade;
}
if (grades[i].getgrade() == B_MINUS)
{
current_grade = B_MINUSNUM + current_grade;
}
if (grades[i].getgrade() == C_MINUS)
{
current_grade = C_MINUSNUM + current_grade;
}
if (grades[i].getgrade() == D_MINUS)
{
current_grade = D_MINUSNUM + current_grade;
}
}
if (grades[i+ABOVE_ONE].getid() != grades[i].getid() || i == grades.size()-LESS_ONE)
{
//computes the average if the currentid is not equal to the nextid
double avggpa = current_grade/counter;
grades[i].newgpa(avggpa);
counter = START_NUM;//resets counter for a new student to get his gpa
}
counter++;
}
}
int main(int argc, char* argv[])
{
string student_file, grades_file, idnum, name, address, pnum, course, gletter;
//creates student and grade objects from respective classes
vector<Student> students;
vector<Grade> grades;
student_file = argv[1];
//reads in information from file to import into student objects
ifstream sfile;
sfile.open(student_file);
while(getline(sfile, idnum))//gets the student information from student file
{
getline(sfile, name);
getline(sfile, address);
getline(sfile, pnum);
//creates student objects to import info. into, and inserts into students vector
Student s(idnum, name, address, pnum);
students.push_back(s);
}
sfile.close();
//opens information from the grade file
grades_file = argv[2];
//reads from file to import into grades objects
ifstream gfile;
gfile.open(grades_file);
//gets the grade information from the grades file
while(getline(gfile, course))
{
getline(gfile, idnum);
getline(gfile, gletter);
//creates grade objects to import info, and inserts into grades vector
Grade g(course, idnum, gletter, START_GRADE);
grades.push_back(g);
}
gfile.close();
//reads the query file
string query_file;
query_file = argv[3];
ifstream qfile;
qfile.open(query_file);
//reads from query file
//creates vector to store each student number
vector<string> query_nums;
string incheck;
while(getline(qfile, incheck))
{
query_nums.push_back(incheck);
}
qfile.close();
//sorts the information for the students
sort(students.begin(), students.end());
//sorts the information for the grades
sort(grades.begin(), grades.end());
ofstream outtxt;
string out_file = argv[4];
outtxt.open(out_file);
//outputs the student information, sorted now.
for(int i = 0; i < students.size();i++)
{
students[i].print(outtxt);
outtxt << "got through it";
}
//compiler did not get past here!
outtxt << "We're here!";
//outputs the grades with student id's, now sorted
for (int i = 0; i < grades.size(); i++)
{
grades[i].print(outtxt);
outtxt << "\n\n" << "some output!";
}
//calculates the average gpa for every student
calcgrades(grades);
for(int i = 0; i < query_nums.size(); i++)//goes through each query number to check first
{
for (int j = 0; j < students.size(); j++)//after, goes through each student object
{
if (query_nums[i] == students[j].getid())
{
//finds the gpa in the grades class that matches the student id
for (int k = 0; k < grades.size(); k++)
{
if (grades[k].getid() == query_nums[i])//
{
//outputs the resulting id, avg gpa, and name of matching students
outtxt << grades[i].getid() << "\tthere is nothinghere" << grades[i].getgpa() << "\t" << students[i].getname();
}
}
}
}
}
outtxt.close();
return 0;
}
student class with print function
class Student
{
private:
string idnum;
string name;
string address;
string pnum;
public:
//defines constructor
Student(string idnum,string name,string address,string pnum);
//prints each student info
void print(ofstream& out);
string getname();
string getid();
bool operator < (Student s) const {
return idnum < s.idnum;
}
};
student cpp file
#include "Student.h"
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
using namespace std;
//Student constructor, used to make student objects
Student::Student(string id,string nm,string add,string pnumber)
{
idnum = id;
name = nm;
address = add;
pnum = pnumber;
}
void Student::print(ofstream& out)
{
out << name << endl << idnum << endl << pnum << endl << address << endl;
}
string Student::getname()
{
//returns the student name
return name;
}
string Student::getid()
{
return idnum;
}
In answer your question regarding how to correctly pass an ofstream object, you are passing it correctly.
So why doesn't it work? From what is available to observe from your code, it should work just fine. I would suggest debugging the output file name in these lines of code:
ofstream outtxt;
string out_file = argv[4];
outtxt.open(out_file);
Verify that the open function succeeded by checking the ios::fail flag after calling the open function.
Try something like this after opening:
if (ios::fail)
cout << "fail";
I hope this helps.
Edited: There may be other problems, but the calcgrades() function has an access violation on the last for loop iteration, after the while loop, at this if statement:
if (grades[i+ABOVE_ONE].getid() != grades[i].getid() || i == grades.size()-LESS_ONE)

How can I check if array is full and double/half the size of it?

This program reads information from a text file, stores it in an array, and performs one of 3 functions. I need to be able to check if the array is full and double the size if it is or half the size if their is a deletion 1/4 of the size of the array. Tried to be brief so if you need more information, let me know.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct info{
char letter;
string SSN;
string firstName;
string lastName;
};
void insertion(int &count, int &validInsertationCount, string &SSN, char &letter, string &firstName, string &lastName, info *list);
void deletion(int &count, int &validDeletionCount, string &SSN, char &letter, string &firstName, string &lastName, info *list);
void retrieval(int &count, int &validRetrievalCount, string &SSN, string &firstName, string &lastName, info *list);
int main(int argc, char* argv[]){
int arraySize = 1000;
struct info list[1000];
fstream input(argv[1]);
int count = 0;
int validInsertationCount = 0;
int validDeletionCount = 0;
int validRetrievalCount = 0;
while(!input.eof()){
input >> list[count].letter >> list[count].SSN >> list[count].firstName >> list[count].lastName;
if(list[count].letter == 'i'){
insertion(count, validInsertationCount, list[count].SSN, list[count].letter, list[count].firstName, list[count].lastName, list);
}
else if(list[count].letter == 'd'){
deletion(count, validDeletionCount, list[count].SSN, list[count].letter, list[count].firstName, list[count].lastName, list);
}
else if(list[count].letter == 'r'){
retrieval(count, validRetrievalCount, list[count].SSN, list[count].firstName, list[count].lastName, list);
}
count++;
}
input.close();
int numberOfItems = validInsertationCount - validDeletionCount;
cout << "The Number of Valid Insertation: " << validInsertationCount << endl;
cout << "The Number of Valid Deletion: " << validDeletionCount << endl;
cout << "The Number of Valid Retrieval: " << validRetrievalCount << endl;
cout << "Item Numbers in the array: " << numberOfItems << endl;
cout << "Array Size is: " << arraySize << endl;
//cout << "Time Elapsed: " << <<endl;
}
void insertion(int &count, int &validInsertationCount, string &SSN, char &letter, string &firstName, string &lastName, info *list){
for(int i = 0; i < count; i++){
if(SSN == list[i].SSN && list[i].letter == 'i'){
for(int k = i; k < count; k++){
list[k].SSN = list[k+1].SSN;
list[k].letter = list[k+1].letter;
list[k].firstName = list[k+1].firstName;
list[k].lastName = list[k+1].lastName;
}
count--;
return;
}
}
validInsertationCount++;
return;
}
void deletion(int &count, int &validDeletionCount, string &SSN, char &letter, string &firstName, string &lastName, info *list){
for(int i = 0; i < count; i++){
if(SSN == list[i].SSN && firstName == list[i].firstName && lastName == list[i].lastName){
for(int k = i; k < count; k++){
list[k].SSN = list[k+1].SSN;
list[k].letter = list[k+1].letter;
list[k].firstName = list[k+1].firstName;
list[k].lastName = list[k+1].lastName;
}
count--;
validDeletionCount++;
return;
}
}
}
void retrieval(int &count, int &validRetrievalCount, string &SSN, string &firstName, string &lastName, info *list){
for(int i = 0; i < count; i++){
if(SSN == list[i].SSN && firstName == list[i].firstName && lastName == list[i].lastName){
validRetrievalCount++;
}
}
return;
}
You can't simply resize a statically allocated array so you'll want to either use std::vector or malloc/new to allocate a dynamic array. However in that case you can't determine the size of the array using sizeof(). So you either keep a size variable or use a "delimiter" value in order to pinpoint the end of the array.

Moving For Loop to Function

in the following code I have a for loop in my main function. Since a function can't return 2 values, what are some ways I could create a function, or functions, to remove it from my main function. Thanks!
#include <iostream>
#include <cmath>
using namespace std;
int getNumberExercises();
int getScores(int numberOfExercises);
int getPoints(int numberOfExercises);
double roundToTenth(double number);
double calcPercentage(int totalScore, int totalPoints);
void getTotal(int totalScore, int totalPoints, double scorePercentage);
int main() {
int numberOfExercises = 0;
int totalScore = 0;
int totalPoints = 0;
double scorePercentage = 0.0;
numberOfExercises = getNumberExercises();
for (int i = 1; i <= numberOfExercises; i++) {
totalScore += getScores(i);
totalPoints += getPoints(i);
}
scorePercentage = calcPercentage(totalScore, totalPoints);
getTotal(totalScore, totalPoints, scorePercentage);
return 0;
}
int getNumberExercises() {
int numberOfExercises;
cout << "How many exercises to input? ";
cin >> numberOfExercises;
cout << endl;
return numberOfExercises;
}
int getScores(int i) {
int score = 0;
cout << "Score received for exercise " << i << ": ";
cin >> score;
return score;
}
int getPoints(int i) {
int points = 0;
cout << "Total points possible for exercise " << i << ": ";
cin >> points;
cout << endl;
return points;
}
double roundToTenth(double number) {
return floor(number * 100 + 0.5) / 100;
}
double calcPercentage(int totalScore, int totalPoints) {
double scorePercentage = (double) totalScore / totalPoints * 100;
return scorePercentage;
}
void getTotal(int totalScore, int totalPoints, double scorePercentage) {
cout << "Your total is " << totalScore << " out of " << totalPoints << ", or " << roundToTenth(scorePercentage) << "%";
}
Either typedef a std::pair to a descriptive name, or create your own type to hold the things you want to return:
using ScorePointPair = std::pair<int, int>; // C++11
typedef std::pair<int, int> ScorePointPair; // pre C++11
Or
struct ScorePointPair
{
int score;
int points;
};
Then simply return this from your function (by value):
ScorePointPair fun()
{
// Loop etc...
return {score, points};
};
I would recommend the custom type (struct/class) approach, as this tends to be more maintainable.
To return multiple values use pass by pointer:
void modify(int *val1, int *val2)
{
*val1 = 46;
*val2 = 100;
}
In caller:
int a, b;
modify(&a, &b);
Now a will be 46, and b will be 100. This is because the address is copied, rather than the actual variable, which is what happens in pass by value.
So if you want to find the number of occurences of tabs and commas in a file:
void findtabcomma(const char *fn, int *ncomma, int *ntab)
{
FILE *fp;
int c;
if (fp = fopen(fn, "r")) {
while ((c = getc(fp)) != EOF) {
if (c == '\t')
++(*ntab);
if (c == ',')
++(*ncomma);
}
fclose(fp);
}
}
You can use the function like this:
int c, t;
findtabcomma(filenam, &c, &t);
printf("Commas: %d\nTabs: %d", c, t);
And in C++, you can use reference variables. So the findtabcomma function could be rewritten as:
void findtabcomma(const char *fn, int &ncomma, int &ntab)
{
FILE *fp;
int c;
if (fp = fopen(fn, "r")) {
while ((c = getc(fp)) != EOF) {
if (c == '\t')
++ntab;
if (c == ',')
++ncomma;
}
fclose(fp);
}
}
And used like this:
int c, t;
findtabcomma(filenam, c, t);
printf("Commas: %d\nTabs: %d", c, t);
Notice how there are no more *s and &s with C++ references.
You can create a function that either returns an array of type int of size 2 such as
int* functionName(arg1, arg2)
array[0] = totalScore;
array[1] = totalPoints;
return array;
or you could pass in the values by reference by doing something like
void functionName(&arg1, &arg2)
What passing by reference does is it passes the ADDRESS of the variable and then modifies the variable directly instead of creating a copy and passing it into the function.
You can use reference in the argument list to return data
int fun(); can be coded as void fun(int& )

Why is my data member empty even after construction?

I have included both my definition of the Question class and its implementation, the first is a header file and the second a cpp file.
I put comments in to show where the problem is. For some reason under the constructor I can cout the questionText just fine but when I try to do this under the getQuestionText function it just outputs an empty string? Any help would be most appreciated!! Thanks!
#include <string>
#include <vector>
#include <iostream>
using namespace std;
#ifndef QUESTION_H
#define QUESTION_H
class Question{
public:
Question(int thePointValue, int theChapterNumber, \
string theQuestionText);
int getPointValue() const;
int getChapterNumber() const;
string getQuestionText() const;
virtual void writeQuestion(ostream& outfile) const;
virtual void writeKey(ostream& outfile) const;
private:
int pointValue;
int chapterNumber;
string questionText;
void writePointValue(ostream& outfile) const;
};
#endif
#include "Question.h"
Question::Question(int thePointValue, int theChapterNumber, \
string theQuestionText)
{
pointValue = thePointValue;
chapterNumber = theChapterNumber;
questionText = theQuestionText;
//HERE THIS WORKS PERFECTLY
cout << questionText << endl;
}
int Question::getPointValue() const
{
return pointValue;
}
int Question::getChapterNumber() const
{
return chapterNumber;
}
string Question::getQuestionText() const
{
//THIS IS THE PROBLEM. HERE IT OUPUTS AN EMPTY STRING NO MATTER WHAT!
cout << questionText << endl;
return questionText;
}
void Question::writeQuestion(ostream& outfile) const
{
writePointValue(outfile);
outfile << questionText << endl;
}
void Question::writeKey(ostream& outfile) const
{
writePointValue(outfile);
outfile << endl;
}
void Question::writePointValue(ostream& outfile) const
{
string pt_noun;
if (pointValue == 1)
pt_noun = "point";
else
pt_noun = "points";
outfile << "(" << pointValue << " " << pt_noun << ") ";
}
vector<Question *> QuestionsList(string filename, int min, int max)
{
vector<Question *> QuestionList;
string line;
vector<string> text;
ifstream in_file;
in_file.open(filename.c_str());
while (getline(in_file, line))
{
text.push_back(line);
}
string type;
for(int i = 0; i < text.size(); i ++)
{
int num = text[i].find('#');
type = text[i].substr(0, num);
if (type == "multiple")
{
MultipleChoiceQuestion myq = matchup(text[i]);
MultipleChoiceQuestion* myptr = &myq;
if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
{
QuestionList.push_back(myptr);
}
}
if (type == "short")
{
ShortAnswerQuestion myq = SAmatchup(text[i]);
ShortAnswerQuestion* myptr = &myq;
if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
{
QuestionList.push_back(myptr);
}
}
if (type == "long")
{
LongAnswerQuestion myq = LAmatchup(text[i]);
LongAnswerQuestion* myptr = &myq;
if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
{
QuestionList.push_back(myptr);
}
}
if (type == "code")
{
CodeQuestion myq = CODEmatchup(text[i]);
CodeQuestion* myptr = &myq;
if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
{
QuestionList.push_back(myptr);
}
}
cout << QuestionList[QuestionList.size()-1]->getQuestionText() << endl;
}
for (int i = 0; i < QuestionList.size(); i ++)
{
int numm = QuestionList.size();
cout << QuestionList[numm-1]->getQuestionText() << endl;
}
return QuestionList;
}
then when i call this in main the code breaks
vector<Question *> list = QuestionsList(pool_filename, min_chapter, max_chapter);
cout << list[0]->getQuestionText() << endl;
You are declaring, multiple times in your code, local objects and storing their pointer into the QuestionList vector (returned by the function) which, at the end of the function block, will contains dangling pointers.
MultipleChoiceQuestion myq = matchup(text[i]); // < local object
MultipleChoiceQuestion* myptr = &myq; // < pointer to local object
QuestionList.push_back(myptr); // < push back into vector
At this point you can either use dynamic memory allocation (I suggest you not to do that unless you are absolutely forced, and even in that case use one of the smart pointers provided by the standard library) or store the objects directly inside the vector.