Program crashes upon calling member function of an object pointer - c++

As the title says, whenever I try to call a getter function to return the value of a private variable in an object pointer that is in a vector, it crashes. This causes my 2 other functions useless.
I know command == display and command == summary are not working properly. I did some debugging and found out that whenever I try to cout<<P_obj[i]->getnumber() for example, I crash.
Here is my code:
#include <string>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <cstring>
#include <vector>
#include <cstdio>
using namespace std;
class stock {
private:
int sharenumber;
float shareprice;
string sharename;
public:
stock(int x, string y,float z)
:sharenumber(x),sharename(y),shareprice(z)
{
}
int returnnumber(){
return sharenumber;
}
string returnname(){
return sharename;
}
float returnprice(){
return shareprice;
}
};
bool ispositive(int x){
bool a = false;
if (x>0){a = true;}
return a;
}
void buy(vector <stock*> list,int size){
int amount;
float price;
string symbol;
cout<<"Please enter the number of shares, the share symbol and the price of the share to make your purchase.\n";
do{
cout<<"Enter the amount: ";
cin>>amount;
if (ispositive(amount)==false){
cout<<"Please enter a positive number for the amount!\n";
}
}while(ispositive(amount)==false);
cout<<"Enter the symbol: ";
cin>>symbol;
do{
cout<<"Enter the stock price: $ ";
cin>>price;
if (ispositive(price)==false){
cout<<"Please enter a positive number for the price!\n";
}
}while(ispositive(price)==false);
list.push_back(new stock(amount,symbol,price));
cout<<"Your purchase has been made. Thank you for your time.\n\n";
}
void summary(vector <stock*> list,int size){
float cost = 0;
int stocktotal = 0;
for (int i = 0; i < size;i++){
cost = cost + (list[i]->returnprice()*list[i]->returnnumber());
stocktotal = stocktotal + list[i]->returnnumber();
}
cout<<"\nUser has made "<<size<<" purchases in total. The total number of stocks bought is "<<stocktotal<<". The total cost is "<<cost<<"."<<endl<<endl;
}
int main(int argc, char *argv[])
{
vector <stock*> P_obj;
bool cont = true;
bool last_cont = true;
char * check;
bool signal = false;
string command;
char done;
if (argc>1){
check = strstr(argv[1],".txt");
if (check!= NULL){
fstream tester;
tester.open(argv[1]);
if (tester.is_open()){
signal=true;}
}else{cout<<"Error has occurred. Please enter correct data file name with .txt extension.";}
if (signal){
cout<<"\nWelcome to the Golden Sacks! Enter a command to start your stock trading career.\n\n";
ofstream user_data(argv[1]);
while(cont==true){
bool e_valid = false;
cout<<"Enter command here: ";
cin>>command;
if (command == "buy"){
buy(P_obj,P_obj.size());
}
if (command == "summary"){
summary(P_obj,P_obj.size());
}
if (command == "display"){
cout<<"\nList of all purchases:\n";
for (int y = 0; y < P_obj.size(); y++){
cout<<P_obj[y]->returnnumber()<<" "<<P_obj[y]->returnname()<<" "<<"$"<<fixed<<setprecision(2)<<P_obj[y]->returnprice()<<endl;
}
cout<<endl;
}
if (command=="help"){
cout<<"Command list:\n";
cout<<left<<setw(2)<<"- buy\n";
cout<<left<<setw(2)<<"- display\n";
cout<<left<<setw(2)<<"- summary\n";
cout<<left<<setw(2)<<"- find <stock-symbol>\n";
cout<<left<<setw(2)<<"- amount>= <purchase-amount>\n";
cout<<left<<setw(2)<<"- help\n";
cout<<left<<setw(2)<<"- exit\n\n\n";
}
if (command == "exit"){
while (last_cont == true){
cout<<"Are you sure you want to quit? (Yy/Nn):";
cin>>done;
if (done == 'Y'||done == 'y'||done =='N'||done =='n'){
last_cont=false;
if(done=='Y'||done=='y'){
cont = false;
cout<<"Thank you for using Golden Sacks. We hope to see you soon!\n";
}
}else {cout<<"Please enter only Y|N or y|n, try again.\n\n";}
}
}
} //end of loop
for (int i = 0; i < P_obj.size(); i++){
user_data<<P_obj[i]->returnnumber()<<" "<<P_obj[i]->returnname()<<" "<<"$"<<fixed<<setprecision(2)<<P_obj[i]->returnprice()<<endl;
}
}
}else {cout<<"Too few arguments, enter a data file name with .txt extension to continue";}
}

