Code keeps displaying variable even after it is deleted - c++

I am still new to c++ and just started to learn about classes and OOP. I have been practicing trying to make classes out of any item I can think of, so I made a phone class. Code is below. The problem is no matter what number I give it, it displays the same WRONG number everytime. The crazy thing is in the beginning I had given the phone class a variable to store its own number and gave the class instance its own number. That number is the number it keeps wanting to "call". Even after going back several times and making sure I wasn't calling the wring variable I completely deleted the variable and the code still displays the same number. The number is 214-748-3647. Makes me feel like my computer is haunted. Could anyone help?
CODE DOESN'T ACTUALLY MAKE ANY SORT OF PHONE CALL OR ANY CONNECTION WHAT SO EVER
PHONE CLASS HEADER
#ifndef PHONE_H_INCLUDED
#define PHONE_H_INCLUDED
#include <string>
using namespace std;
class Phone{
public:
string Brand;
int Serial;
string CellId;
void Call();
private:
void Dial(int NumberToDial);
void EndCall();
};
#endif // PHONE_H_INCLUDED
PHONE SOURCE CODE
#include <iostream>
#include <string>
#include <sstream>
#include "phone.h"
using namespace std;
void Phone::Call(){
string UserInput = "0";
int NumberToCall = 0;
cout << "What number would you like to call?" << endl << endl;
getline(cin, UserInput);
if(UserInput.length() != 10){
cout << endl << "invalid digits" << endl;
Call();
}
else{
stringstream(UserInput) >> NumberToCall;
Dial(NumberToCall);
}
}
void Phone::Dial(int NumberToDial = 0){
ostringstream converter;
string Number;
converter << NumberToDial;
Number = converter.str();
cout << "Dialing ";
for(int i=0;i<10;i++){
cout << Number[i];
if(i==2){
cout << "-";
}
if(i==5){
cout << "-";
}
}
cout << endl << endl << "Press any key to end the call..." << endl << endl;
cin.get();
EndCall();
}
void Phone::EndCall(){
cout << "Call ended." << endl << endl;
}
Aaaaannnnd my MAIN
#include <iostream>
#include <cstdlib>
#include "phone.h"
using namespace std;
int main()
{
Phone MyPhone;
MyPhone.Brand = "iPhone 5";
MyPhone.CellId = "F2D9G3A2";
MyPhone.Serial = 1411512;
MyPhone.Call();
return 0;
}

This is a very simple answer. You're code and logic is fine. The error occurs because you convert the std::string which holds the phone number to an integer. This is a problem because a typical 10 digit phone number is too big to fit inside the int type. Have a look here to see the min and max numbers you can fit in different types: http://www.cplusplus.com/reference/climits/
Look at this line here actually.
Maximum value for an object of type long int: 2147483647 (231-1) or greater
Funny how the max value is that mysterious phone number.

Related

Reference to List of Objects invalid in Constructor

I am working on some code to make a wallet to hold different currencies and this is my first time programming in c++ as a c programmer. Every time I make a new currency I want to add it to the list of valid Currencies that my wallet will be able to hold. To do this I make a currency class with a list that I want to add to every time a new currency is spawned. The error I get is error: no matching function for call to ‘std::__cxx11::list<Currency>::push_back(Currency*) CurrencyList.push_back(this);"\
Currency.h looks like:
#ifndef CURRENCY_H
#define CURRENCY_H
#include <string>
#include <list>
class Currency {
public:
//Instances of class
int id;
float max;
float left_over;
std::string coinName;
//Methods
float buyFrom(float amount);
float sellBack(float amount);
//constructor
Currency();
};
extern std::list<Currency> CurrencyList; //global list
#endif
Currency.c looks like
#include "currency.h"
#include <iostream>
Currency::Currency() {
Currency::id = 0;
std::cout << "Input name :" << std::endl;
std::cin >> Currency::coinName;
std::cout << "Input max :" << std::endl;
std::cin >> Currency::max;
Currency::left_over = Currency::max - 0;
CurrencyList.push_back(this);
}
float Currency::buyFrom(float amount) {
Currency::left_over-=amount;
std::cout << "Currency just lost :" << amount << "remaining is : " << Currency::left_over << std::endl;
}
float Currency::sellBack(float amount) {
Currency::left_over -= amount;
std::cout << "Currency just gained : " << amount << " remaining is : " << Currency::left_over << std::endl;;
}
The main is quiet simple it is only meant to spawn an object to test, that looks something like this.
Main.cpp
#include <iostream>
#include "wallet.h"
#include "currency.h"
int main(){
std::cout << "Hello World" << std::endl;
Currency currencyTest;
currencyTest.buyFrom(200.3);
}
Note that this is a pointer, but your list holds actual objects, not pointers.
So just dereference the pointer and you should be fine:
CurrencyList.push_back(*this);

