my problem today is with dynamic arrays. Every time I enter more then 2 test scores I get an error after I enter the 3rd max test score which says "* Error in `./a.out': double free or corruption (out): 0x09c2e028 *
Aborted (core dumped)" Am I doing something wrong with the arrays? Or is there something I'm painfully missing?
The program is supposed to take an unlimited number of test scores and their respective max possible points (i.e. test score = 76 Max test score possible = 100) and turn those numbers into a GPA. I'be only included the class I'm using to create the GPA because the rest of the code isn't finished yet as I can't get past this part.
I have to use the dynamic arrays because it is for a school assignment.
Thanks for reading I hope someone can help me!
#include <iostream>
#include <string>
#include <cmath>
#include <math.h>
#include <iomanip>
#include <cassert>
using namespace std;
void programGreeting();
class testScores{
public:
float testAverage(){
int i = 0;
float gpa2 = 0;
int loopCountVar = 0;
int size = 1;
int size2 = 1;
float *testScore = new float[size];
float *maxScore = new float[size];
while(testScore[i] != -1){
i++;
loopCountVar++;
cout << "Enter test score #" << loopCountVar << endl;
cin >> testScore[i];
if(testScore[i] == -1){
size = i;
}
assert(testScore[i] > -2);
cout << "Enter max test score #" << loopCountVar << endl;
cin >> maxScore[i];
if(maxScore[i] == -1){
size2 = i;
}
assert(maxScore[i] > -2);
}
float *gpa = new float[size];
for(i = 1; i < size; i++){
gpa[i] = testScore[i] / maxScore[i];
cout << gpa[i] << " " << endl;
}
for(i = 1; i < size; i++){
gpa2 += gpa[i];
}
for (i = 1; i < size; i++){
cout << endl << testScore[i] << " " << endl;
}
for (i = 1; i < size2; i++){
cout << endl << maxScore[i] << " ";
}
cout << endl << gpa2 << endl;
cin >> size;
delete testScore;
delete [] maxScore;
delete gpa;
return 0;
}
};
All your allocations are new ...[], so all deletes must be delete [] ....
delete [] testScore;
delete [] maxScore;
delete [] gpa;
Also your code only allocates one element for testscore and maxscore but you keep writing elements into the Array until the user enters -1. That means you will very likely write over the end of the buffer.
You should get rid of your raw pointers and use STL containers like std::vector. With these you can easily add elements to the end without having to reallocate yourself.
Related
Getting 0xC0000005: Access violation writing location 0xCDCDCDCD with the code below.
I know I must have not allocated the pointer properly, but I'm not sure where.
I'm trying to have **scoreSet refer to sets of *scores and *scores is to be entered in manually. The names pointer to array is working fine and seems to be allocated properly. The problem is when I try to mimic the same for scoreSet, with the difference being scoreSet is a pointer to an array of pointers scores. I feel like the way I'm trying to dynamically allocate the arrays that this pointer is pointing to is completely wrong.
Basically trying to get something like this to be possible after user input:
scoreSet0 = {22,33,44}
scoreSet1 = {35, 45, 65, 75}
scoreSet3 = {10}
#include <iostream>
#include <string>
using namespace std;
int inputData(string*& names, double**& scores);
int main() {
string *names = nullptr;
double *scores = nullptr;
double **scoreSet = &scores;
int size = 0;
size = inputData(names, scoreSet);
for (int i = 0; i < size; i++) {
cout << *(names+i) << endl;
}
}
int inputData(string*& names, double**& scoreSet) {
int numStudents = 0;
cout << "How many students do you have in the system? ";
cin >> numStudents;
while (numStudents <= 0) {
cout << "Invalid number of students. Please enter number of students: ";
cin >> numStudents;
}
names = new string[numStudents];
cin.ignore(10000, '\n');
for (int i = 0; i < numStudents; i++) {
int numTests = 0;
cout << "Enter the student's name: ";
getline(cin,names[i]);
cout << "Enter how many tests " << *(names + i) << " took: ";
cin >> numTests;
*(scoreSet + i)= new double[numTests]; //Pretty sure this is wrong.
cin.ignore(10000, '\n');
for (int j = 0; j < numTests; j++) { //This loop is causing the error.
cout << "Enter grade #" << j + 1 << ": ";
cin >> *(scoreSet+i)[j];
}
}
return numStudents;
}
Per PaulMcKenzie suggestion, this is how it would roll. It may be a bit much for you to use templates, but if you can... Otherwise create the name and score containers separately. But then you have duplicate code to maintain.
The idea is to keep all your stuff in some kind of order. Note that now the memory management is taken care of in the container.
I dropped handling std::cin and the scores, but it should be much easier for you to code that stuff back without a lot of fluff in the way. At that, develop without std::cin, it is a waste of time. You should write so you can just edit and run.
Also, get out of the habit of using namespace std; It will pay off in the long run.
#define DEV
template<typename T>
struct container {
size_t size;
T* ar;
container(size_t size) :size(size) {
ar = new T[size];
}
~container() { delete[]ar; }
T& operator [](size_t pos) { return ar[pos]; }
};
using names_c = container<std::string>;
using scores_c = container<double>;
size_t inputData(names_c& names, scores_c& scores);
int main() {
container<std::string> names(2);
container<double> scoreSet(2);
auto size = inputData(names, scoreSet);
for (int i = 0; i < size; i++) {
std::cout << names[i] << endl;
}
}
size_t inputData(names_c& names, scores_c& scores) {
#ifdef DEV
size_t numStudents = 2;
names[0] = "tom";
names[1] = "mary";
#else
//do your std::cin stuff
#endif
return names.size;
}
I wasn't going to go there, but. You can extend the concept so that you have containers in containers. Much easier to know what scores go with what student.
struct student_type {
using scores_c = container<double>;
std::string name;
scores_c scores;
};
using student_c = container<student_type>;
I've taken your code, and modified it to work. I've removed your comments, and placed comments in on the lines that I changed.
#include <iostream>
#include <string>
using namespace std;
int inputData( string *&names, double **&scores );
int main() {
string *names = nullptr;
double **scores = nullptr; // Changed to double ** so it's "2D"
// double **scoreSet = &score; // removed, this was unneeded and probably causing problems
int size = 0;
size = inputData( names, scores );
for ( int i = 0; i < size; i++ ) {
cout << *( names + i ) << endl;
}
}
int inputData( string *&names, double **&scoreSet ) {
int numStudents = 0;
cout << "How many students do you have in the system? ";
cin >> numStudents;
while ( numStudents <= 0 ) {
cout << "Invalid number of students. Please enter number of students: ";
cin >> numStudents;
}
names = new string[numStudents];
scoreSet = new double*[numStudents]; // allocate an array of pointers
// cin.ignore( 10000, '\n' ); // Removed from here, placed inside loop
for ( int i = 0; i < numStudents; i++ ) {
cin.ignore( 10000, '\n' ); // placed here so that it always clears before getting the name
int numTests = 0;
cout << "Enter the student's name: ";
getline( cin, names[i] );
cout << "Enter how many tests " << names[i] << " took: "; // simplified
cin >> numTests;
scoreSet[i] = new double[numTests]; // simpliefied left hand side
//cin.ignore( 10000, '\n' ); // not needed
for ( int j = 0; j < numTests; j++ ) {
cout << "Enter grade #" << j + 1 << ": ";
cin >> scoreSet[i][j]; // simplified
}
}
return numStudents;
}
The strange problem appears in my program. It is working, but in debugging it shows the "Exception thrown" in random places at the outputting
cout<<"Average value:"<<u3.apr();
_getch();
Sometimes, it even throws this error after the main function (Behind the {})
It is quite annoying because the program just closes after 3 seconds because of these errors.
(Maybe that's because of class, but I'm trying to learn it ;) )
Have tried already changing lines order, rewriting class name and array name.
#include <iostream>
#include <conio.h>
using namespace std;
class vid
{
private:
int i, j;
double rez, sum=0;
public:
int size;
double *arr = new double[size];
double apr()
{
for (i = 0; i < size; i++)
{
sum += (*(arr + i));
}
return sum / size;
}
};
int main()
{
vid u3;
cout << "Enter array length:";
cin >> u3.size;
for (int i = 0; i < u3.size; i++)
{
cout << "Enter array's " << i << " element:" << endl;
cin >> *(u3.arr+i);
}
cout << "Your array:" << endl;
for (int i = 0; i < u3.size; i++)
{
cout << *(u3.arr + i) << "\t";
}
cout << endl;
cout<<"Average value:"<<u3.apr();
_getch();
}
Thanks for any help ;)
arr is initialised when u3 is constructed.
But you didn't populate u3.size until later.
So, your array has indeterminate length (which is already UB), and your accesses later may be invalid.
You're going to have to manage your class's member a bit more cleverly!
Such classes generally have a "resize" function that performs the allocation per the requested size. Don't forget to safely kill any prior allocation, transplanting data if necessary. You can find online plenty of examples of a vector implementation.
Certainly renaming classes and randomly re-ordering the lines of your program's source code is not going to solve anything.
u3.size is not set until after u3 is constructed. By setting u3.size you can avoid this compiler-time error.
It seems that as an alternative solution, you might want to consider how to get rid of the new call and the need to write a destructor that will delete arr.
By creating a constructor that takes a size parameter AND by switching arr to a std::vector, you can allow the class to hold the vector and handle memory allocation and deallocation:
#include <iostream>
#include <vector>
using namespace std;
class vid
{
private:
int i, j;
double rez, sum=0;
public:
int size;
std::vector<double> arr;
// constructor requires size to be passed in;
// constructor initializes the arr array with the passed in size to zeroes.
vid(int argSize) : size(argSize), arr(argSize, 0.0){ }
double apr()
{
for (i = 0; i < size; i++)
{
sum += arr[i];
}
return sum / size;
}
};
int main()
{
uint size;
cout << "Enter array length:";
cin >> size;
vid u3(size);
for (int i = 0; i < u3.size; i++)
{
cout << "Enter array's #" << i << " element:" << endl;
cin >> u3.arr[i];
}
cout << "Your array:" << endl;
for (int i = 0; i < u3.size; i++)
{
cout << u3.arr[i] << "\t";
}
cout << endl;
cout<<"Average value:"<<u3.apr();
char ch;
cin >> ch;
}
I have this code of a dynamic array that I turned in as a lab. My instructor responded saying "wouldn't even compile, no resize of the array". I am having trouble dealing with the comment of "no resize of the array", meaning I have to add the ability to resize the array. Please help quick! (It does compile). Appreciate it.
I am supposed to make a program that asks the user to initially size the array. Create an array based on that size asking for a number, and insert the number. Then repeat getting and inserting a number, resizing the array as needed or until they enter -1 for the number.
Print the list.
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
int count;
cout << "How many values do you want to store in your array?" << endl;
cin >> count;
int* DynamicArray;
DynamicArray = new int[count];
for (int i = 0; i < count; i++) {
cout << "Please input Values: " << endl;
cin >> DynamicArray[i];
{
if (DynamicArray[i] == -1) {
delete[] DynamicArray;
cout << "The program has ended" << endl;
exit(0);
}
else {
cout << endl;
}
}
}
for (int k = 0; k < count; k++) {
cout << DynamicArray[k] << endl;
}
delete[] DynamicArray;
return 0;
}
When the array is full, we need to resize it. Here is my solution
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
int main()
{
int count;
cout << "How many values do you want to store in your array?" << endl;
cin >> count;
if (count <= 0) {
cout << "The value should be greater than zero" << endl;
exit(0);
}
int* DynamicArray;
DynamicArray = new int[count];
int i = 0, value = 0;
while (1) {
cout << "Please input Values: " << endl;
cin >> value;
if (value == -1) {
cout << "The program has ended" << endl;
break;
}
else if (i < count)
{
DynamicArray[i++] = value;
}
else
{
// resize the array with double the old one
count = count * 2;
int *newArray = new int[count];
memcpy(newArray, DynamicArray, count * sizeof(int));
delete[]DynamicArray;
newArray[i++] = value;
DynamicArray = newArray;
}
}
for (int k = 0; k < i; k++) {
cout << DynamicArray[k] << endl;
}
delete[] DynamicArray;
return 0;
}
I've got a small task I need to complete and I'm rather confused. This task has 3 parts to it which are:
Write a program that dynamically allocates a float array of a size specified by a user (currently working on - if anyone could check my code for this it would be appreciated.
It should then allow the user to input that number of floats, which should be stored in the array. (I have no clue what this means so if I'd appreciate someone explaining it if they could)
Program should print what was saved into the array, the sum, and the average value in the array, and exit.
As you could tell I'm new to C++ and coding in general so please spell it out for me wherever possible. It is mandatory that I am using pointers so I'm afraid I can't change that.
#include <iostream>
using namespace std;
int main()
{
int length;
cout << “Please enter the length of the array: “;
cin >> length;
float * dArray = new float [length];
for (int i = 0; i < length; i++)
{
cin >> dArray[i] = i;
for (int i = 0; i < length; i++)
{
cout << dArray[i] << “ “;
}
cout << ‘/n’;
int sum = 0;
for (int i=0; i < length; i++)
{
sum +=dArray[i];
avg =sum/length;
cout << “Sum is “ << sum << “/nAverage is “ << average;
delete [] dArray;
}
return 0;
}
Please explain the 2nd part.
Thanks in advance.
Regarding
It should then allow the user to input that number of floats, which should be stored in the array. (I have no clue what this means so if I'd appreciate someone explaining it if they could)
It means that you have to let the user input the values to that array. What you are doing is giving them values yourself.
What you need to do is change
for (int i = 0; i < length; i++)
{
dArray[i] = i;
}
to
for (int i = 0; i < length; i++)
{
cin>>dArray[i];
}
Also Note that length should be an int and not a float.
After completion, this would probably be the code you need ( although I would advice you to do the part of finding the sum and average by yourself and use this code I have posted as reference to check for any mistake, as finding the sum and average for this is really easy )
#include <iostream> // include library
using namespace std;
int main() // main function
{
int length; // changed length to int
float sum = 0 , avg; // variables to store sum and average
cout << "Please enter the length of the array: "; // ask user for array
cin >> length;
float *dArray = new float[length];
cout << "\nEnter " << length << " values to be added to the array\n";
for (int i = 0; i < length; i++)
{
cin >> dArray[i]; //accepting values
sum += dArray[i]; // finding sum
}
avg = sum / length; //the average
cout << "\nThe array now contains\n"; // Displaying the array
for ( int i = 0; i < length; i++) // with the loop
{
cout << dArray[i] << " ";
}
cout << "\nThe sum of all values in the array is " << sum; // the sum
cout << "\n\nThe average value is " << avg; // the average
delete[] dArray;
return 0;
}
EDIT
After getting your comment, I decided to post this new code. ( I am assuming what you meant is that the program should repeat as long as the user wants )
I have done it by using a do while loop.
#include <iostream> // include library
using namespace std;
int main() // main function
{
int length; // changed length to int
char a; // a variable to store the user choice
do
{
float sum = 0 , avg; // variables to store sum and average
cout << "\nPlease enter the length of the array: "; // ask user for array
cin >> length;
float *dArray = new float[length];
cout << "\nEnter " << length << " values to be added to the array\n";
for ( int i = 0; i < length; i++ )
{
cin >> dArray[i]; //accepting values
sum += dArray[i]; // finding sum
}
avg = sum / length; //the average
cout << "\nThe array now contains\n"; // Displaying the array
for ( int i = 0; i < length; i++ ) // with the loop
{
cout << dArray[i] << " ";
}
cout << "\nThe sum of all values in the array is " << sum; // the sum
cout << "\n\nThe average value is " << avg; // the average
cout << "\n\nDo you want to try again ( y/n ) ?\n";
cin >> a;
delete[] dArray;
}while( a =='Y' || a == 'y' ); // The do while loop repeats as long as the character entered is Y or y
return 0;
}
Well, hope this is what you were looking for, if not, please do notify me with a comment... :)
Just so you know, the new code you have posted doesn't even compile. Here are some of the problems.
cin >> dArray[i] = i;
You don't need to use = i here. Just cin >> dArray[i] ; is enough.
The next problem is
cout << ‘/n’;
First of all, its \n and not /n. You also need to enclose it in double quotes and not single quotes. That is cout << "\n";
Next one, you have not defined the variable avg . Also note that you have also used an undefined variable average, which I assume you meant avg.
Now here's one of the main problems , You have not closed the curly brackets you opened. You open the brackets for for loops, but forget to close it. I'm leaving that part to you as you need to learn that part yourself by trying.
Now Here's one problem I don't understand, you have used “ “, which is somehow not the same as " ". I don't know if it's something wrong with my computer, or if it's a totally different symbol. My compiler couldn't recognize it. If its not causing any trouble on your end, then don't mind it.
Well, this sums up the problems I noticed in your code ( the problems that I noticed ).
Your issues are too simple for us to just give you the answers, but I've commented your code with suggestions on how to solve your problem:
#include <iostream>
using namespace std;
int main()
{
float length; //it doesn't make sense for something to be of a float length
//should be size_t instead
cout << "Please enter the length of the array: ";
cin >> length;
float *dArray = new float[length];
for (int i = 0; i < length; i++)
{
dArray[i] = i; //this line is incorrect
//how should we read the data into this array?
//we've used cin before
}
for (int i = 0; i < length; i++)
{
cout << dArray[i] << " ";
}
cout << '\n';
//now we've output the array, just need to output the sum and average value
int sum = 0;
for (int i=0; i < length; i++)
{
sum += //what should go here?
}
int average = //how should we calculate the average?
cout << "Sum is " << sum << "\nAverage is " << average;
delete[] dArray;
return 0;
}
Having trouble getting my code to run properly, first time I have ever used C++ and just trying to learn it for my knowledge, I am trying to get a 2d array with all zeros except in the final column. Inputs are stock = 100, strike = 100, time to maturity = 1, interest rate = 0.06, time steps = 3, upfactor = 1.1, downfactor = 0.9091. The end Array should look like {[0,0,0,133.10], [0,0,0,110], [0,0,0,90.91], [0,0,0,75.13]}, bot for some reason I keep getting values in the first column as well and I am stumped. Any advice?
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <math.h>
#include <cmath>
using namespace std;
int main(int nNumberofArgs, char*pszArgs[])
{
double st;
cout << " Enter Value of stock: ";
cin >> st;
double K;
cout << " Enter Value of strike price: ";
cin >> K;
double t;
cout << " Enter time of maturity: ";
cin >> t;
double r;
cout << " Enter Value of the interest rate: ";
cin >> r;
int N;
cout << " Enter Value of time steps: ";
cin >> N;
double u;
cout << " Enter value of up factor: ";
cin >> u;
double d;
cout << " Enter Value of down factor: ";
cin >> d;
double dt;
dt = t/N;
double p;
p = (exp(r*dt)-d)/(u-d);
// Initialise asset price at maturity time step N
double price[N][N];
for( int i = 0; i < N+1; i++)
{
for (int j = 0; j<N+1; j++)
{
price[i][j] = 0;
}
}
price[N][N] = st*pow(d,N);
cout << "price[N][N] is equal to: " << price[N][N] << endl;
double newN;
newN = N-1;
//cout << price[2][0] << endl;
for(int ii = newN; ii >=0; ii--)
{
price[ii][N] = (price[ii+1][N]) * (u/d);
}
//cout << price[2][0] << endl;
for( int i = 0; i <= N; i++)
{
for (int j = 0; j <=N; j++)
{
cout << price[i][j] << " ";
}
cout << endl;
}
system("PAUSE");
return 0;
}
The problem area is
for(int ii = newN; ii >=0; ii--)
{
price[ii][N] = (price[ii+1][N]) * (u/d);
}
and not sure exactly how to fix it. Any thoughts??
In C/C++ indexes are from 0
double price[N][N];
or
double price[10][10];
means that you have an array from 0..9 and 0..9
so
price[N][N] = st*pow(d,N);
is writing to a location outside the arrays as the maximum index is price[N-1][N-1]
and for that reason, loops in C/C++
for( int i = 0; i <= N; i++)
should be written as
for( int i = 0; i < N; i++)
since N is not included as a valid index value for the array.
Couple of issues with your program.
You have created a double dimensional array on stack with variable sized length (N).
If your array size is dynamic don't create it on stack, use new to allocate it on heap.
Also, as I see it you are accessing out-of-array entries. (Index greater than max array index)