vector <stock*> P_obj;
is not properly allocated. //memory leak
stock is not a user defined type like int or double.
so if you are using it as a pointer, use RAII technique with it, deallocate it in it's destructure
eg:
class Stock{
int* x{nullptr};
public:
Stock(...);//allocated here
~Stock(..);//deallocate here
};
you can further more defined new and delete operators

Related

How do you compare and sort a specific parameter within a class?

My professor has asked us to make a program that will take a user's input and continue reading until the end of input. Only then, can the program output what the user has typed.
Input should be based on video title, it's url, comments made on the video, length (in minutes), and rating (in *).
For example:
United Break Guitars, https://www.youtube.com/watch?v+5YGc4zOqozo, Great example of one person getting a giant company to listen, 4.5, ***, Space Versus Tabs, https://www.youtube.com/watch?v=SsoOG6ZeyUl, Decide for yourself: spaces or tabs?, 2.83, ****
Up until what is explained, I have completed and tested to see if everything works. My problem is the next part of the project which requires the user to choose between Rating, Length, or title then sort them based on what the user chose.
If I chose Rating, then the input above should be sorted from highest rated video to lowest.
This is what I have so far:
#include <iostream>
#include <stdlib.h>
#include <cstring>
#include <algorithm>
using namespace std;
#include "video.h"
int main()
{
string user, url, comment, title;
int rating;
double length;
int i = 0, last = 0;
Video *videoObj[100];
Video *temp[100];
// specifies how the videos should be sorted
cin >> user;
cin.ignore();
while (getline(cin,title) ) {
getline(cin, url);
getline(cin, comment);
cin >> length;
cin >> rating;
cin.ignore();
videoObj[i] = new Video(title, url, comment, length, rating);
i++;
last++;
}
temp[i] = new Video(title, url, comment, length, rating);
if(user=="rating"){
for(int i = 0; i < last - 1; i++){
for(int j = i+1; j< last; j++){
if(videoObj[i] -> Rating(videoObj[j])) {
temp[i] = videoObj[i];
videoObj[i]= Rating(videoObj[j]);
Rating(videoObj[j]) = temp[i];
}
}
}
}
for(int i= 0; i < last; i++)
{
videoObj[i]->print();
}
//delete[] videoObj;
return 0;
}
video.cpp file:
#include <iostream>
#include <algorithm>
using namespace std;
#include "video.h"
Video::Video(string video_title, string video_link, string video_comment, double video_length, int video_number)
: title(video_title), link(video_link), comment(video_comment), length(video_length), rating(video_number)
{
}
bool Video::Rating(Video *videoObj) {
if(rating > videoObj-> rating )
{
return true;
}
else
{
return false;
}
}
void Video::print(){
string star;
switch(rating){
case 1:
star = "*";
break;
case 2:
star = "**";
break;
case 3:
star = "***";
break;
case 4:
star = "****";
break;
case 5:
star = "*****";
break;
}
cout << title << ", " << link << ", " << comment << ", " << length << ", " << star << endl;
}
void Video::temp(){
title, link, comment, length, rating;
}
video.h file:
#ifndef VIDEO_H
#define VIDEO_H
using namespace std;
class Video {
public:
Video(string video_title, string video_link, string video_comment, double video_length, int video_number);
void print();
bool Rating(Video *videoObj);
void temp();
private:
string title;
string link;
string comment;
double length;
int rating;
};
#endif
I honestly have no idea how to implement the bubble sort correctly. I have looked up multiple different videos on youtube and posts on stackoverflow, but I can't seem to figure out how to sort a specific parameter within my class.
My professor gave us these instructions for sorting within our class:
When sorting the videos you need to be able to determine how two video objects should be
ordered. The easiest way to do this is to write member functions to handle the comparisons in
class Video. For example, this method could be used when sorting the videos by length:
// return true if the current video is longer than the given video (other) ,
// otherwise return false
bool Video :: longer(Video *other) {
return (mlength > other -> mlength ;
}
I'm not even sure if I did that part correctly in my video.cpp file. Any ideas on how I can get the sorting method to work properly?
Please be gentle, I'm very new to programming. I realize my bubble sort is wrong as well, I just don't know where to start fixing it...
I'd normally use std::sort with a comparison operator for each field you want to be able to compare. You can implement those either as named classes:
struct by_title {
bool operator()(Video const &a, Video const &b) {
return a.title < b.title;
}
};
struct by_rating {
bool operator()(Video const &a, Video const &b) {
return a.rating < b.rating;
}
};
// ...
std::sort(videos.begin(), videos.end(), by_rating);
std::sort(videos.begin(), videos.end(), by_title);
...or you can use a lambda expression to define a comparison:
// sort by rating
std::sort(videos.begin(), videos.end(), [](auto &a, auto &b) { return a.rating < b.rating; });
// sort by title
std::sort(videos.begin(), videos.end(), [](auto &a, auto &b) { return a.title < b.title; });

How to print students name in ascending according to marks

I had sort the mark for all tests, quizzes, assignments and final exam in ASCENDING order. But I don't know how to display all student's name in ascending order based on their mark for each tests, quizzes, assignments and final exam.
Below are my code to sort each mark for tests, quizzes, assignments and final exam in ascending order. How to change the code so that it will display the students name, not the marks for each tests, quizzes, assignments and final exam?
Please, help. Thank you in advance.
#include <iostream>
#include <string>
using namespace std;
//global constant
const int NUM_STUDENTS=5;//row
const int NUM_SCORES=4;//col
string name[5]={"Hani","Haziq","Aiman","Farah","Sabrina"};
string mark[4]={"test","quiz","assignment","final exam"};
//Function prototypes
void ascenDescen(double [ ][NUM_SCORES],int);
int main ( )
{
cout<<"This program will help you keep track of your academic record!"<<endl;
double scores[NUM_STUDENTS][NUM_SCORES]=
{{9.0,2.7,16.0,78.0},
{7.4,2.7,19.0,88.0},
{8.9,3.5,17.5,93.7},
{10.0,3.0,19.5,64.8},
{6.3,3.0,16.0,74.2}};
//function call
ascenDescen(scores,NUM_STUDENTS);
cout<<endl;
cout<<"THANK YOU."<<endl;
return 0;
}
void ascenDescen (double table[][NUM_SCORES],int rows)
{
//for ascending
cout<<"Press ENTER to sort the mark for all tests, quizzes, assignments and final exam in ASCENDING order : \n\n";
char ch;
ch=cin.get();
double ascen;
for(int col=0;col<NUM_SCORES;col++)
{
for(int row=0;row<NUM_STUDENTS;row++)
{
for(int j=row+1;j<NUM_STUDENTS;++j)
{
if(table[row][col]>table[j][col])
{
ascen=table[row][col];
table[row][col]=table[j][col];
table[j][col]=ascen;
}
}
}
cout<<mark[col]<<" mark in ASCENDING order : \n";
for(int row=0;row<NUM_STUDENTS;row++)
{
cout<<" ";
cout<<table[row][col];
cout<<endl;
}
}
cout<<"________________________"<<endl;
}
A rule of thumb: If you need parallel arrays, chances are you should have a vector of struct.
Let's try modeling the data using a Student structure:
struct Student
{
std::string name;
std::vector<int> marks;
};
Thus far, every Student has a name and has some marks. The has-a relationship indicates composition. The is-a relationship indicates inheritance.
Let's add a sort method for the marks. The students will be easier to order by marks, if the marks are sorted.
struct Student
{
//...
void sort_marks()
{
std::sort(marks.begin(), marks.end()); // Assume default of `std::less<int>`
}
};
To perform an ordering other than the default, we'll need to define a custom ordering function:
bool Order_By_Marks(const Student& a, const Student& b)
{
bool a_is_less_than_b = true;
unsigned int quantity_of_marks = a.marks.size();
if (b.marks.size() < quantity_of_marks)
{
quantity_of_marks = b.marks.size();
}
for (unsigned int i = 0; i < quantity_of_marks; ++i)
{
if (a.marks[i] > b.marks[i])
{
a_is_less_than_b = false;
break;
}
}
return a_is_less_than_b;
}
To sort a database of Student by marks:
std::vector<Student> database;
// ... input students ...
for (i = 0; i < database.size(); ++i)
{
database[i].sort_marks();
}
std::sort(database.begin(), database.end(), Order_By_Marks);
You'll need to walk through the code with a debugger to verify the ordering of the student marks and also the ordering of the students by mark.
#include <iostream>
#include <string>
using namespace std;
//global constant
const int NUM_STUDENTS=5;//row
const int NUM_SCORES=4;//col
string name[5]={"Hani","Haziq","Aiman","Farah","Sabrina"};
string mark[4]={"test","quiz","assignment","final exam"};
struct student {
};
//Function prototypes
void ascenDescen(double [ ][NUM_SCORES],int);
int main ( )
{
cout<<"This program will help you keep track of your academic record!"<<endl;
double scores[NUM_STUDENTS][NUM_SCORES]=
{{9.0,2.7,16.0,78.0},
{7.4,2.7,19.0,88.0},
{8.9,3.5,17.5,93.7},
{10.0,3.0,19.5,64.8},
{6.3,3.0,16.0,74.2}};
//function call
ascenDescen(scores,NUM_STUDENTS);
cout<<endl;
cout<<"THANK YOU."<<endl;
return 0;
}
void ascenDescen (double table[][NUM_SCORES],int rows)
{
//for ascending
cout<<"Press ENTER to sort the mark for all tests, quizzes, assignments and final exam in ASCENDING order : \n\n";
cin.get();
double ascen;
string temp1[5] = name;
string temp2;
for(int col=0;col<NUM_SCORES;col++)
{
for(int row=0;row<NUM_STUDENTS;row++)
{
for(int j=row+1;j<NUM_STUDENTS;++j)
{
if(table[row][col]>table[j][col])
{
ascen=table[row][col];
temp2 = temp1[row];
table[row][col]=table[j][col];
temp1[row] = temp1[j];
table[j][col]=ascen;
temp1[j] = temp2;
}
}
}
cout<<mark[col]<<" mark in ASCENDING order : \n";
for(int row=0;row<NUM_STUDENTS;row++)
{
cout<<" ";
cout << temp1[row] << " " <<table[row][col];
cout<<endl;
}
for(int i = 0; i < NUM_STUDENTS; i++)
{
temp1[i] = name[i];
}
}
cout<<"________________________"<<endl;
}

Segmentation fault (core dumped) C++ Object Oriented Programming

I'm a student of system engineering, 2nd semester of the ULA (Universidad de los Andes)
So, I'm programming a c++ mini project for university. The project consists of making a draft of a software oriented to buying and selling crypto currencies, however, since yesterday I've been getting a problem with it (a segmentation fault core dumped specifically)... So, as this page had been helpful with my previous programs and this time I didn't find something that could have helped me, I decided to register and ask in case someone is willing to help me.
#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;
class usuario {
private :
string username[10], password[10];
int aux;
public :
usuario();
void setUnamep(string, string, int);
string getUnamep();
void setPass(string);
string getPass();
int DataAcc(string, string);
~usuario();
};
class moneda {
protected :
float cantidad;
public :
moneda(float);
void setCant(float);
void getCant();
~moneda();
};
class bitcoin : public moneda {
private :
float btc[20];
public :
bitcoin (float);
void setBuy(float, float[]);
void getBuy();
void mostrarc(float);
~bitcoin();
};
usuario::usuario () {
}
void usuario::setUnamep(string username_, string password_, int aux_) {
string PreUser[20], aux_2;
aux = aux_;
for (int i= 1; i <= aux; i++) {
username[i] = username_[i];
password[i] = password_[i];
cout<<"\nEnter an username: ";
cin>>username[i];
cout<<"Enter a password: ";
cin>>password[i];
username[0] = "."; //pass 1 leer
for (int v = 0 ; v < i; v++) {
if (username[v] == username[i]) {
cout<<"\nUsername already in use. Choose another"<<endl;
username[i] = "null";
password[i] = "null";
i--;
v = 20000;
}
}
}
}
int usuario::DataAcc(string InUs, string InPass) {
bool ing = false, ret = false;
int u = 0;
do {
if (InUs==username[u] and InPass==password[u]) {
ing = true;
u = 10;
ret = true;
}
else //////
u++;
}
while (ing == false and u<5);
if (u == 5)
cout<<"\nIncorrect user or password. Try again."<<endl;
if (ing == true) {
cout<<"\nAccount data..."<<endl;
}
return ret;
}
usuario::~usuario() {
}
moneda::moneda(float cantidad_) {
cantidad = cantidad_;
}
moneda::~moneda() {
}
bitcoin::bitcoin(float cantidad_) : moneda(cantidad_) {
}
void bitcoin::setBuy(float cantidad_, float btc_[]) {
int aux;
for (int i = 0; i < 20 ; i++) {
btc[i] = btc_[i];
}
cout<<"How many BTC do you wish to buy?: ";
cin>>cantidad;
btc[aux] = btc[aux] + cantidad;
}
bitcoin::~bitcoin() {
}
int main() {
int opc = 0, aux1;
string InUs, InPass;
int aux2 = 0;
bitcoin b1(0);
cout<<"Welcome to BitZuela 2018, down there you have several options for you to choice which one do you want to run. ";
cout<<"\n\n1. Sign Up."<<endl;
cout<<"2. Log in."<<endl;
cout<<"3. Finish program."<<endl;
usuario u1;
while (opc >=0 and opc <=2) {
cout<<"\nPress the button of the option you want to run: ";
cin>>opc;
if (opc==1) {
cout<<"\nHow many accounts do you want to register?: ";
cin>>aux1;
u1.setUnamep("null", "null", aux1);
}
if (opc==2) {
cout<<"\nUsername: ";
cin>>InUs;
cout<<"Password: ";
cin>>InPass;
aux2 = u1.DataAcc(InUs, InPass);
if (aux2 == 1) {
b1.setBuy(0,0); //The problem is when this object is created
}
}
if (opc == 3)
cout<<"\nProgram finished."<<endl;
}
return 0;
}
That's it, I would be very grateful if someone can help me solving this problem. Also, if you have a suggestion about another thing, It'll be a pleasure to read it!
There seems to be some trouble with this method
void bitcoin::setBuy(float cantidad_, float btc_[]) {
int aux;
for (int i = 0; i < 20 ; i++) {
btc[i] = btc_[i];
}
cout<<"How many BTC do you wish to buy?: ";
cin>>cantidad;
btc[aux] = btc[aux] + cantidad;
}
The 'aux' variable is used before it is set resulting in undefined behavior.
Also the call is passing a 0 instead of a float[]. The compiler interprets the 0 as a nullptr, resulting a crash in ::setBuy
if (aux2 == 1) {
b1.setBuy(0,0);
Probably some other issues but fixing these will be a step in the right direction
Your core dumped is in the setBuy function. You ask for an array of float, but when you call it in your code, you pass a "0", but you should pass an array of 20 elements.
The aux variable is set inside the function, but I think you should pass it from the signature of the function.
Also, the cantidad variable that you are using inside that function is not the one in the signature (you should remove it from the signature, or add an _ to cantidad).
I also looked into your setUnamep function, you should use an std::map for your username and password management (You can search for an already existing keys in log(n)).

windows causing breaking point

I am writing a program for a class assignment on learning about pointers and memory management. Allocating memory for student and courses is necessary with the new operator in this assignment and the program seems to run properly but after it prints everything the program crashes and it says that that it has triggered a break point. Any help would be appreciated.
The error is located here but I'm not sure what it means
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
struct Student //Structs
{
string firstName, lastName, aNumber;
double GPA;
};
struct Course
{
int courseNumber, creditHours;
string courseName;
char grade;
};
Student* readStudent(); // Function Prototypes
Course* readCourseArray(int&);
void computeGPA(Student *student, Course *courseArray, int coursesTaken);
void printSummary(Student *studentPTR, Course *courseArray, int courses);
int main() //Main
{
int courses = 0;
Student *studentPTR = readStudent();
Course *coursePTR = readCourseArray(courses);
computeGPA(studentPTR, coursePTR, courses);
printSummary(studentPTR, coursePTR, courses);
delete studentPTR;
delete coursePTR;
system ("pause");
return 0;
}
Student* readStudent() // Read Student
{
Student* student = new Student;
cout<<"\nEnter students first name\n";
cin>>student->firstName;
cout<<"\nEnter students last name\n";
cin>>student->lastName;
cout<<"\nEnter students A-Number\n";
cin>>student->aNumber;
return student;
}
Course* readCourseArray(int &courses) //Read Courses
{
cout<<"\nHow many courses is the student taking?\n";
cin>>courses;
const int *sizePTR = &courses;
Course *coursePTR = new Course[*sizePTR];
for(int count = 0; count < *sizePTR; count++) //Enter course information
{
cout<<"\nEnter student "<<count+1<<"'s course name\n";
cin>>coursePTR[count].courseName;
cout<<"\nEnter student "<<count+1<<"'s course number\n";
cin>>coursePTR[count].courseNumber;
cout<<"\nEnter student "<<count+1<<"'s credit hours\n";
cin>>coursePTR[count].creditHours;
cout<<"\nEnter student "<<count+1<<"'s grade\n";
cin>>coursePTR[count].grade;
}
return coursePTR;
}
void computeGPA(Student *studentPTR, Course *courseArray, int coursesTaken) // Compute GPA
{
double total = 0, hours = 0;
for(int count = 0; count < coursesTaken; count++)
{
hours += courseArray[count].creditHours;
if (courseArray[count].grade == 'A')
total+=4;
else if (courseArray[count].grade == 'B')
total+=3;
else if (courseArray[count].grade == 'C')
total+=2;
else if (courseArray[count].grade == 'D')
total+=1;
else if (courseArray[count].grade == 'F')
total+=0;
}
studentPTR->GPA = (total / hours);
}
void printSummary(Student *studentPTR, Course *courseArray, int courses)
{
cout<<"\nReport\n";
cout<<"\nNumber Name Hours Letter Grade Point Grade";
cout<<"\n------ ---- ----- ------------ -----------\n";
for(int count = 0; count < courses; count++)
cout<<setw(3)<<courseArray[count].courseNumber<<" "<<courseArray[count].courseName<<setw(20)<<" "<<courseArray[count].creditHours<<setw(5)<<" "<<courseArray[count].grade<<endl;
cout<<"\nStudent :"<<studentPTR->firstName<<" "<<studentPTR->lastName;
cout<<"\nA-Number :"<<studentPTR->aNumber;
cout<<"\nOverall GPA :"<<studentPTR->GPA;
}
You're allocating courses with operator new[] (which is for arrays), but freeing it with operator delete, instead of operator delete[].
You should deallocate it like that:
delete[] coursePTR;
I also don't understand why you use the sizePTR pointer instead of directly using courses.
BTW, just so you'd know, this is not a 'find my bug' site. You have a code review site for that.
You need to change
delete coursePTR;
to
delete [] coursePTR;
new always needs to be used with delete, and new [] with delete [], otherwise bad things happen.

Array not being assigned correctly

I'm trying to write a program that accepts user input for a file name. From there it stores the numbers in the file into an array, sorts them, then displays them. However, i'm getting large numbers similar to accessing an out-of-bounds array, but I can tell from the debugger i'm not.
#include <iostream>
using namespace std;
class TestScores
{
public:
TestScores();
TestScores(int scores);
~TestScores();
void AddScore(int newScore);
void DisplayArray();
void SortScores();
bool ArraySorted();
int AvgScore();
private:
int *scoresArray; //Dynamically allocated array
int numScores; //number of scores input by user
int scoreCounter;
const static int default_NumArrays=10; //Default number of arrays
};
#include <iostream>
#include "TestScores.h"
TestScores::TestScores()
{
scoresArray=new int[default_NumArrays];
scoreCounter=0;
numScores=default_NumArrays;
}
TestScores::TestScores(int scores)
{
scoresArray=new int[scores];
numScores=scores;
scoreCounter=0;
for(int i=0; i<scores;i++)
scoresArray[i]=0;
}
TestScores::~TestScores()
{
delete[] scoresArray;
}
void TestScores::AddScore(int newScore)
{
if(scoreCounter<numScores){
scoresArray[scoreCounter]=newScore;
scoreCounter++;
}
else
cout<<"More scores input than number of scores designated"<<endl;
}
void TestScores::DisplayArray()
{
for(int i=0; i<numScores; i++)
cout<<scoresArray[i]<<endl;
cout<<endl<<"This is scoresArray"<<endl;
}
bool TestScores::ArraySorted()
{
for(int i=0; i<(scoreCounter-1);i++){
if(scoresArray[i]<=scoresArray[i+1])
continue;
else
return false;
}
return true;
}
void TestScores::SortScores()
{
int tempValue;
while(ArraySorted()!=true){
for(int i=0; i<(scoreCounter-1); i++){
if(scoresArray[i]<=scoresArray[i+1])
continue;
else{
tempValue=scoresArray[i+1];
scoresArray[i+1]=scoresArray[i];
scoresArray[i]=tempValue;
}
}
}
}
int TestScores::AvgScore()
{
int sumScores=0;
if(scoreCounter>0){
for(int i=0; i<scoreCounter; i++)
sumScores+=scoresArray[i];
return (sumScores/scoreCounter);
}
else{
cout<<"There are no scores stored."<<endl;
return 0;
}
}
#include "TestScores.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
//Function prototypes
bool FileTest(ifstream& inData);
void StoreScores(ifstream& inData, int& newNumScores, TestScores satScores);
int main()
{
int newNumScores=0;
string inputFile; //Contains name of the user file being used
//Opening file stream
ifstream inData;
//User prompt for input file
cout<<"Please enter the file name containing the student scores you wish to "
<<"have stored, sorted, and displayed."<<endl;
cin>>inputFile;
//Opening file streams
inData.open(inputFile.c_str());
while(FileTest(inData)==false){
cout<<"I'm sorry, the file you entered was not a valid file. "
<<"Please enter another file name, or enter q to exit"<<endl;
cin>>inputFile;
if(inputFile=="q")
return 0;
//Opening file streams
inData.open(inputFile.c_str());
}
inData>>newNumScores;
TestScores satScores(newNumScores); //Instantiating TestScores variable
StoreScores(inData, newNumScores, satScores); //Storing scores into array
satScores.DisplayArray();
satScores.SortScores();
satScores.DisplayArray();
cout<<endl<<"This is the array after sorting"<<endl<<endl;
cout<<"This is the average score "<<satScores.AvgScore()<<endl;
//Program pauses for user input to continue
char exit_char;
cout<<"\nPress any key and <enter> to exit\n";
cin>>exit_char;
inData.close();
return 0;
}
bool FileTest(ifstream& inData)
{
if(!inData)
{
cout<<"Your file did not open.\n";
return false;
}
return true;
}
void StoreScores(ifstream& inData, int& newNumScores, TestScores satScores)
{
int userScore;
while(inData>>userScore){
satScores.AddScore(userScore);
}
}
My test file is random.dat and contains the following:
15
67
76
78
56
45
234
Based on looking through the debugger, I can tell that scoreCounter is incrementing correctly and that newScore contains the next value, so why isn't it being stored in the array? Thanks for the help
Okay, the problem is pretty simple: You pass satScores by value to StoreScores. This will only fill the local copy, change the signature of StoreScores to the following to fix:
void StoreScores(ifstream& inData, int& newNumScores, TestScores& satScores)
(Btw you don't actually use the newNumScores variable.)
The output is then as expected:
15
67
76
78
56
45
234
0
0
0
0
0
0
0
0
0
0
For further improvement of your code, see GMan's comment and Ben's answer.
You have a user-defined destructor but no copy-constructor or assignment operator. No wonder assignment doesn't work right, you get a leak of one buffer and double-free of the other.
Follow the Rule of Three. Or better yet, use a container that's already been debugged, like std::vector.