OOP can't get value from a class

So I read a file in a function and set values to a class. I would like to read those same values in another function (another .cpp file) and I can't get it to work.
This is the code where I read values from .txt file. This seems to work. I can cout the value that I read.
#include "branjeDatoteke.h"
#include "parametri.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
using namespace std;
void branjeDatoteke() {
Parametri pin[101];
string line;
ifstream myfile("pin.txt");
if (myfile.is_open())
{
for (int i = 0; i <= 100 && getline(myfile, line); i++)
{
pin[i].setPin(line);
// cout << pin[i].readPin() << endl;
//cout << line << '\n';
}
myfile.close();
// cout <<"tole more delat: "<< pin[2].readPin() << endl;
}
else cout << "Unable to open file";
}
And this is the code where I want to get the same values again, but cout is not working. I just get blank console where the cout should be.
#include <iostream>
#include "pin.h"
#include "parametri.h"
#include <string>
#include "branjeDatoteke.h"
using namespace std;
void pinPass() {
Parametri pin[101];
string pinKoda;
branjeDatoteke();
cout << pin[0].readPin() << endl;
cout << "Vnesite pin: ";
cin >> pinKoda;
for (int i = 0; i <= 100; i++) {
if (pin[i].readPin() == pinKoda) {
cout << pin[i].readPin() << endl;
cout << "KODA JE PRAVILNA" << endl;
}
else if (i > 100) {
cout << "kode ni v sistemu" << endl;
}
}
}
Assuming your Parametri class is correct, the issue is you are using local variables so they are initialised every time you call the function. They are allocated on the stack, locally for the calling function and can't be used outside of the function that declares them, at least not the way you're doing it. If you call the function twice you also have to assume all local variables must be reinitialised. One way you could solve this would be promoting your pin variable to global, like so:
// your_file_one.cpp
Parametri pin[101];
void PinPass() {
...
}
If you want to use it in another cpp file, then you have to redeclare the variable in the other file as well, like follows:
// your_file_two.cpp
extern Parametri pin[101];
The extern keyword specifies the variable was declared in another compilation unit - for simplicity let's imagine each C++ file which is not a header file as a separate compilation unit.
So your code will look like:
#include "branjeDatoteke.h"
#include "parametri.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
using namespace std;
Parametri pin[101];
void branjeDatoteke() {
string line;
ifstream myfile("pin.txt");
if (myfile.is_open())
{
for (int i = 0; i <= 100 && getline(myfile, line); i++)
{
pin[i].setPin(line);
// cout << pin[i].readPin() << endl;
//cout << line << '\n';
}
myfile.close();
// cout <<"tole more delat: "<< pin[2].readPin() << endl;
}
else cout << "Unable to open file";
}
And
#include <iostream>
#include "pin.h"
#include "parametri.h"
#include <string>
#include "branjeDatoteke.h"
using namespace std;
extern Parametri pin[101];
void pinPass() {
string pinKoda;
branjeDatoteke();
cout << pin[0].readPin() << endl;
cout << "Vnesite pin: ";
cin >> pinKoda;
for (int i = 0; i <= 100; i++) {
if (pin[i].readPin() == pinKoda) {
cout << pin[i].readPin() << endl;
cout << "KODA JE PRAVILNA" << endl;
}
else if (i > 100) {
cout << "kode ni v sistemu" << endl;
}
}
}
There are better ways of using global variables than declaring them many times and you may want to research these if you're going to write bigger programs. Also global variables are very useful in certain instances but must not be abused as they can make bigger applications much more difficult to read and maintain.
The Parametri array in your pinPass function is empty(or more precisely , has garbage values).You call the branjeDatoteke function from within pinPass , the
branjeDatoteke function then creates it's own Parametri array (WHICH IS DIFFERENT from the one in your pinPass function),reads the values from the file and displays it via cout.
When branjeDatoteke is done with it's work , all the local variables of that function , inlcuding the Parametri array are destroyed and your program jumps back to the pinPass function.
To do what you're trying to achieve , which is , presumably , have a common array for both the functions, you can either pass the array from pinPass to branjeDatokete , or you can tell branjoDatokete to allocate an array on the heap and then return a pointer to it.I guess the first approach fits better for what you're trying to achieve.

C++ Batting Average program trouble using Input/Output files to print names, averages, highest/lowest averages

I have this batting average program. My problem is that I cannot output this program using input/output files so that it shows the highest/lowest averages and the names to go with them. The code I have in main is not right because it is only outputting "Highest batting average is: 0" and "Players with the highest batting average: " None of the averages are 0 so it should not be outputting that, and there should be a name next to the highest batting average. The same goes with the lowest. This is what I have so far:
#include "Player.h"
#include "Stack.h"
#include <fstream>
using namespace std;
int main()
{
Player x;
string name;
double avg;
ifstream infile("avgs.txt");
while (infile >> name >> avg)
{
x.insertPlayer(name, avg);
}
infile.close();
x.printHigh();
x.printLow();
if(!infile)
{
cout << "Unable to open the file for writing " << endl;
exit(0);
}
ofstream outfile("avgs.txt");
if (!outfile)
{
cout << "Error opening file " << endl;
exit(0);
}
outfile << endl;
}
Here are the files to the Player class, and the Stack class in case it is needed aswell:
////Player.h
#include "stdafx.h"
#include <iostream>
#include <string>
#include "Stack.h"
using std::string;
class Player
{
public:
double lowest;
double highest;
Stack<string> low;
Stack <string> high;
void insertPlayer(string name, double batAvg);
void printHigh();
void printLow();
};
This is the .cpp file for the Player class:
#include "stdafx.h"
#include <iostream>
#include <string>
#include "Player.h"
using namespace std;
using std::string;
void Player::insertPlayer(string name, double batAvg)
{
cout << "Player " << name << " has an average of: " << batAvg << endl;
if (low.empty() && high.empty())
{
low.push(name);
high.push(name);
highest = lowest = batAvg;
}
else
{
if (batAvg>highest)
{
while (!high.empty())
high.pop();
highest = batAvg;
high.push(name);
}
else if (batAvg == highest)
high.push(name);
else if (batAvg<lowest)
{
while (!low.empty())
low.pop();
lowest = batAvg;
low.push(name);
}
else if (batAvg == lowest)
low.push(name);
}
}
void Player::printHigh()
{
cout << "Highest batting average is: " << highest << endl;
cout << "Players with the highest batting average: " << endl;
}
void Player::printLow()
{
cout << "Lowest batting average is: " << lowest << endl;
cout << "Players with the lowest batting average: " << endl;
}
And my Stack class if it is needed:
#ifndef STACK
#define STACK
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class Stack : public exception
{
private:
vector<T>myStacks;
public:
void push(T const& uStack);
void pop();
T peek() const;
bool empty() const
{
return myStacks.empty();
}
};
template <class T>
void Stack<T>::push(T const& uStack)
{
myStacks.push_back(uStack);
}
template <class T>
void Stack<T>::pop()
{
if (myStacks.empty())
{
throw std::out_of_range("Stack <>::pop(): This is an empty stack ");
}
myStacks.pop_back();
}
template <class T>
T Stack<T>::peek() const
{
if (myStacks.empty())
{
throw std::out_of_range("Stack<>::peek(): This is an empty stack ");
}
return myStacks.back();
}
#endif
The focus code that I am trying to output is Player.cpp, but the Stack.h and Player.h are needed to make it run. In main() I need to output the names, averages, and the people with the highest/lowest averages. Any help is appreciated!
The text file consists of players and their averages, for example:
Orlando .775
Charles .606
J.D. .775
Gina .400
Sam .702
Rich .686
and so on.
The first thing you want to do is remove everything after x.printLow(); in main, then verify that the expected input is present in avgs.txt.
Your code will overwrite the input file with a single newline, so if you have tried it once, you probably haven't got the input you expect anymore. Notice how you never see output from cout << "Player " << name << " has an average of: " << batAvg << endl;. That indicates insertPlayer is not being called.
I'm pretty sure it is a problem with finding your input file, as it works with a different input source. Is the file with the text in the same folder as your .exe? Is it instead in a different folder, such as where the source files are?
A simple test would be to just copy the contents of the file to cout, to see what the program finds
int main() {
std::ifstream infile("avgs.txt");
for (std::string line; std::getline(infile, line;) {
std::cout << line << std::endl;
}
}

Make console title bar display the value of a variable

I'm working on a small program that counts up to a number given by the user. The number they enter is stored in the variable limit. I want the number in that variable to be displayed in the title kind of like this: "Counting up to 3000" or "Limit set to 3000" or something like that. I've tried using SetConsoleTitle(limit); and other things but they just don't work. With the code that I have posted bellow, I get the following error:
argument of type "int" is incompatible with parameter of type "LPCWSTR"
I'm currently using Visual Studio 2015 if that's important in any way.
#include <iostream>
#include <windows.h>
#include <stdlib.h>
using namespace std;
int main()
{
begin:
int limit;
cout << "Enter a number you would like to count up to and press any key to start" << endl;
cin >> limit;
SetConsoleTitle(limit); // This is my problem
int x = 0;
while (x >= 0)
{
cout << x << endl;
x++;
if (x == limit)
{
cout << "Reached limit of " << limit << endl;
system("pause");
system("cls");
goto begin;
}
}
system("pause");
return 0;
}
The SetConsoleTitle() function expects a string as its argument, but you're giving it an integer. One possible solution would be to use std::to_wstring() to convert an integer to a wide-character string. C++ string that you get as a result has a different format from the null-terminated wide-character string that SetConsoleTitle() expects, so we need to make the necessary conversion using the c_str() method. So, instead of
SetConsoleTitle(limit);
you should have
SetConsoleTitle(to_wstring(limit).c_str());
Don't forget to #include <string> for to_wstring() to work.
If you want a title that includes more than just a number, you'll need to use a string stream (a wide character string stream in this case):
wstringstream titleStream;
titleStream << "Counting to " << limit << " goes here";
SetConsoleTitle(titleStream.str().c_str());
For string streams to work, #include <sstream>. Here's the full code:
#include <iostream>
#include <string>
#include <sstream>
#include <windows.h>
#include <stdlib.h>
using namespace std;
int main()
{
begin:
int limit;
cout << "Enter a number you would like to count up to and press any key to start" << endl;
cin >> limit;
wstringstream titleStream;
titleStream << "Counting to " << limit << " goes here";
SetConsoleTitle(titleStream.str().c_str());
int x = 0;
while (x >= 0)
{
cout << x << endl;
x++;
if (x == limit)
{
cout << "Reached limit of " << limit << endl;
system("pause");
system("cls");
goto begin;
}
}
system("pause");
return 0;
}

Storing a objects derived from an abstract base class with maps in a vector array of base class pointers

I'm writing a program that uses OOP to store student records. At the moment I only have two classes, one for each individual course module called 'Courses', and one ( well two if you count the abstract base class) for the type of degree programme called 'Physics' derived from the 'Records' base class.
I'm using two maps in the program. One to store the individual courses for each individual record and sort them by course code, and one to store all the records and sort them by ID numbers.
I planned on having the user input all student information, including codes, storing this in a vector (named 'prec' in the code), then pushing the vector elements into the map used to store all the records. The code is far from finished, I was just attempting to run it to see if I was on the right track.
The code builds without any errors, but when I attempt to run it, it comes up with the error message: " Debug assertion failed: expression vector subscript out of range". I feel this may have something to do with the way I am using individual vector elements to call my functions to store courses in the maps but I cant quite get it, any help would be much appreciated!
Here are my files:
header file:
#ifndef MY_CLASS_H // Pre-processor directives to prevent multiple definition
#define MY_CLASS_h
#include <iostream>
#include <string>
#include <utility>
#include <map>
#include <fstream>
using std::string;
using std::ostream;
using std::map;
using std::cout;
using std::endl;
using std::cin;
namespace student_record // Defines the namespace student_record in which the classes are defined
{
class Course { /* Create class Course for individual courses, is this better than incorporating
all the data separately into the Record class below? Class contains course name, mark achieved and mark weight and course ID */
protected:
string course_name;
double course_mark;
int course_Id;
public:
Course() {course_name= "Null"; // Default constructor for null course
course_mark=0;
}
Course(string course_namein, double course_markin, int course_Idin) {course_name=course_namein; // Parametrized constructor to create course with set name, mark, weight and course ID
course_mark=course_markin;
course_Id=course_Idin;}
~Course() {course_name.erase(0,course_name.size());} // Destructor to delete the course name
// Access functions to get name, mark and weight //
double getmark() const {return course_mark;}
string getname() const {return course_name;}
int getid() const {return course_Id;}
friend ostream & operator << (ostream &os, const Course &c); // Friend function to overload the insertion operator for courses
};
class Record
{ // Create class Record as abstract base class for all inherited degree classes
protected:
string student_name;
int studentid;
int years;
public:
Record() {student_name="Casper";
studentid=0;
years=0;} // Default constructor for class Record, produces empty record
Record(string name, int number, int time) {student_name=name;
studentid=number;
years=time;} // Parametrized constructor for class Record
~Record() {student_name.erase(0, student_name.size());} // Destructor to delete the student name
virtual int getid()const=0;
virtual int getyears()const=0;
virtual void show_record()const=0;
virtual void print_record(string *filename)const=0;
virtual void degree_class()const=0;
virtual void insert_class()=0;
/* Virtual functions defined to be used in the derived classes (subjects ie, Physics, stamp collecting, etc...)
Thus the base class Record is abstract*/
};
class Physics: public Record
{
private:
string degree_name;
typedef map <int, Course> course_map;
course_map modules;
void searchdatabase (course_map &courses, int coursecode)const; // Uses iterator to search map for corresponding course to inputted key ( remember to move to function definitions)
string get_name (const int i, course_map &temp) const{ return temp[i].getname();}
double get_mark(const int i, course_map &temp)const{ return temp[i].getmark();} // Functions to return the mark, weight and name of a given course corresponding to inputed course code
int getid()const{return studentid;}
int getyears()const{return years;}
void show_record()const;
void print_record( string *filename) const;
void degree_class()const;
void insert_class();
// Function to insert record into map
public:
Physics():Record(){degree_name= "Physics ";}
Physics(string name,int Id, int time):Record( name, Id, time){degree_name= "Physics";}
~Physics() {degree_name.erase(0, degree_name.size());}
};
}
#endif
function definitions:
#include <iostream>
#include <string>
#include <utility>
#include <map>
#include <fstream>
#include <vector>
#include "Database_header.h"
using namespace std;
using namespace student_record;
ostream & student_record::operator<< (ostream &os, const Course &c)
{
os<< "Course code" << c.course_Id << " \n Course name: " <<c.course_name << " \n Mark " << c.course_mark <<endl;
return os;
}
// Function to insert classes //
void Physics::insert_class()
{
int courseid;
string coursename;
double mark;
cout << " Enter course code " << endl;
cin >> courseid;
cout << " \n Enter course name " << endl;
cin >> coursename;
cout << " \n Enter mark achieved " << endl;
cin >> mark;
Course temp (coursename, mark, courseid);
modules.insert(pair<int, Course>(courseid, temp));
}
void Physics::searchdatabase(course_map &courses, int coursecode) const // Function to search for specific course mark based on course code, need to modify this!!!!
//takes in a map as its argument, although i suppose can use student.modules?
{
course_map::iterator coursesIter;
coursesIter=courses.find(coursecode);
if(coursesIter != courses.end())
{
cout << " Course Code " <<
coursecode << " corresponds to " <<
coursesIter ->second << endl;
}
else { cout << " Sorry, course not found " << endl; }
}
void Physics::print_record( string *filename) const // Function for printing record to the file
{
ofstream myoutputfile;
myoutputfile.open(*filename,ios::app);
if(!myoutputfile.good())
{
// Print error message and exit
cerr<<"Error: file could not be opened"<<endl;
}
if(myoutputfile.good())
{
myoutputfile << "Student name: " << student_name << endl
<< "\n Student ID: " << studentid << endl
<< "\n Year: " << years << endl;
course_map::iterator modulesiter; // Iterator to print out courses using overloaded << function (I think?)
for(modulesiter==modules.begin();modulesiter!=modules.end();modulesiter++)
{
myoutputfile<<modulesiter->second << endl;
}
}
}
void Physics::show_record() const // Function for showing specific student record on screen ( with iterator for map of courses)
{
cout << "Student name: " << student_name;
cout << "\n Student ID: " << studentid;
cout << "\n Years on course: " << years;
cout << "\n Courses and grades: ";
course_map::iterator modulesiter; // Iterator to print out courses using overloaded << function (I think?)
for(modulesiter==modules.begin();modulesiter!=modules.end();modulesiter++)
{
cout<<modulesiter->second << endl;
}
}
void Physics::degree_class()const
{
double temp;
vector<double> dynarr; // Create a vector array to store the grades extracted from the course map for each student
course_map::iterator modulesiter;
for(modulesiter==modules.begin();modulesiter!=modules.end();modulesiter++) // Iterate through map and push values into each vector
{
Course ghost;
ghost=modulesiter->second;
dynarr.push_back(ghost.getmark());
}
double sum(0);
for(int i(0);i<=dynarr.size();i++)
{
sum+=dynarr[i];
}
temp=sum/dynarr.size();
if( temp>=40 && temp <=49.9)
{
cout << "The student has achieved a 3rd class degree with an average of: \n "
<< temp;
}
else if( temp>=50 && temp <=59.9)
{
cout << "The student has achieved a 2:2 degree with an average of: \n "
<< temp;
}
else if( temp>=60 && temp <=69.9)
{
cout << "The student has achieved a 2:1 degree with an average of: \n "
<< temp;
}
else if( temp>=70)
{
cout << "The student has achieved a 1st class degree with an average of: \n "
<< temp;
}
else { cout << "The student has failed the degree " << endl;}
}
and main cpp file:
#include <iostream>
#include <utility>
#include <map>
#include <iomanip>
#include <vector>
#include "Database_header.h"
#include <fstream>
using namespace std;
using namespace student_record;
void main()
{
// Create map to store students with ID keys //
string full_name;
int id;
int time;
string degree_name;
vector<Record*> prec;
// Vector of base class pointers to store all the different records first. No need to specify length as it is a vector! (Advantage over dynamic array?)
char student_test('y'); // Condition for adding students to the record //
int q(0);
while (student_test=='y' || student_test=='Y')
{
// Counter for while loop
cout<< " \n Please enter the student name " << endl;
getline(cin, full_name);
// Enter student name, check it is a string? //
cout<< "\n Please enter student ID " << endl;
cin >> id;
// Check if not integer or number, if not need error message //
cout << "\n Please enter the number of years on the course " << endl;
cin >> time;
// Check if not integer or number, if not need error message //
cout<< "\n Please enter degree type " << endl;
cin>>degree_name;
if(degree_name=="Physics" || degree_name=="physics") // create object of appropriate derived class ( Physics, Chem, Maths, Bio)
{
prec.push_back(new Physics(full_name, id, time));
}
char class_test('y'); // test condition for class insertion loop
while(class_test=='y') // Add courses+marks into course map
{
cout << " \n Add classes to student record " << endl;
prec[q]->insert_class();
cout << " \n Add another class? Y/N" << endl;
cin>>class_test;
}
cout << "Enter another student? Y/N " << endl;
cin >> student_test;
if(student_test=='N' && student_test=='n')
{
cout << "\n Thank you for using the student database, Goodbye !" << endl;
}
q++; // increment counter, to keep track of of vectors of base class pointers, and also be able to output number of students
}
// Next insert all records into map //
typedef map<int, Record*> studentlist;
studentlist studentmap;
for(int i(0); i<=prec.size(); i++)
{
studentmap.insert(pair<int, Record*> (prec[i]->getid(), prec[i]));
}
}
Thanks so much!
for(int i(0); i<=prec.size(); i++)
{
studentmap.insert(pair<int, Record*> (prec[i]->getid(), prec[i]));
}
Should be i < prec.size() instead of <=