C++: Bug when trying to fill dynamic vector with double - c++

I'm having trouble with a program I'm doing in class and even the teacher can't find the problem. We're doing a program that ask the user to enter double then when he stop, it scan the array and separate the positive and negative to put them in different arrays.
We notice that when we use float the program work for more numbers but still bug if we enter too much and if we use double it bug after only a few numbers. By bug I mean, the program do well but when it display the result there is some weird numbers in the array. Here is the code using double:
#include <iostream>
using namespace std;
void filling(double *, int &);
void sortPositiveNegative(double *, double *, double *, int, int &, int &);
void display(const double *, int);
int main () {
double * vecteur = new double;
double * positive = new double;
double * negative = new double;
int counter = 0, counterPos = 0, counterNeg = 0;
cout << "Filling of the real number vector " << endl;
filling(vecteur, counter);
cout << endl << "Display of the real number vector " << endl;
display(vecteur, counter);
cout << endl << "Sort of the positive and negative in the real number vector: " << endl;
sortPositiveNegative(vecteur, positive, negative, counter, counterPos, counterNeg);
cout << endl << "Display of the positive real number : " << endl;
display(positive, counterPos);
cout << endl << "Display of the negative real number : " << endl;
display(negative, counterNeg);
system("PAUSE");
return 0;
}
void filling (double *vecteur, int &counter)
{
bool validation;
char choice = 'Y';
do
{
do
{
validation = true;
cout << "Please enter the value of case " << counter+1 << ": ";
cin >> vecteur[counter];
if(cin.fail())
{
cerr << "The number entered is not valid." << endl;
cin.clear();
validation = false;
}
while(cin.get() != '\n'){}
}while(!validation);
counter++;
do
{
validation = true;
cout <<"Do you wish to continue? (Y/N): ";
cin >> choice;
if(toupper(choice) != 'Y' && toupper(choice) != 'N')
{
cerr << "We don't understand your choice, please try again." << endl;
cin.clear();
validation = false;
}
while(cin.get() != '\n'){}
}while(!validation);
}
while(toupper(choice)=='Y');
}
void sortPositiveNegative(double *vecteur, double *positive, double *negative, int counter, int &counterPos, int &counterNeg)
{
int i = 0;
for(i; i<counter;i++)
{
if(vecteur[i] >= 0)
positive[counterPos++] = vecteur[i];
else
negative[counterNeg++] = vecteur[i];
}
}
void display (const double *vecteur, int counter)
{
for(int i = 0; i<counter;i++)
cout << vecteur[i]<<endl;
cout << endl;
}
My teacher think it might be a memory problem but we have no idea why it's doing that.
Thanks in advance.

There is definitely a memory problem, and I don't see how using float would fix it. For example, the below line of code allocated only one double and not an array of doubles:
double * vecteur = new double;
Then, you use this vecteur as if it was an array of N elements. That triggers undefined behavior.
To fix it, you would have to allocate an array of as much values as you need. For example, let's say you need 10, then you allocate 10 like this:
double * vecteur = new double[10];
However, given that you don't know the number of elements in advance, you would need to extend the array every time you want to add an element. If you were writing this in C, I would have recommended you to use realloc(). But given that you use C++, just stick with std::vector<double>, it will manage memory automatically. For example:
#include <vector>
int main()
{
std::vector<double> vecteur; // Use vector to store array of doubles.
// Add as many elements as you want.
// Vector will resize itself if/when needed.
vecteur.push_back(.1);
vecteur.push_back(.2);
vecteur.push_back(.3);
vecteur.push_back(.4);
vecteur.push_back(.5);
}
Hope it helps. Good Luck!

double * vecteur = new double;
You allocate space for one doubile
filling(vecteur, counter);
Pass it to filling
cin >> vecteur[counter];
And fill untill user presses Y going outside of array with one element you have allocated memory for.
double vs float doesn't matter much. float is simply smaller and thus will be corrupting memory slower. But it is still corrupting memory starting from vecteur[1]
I'd suggest you to use std::vector<dobule> instead of plain pointers, and filling it with push_back

double * vecteur = new double;
double * positive = new double;
double * negative = new double;
Here you allocate exactly ONE double each time. The first item you store in your "array" is fine, but anything else after that is undefined behaviour.
The fix is to actually allocate as many items as you need:
double * vecteur = new double[MAXIMUM8NUMBER_OF_ITEMS];
double * positive = new double[MAXIMUM8NUMBER_OF_ITEMS];
double * negative = new double[MAXIMUM8NUMBER_OF_ITEMS];
Or better yet, use a standard container like std::vector.

Related

if, else if, else function isn't accurately displaying results

#include <iostream>
using namespace std;
// prototype functions
void DisplayResult(float MaxOrMin);
float FindMinimum(float Array[5]);
float FindMaximum(float Array[5]);
//Global Variables
float Array[5];
float MaxOrMin = 3;
float FindMin;
float FindMax;
//Main Function
int main()
{
cout << "Please enter 5 numbers: " << endl;
for (int i=0; i<5; i++)
{
cin >> Array[i]; // input for array
}
cout << "Please enter '0' for minimum or '9' for maximum:" << endl;
cin >> MaxOrMin; // input 0 or 9 for min or max
//Calling Functions
FindMinimum(Array);
FindMaximum(Array);
DisplayResult(MaxOrMin);
return 0;
}
//Function to find Minimum
float FindMinimum(float Array[5])
{
float FindMin = Array[0];
for (int y=1;y<5;y++)
{
if(Array[y] < FindMin)
FindMin = Array[y];
}
return FindMin;
}
//Function to find Maximum
float FindMaximum(float Array[5])
{
float FindMax = Array[0];
for (int x=1;x<5;x++)
{
if(Array[x] > FindMax)
FindMax = Array[x];
}
return FindMax;
}
This last part is my if, else if, else funtion:
//Function to display minimum or maximum result
void DisplayResult(float MaxOrMin)
{
if (MaxOrMin == 0)
cout << "Minimum is: " << FindMin << endl;
else if (MaxOrMin == 9)
cout << "Maximum is: " << FindMax << endl;
else
cout << "Invalid Input" << endl;
}
My project is to create a program using functions to take user input on a 5 float array. Then find the max and min and display whichever the user asks for.
Here is where my problem comes in. For both max(input 9) and min(input 0) I am getting "0". However any other input correctly returns my "Invalid Input" message.
I'm not getting any errors or warnings or errors at all on eclipse. My professor has told me that my problem was likely with my void function for displaying results. I am hoping someone could point me in the right direction here.
Apologies for my formatting and/or if this question is too basic for this site.
You misunderstand how local and global variables work. Your Find* functions shadow the globals with locals and thus they don't appear to do anything.
The problem is that your FindMinimum() (and the same with FindMaximum()) function compute the minimum (maximum) in a local variable and return it but you, in main() don't receive they in correct variables
So the computed value is lost.
I mean... instead of
FindMinimum(Array);
FindMaximum(Array);
you should write
FindMin = FindMinimum(Array);
FindMax = FindMaximum(Array);

struct + functions code breaks

There is a problem with the code and i could not find it.
i was asked to write a money struct and use functions to manipulate it.
but the code did not work for any function. i tried couting
the array of structers and it came out nicely, for any missing info
please leave a comment and i'll reply shortly.
Money.txt
2
12 20
13 40
#include <iostream>
#include <fstream>
using namespace std;
struct Money { //declaring structure
int dollars;
int cents;
};
Money addMoney(Money *p[], int n) { //adds money data
Money cash{ 0,0 };
int i;
for (int j = 0; j < n; j++) {
cash.dollars = cash.dollars + p[j]->dollars;
cash.cents = cash.cents + p[j]->cents;
}
if (cash.cents >= 100) //100cents = 1 dollar
{
i = (cash.cents) / 100;
cash.dollars = cash.dollars + i;
i = (cash.cents) % 100;
cash.cents = i;
}
return cash;
}
void printMoney(Money *p[], int n) { //printing money data
for (int i = 0; i < n; i++) {
cout << "Dollars: " << p[i]->dollars << endl;
cout << "Cents: " << p[i]->cents << endl;
}
}
Money maxMoney(Money *p[], int n) {
Money cash;
cash.dollars = p[0]->dollars;
cash.cents = p[0]->cents;
for (int i = 0; i < n; i++)
{
if ((p[i]->dollars)>=(cash.dollars))
if ((p[i]->cents)>(cash.cents))
{
cash.dollars = p[i]->dollars;
cash.cents = p[i]->cents;
}
}
return cash;
}
void main() {
Money cash;
ifstream mycin("money.txt");
if (mycin.fail())
cout << "Enable to open file";
int x;
mycin >> x;
Money *arr = new Money[x];
for (int i = 0; i < x; i++)
{
mycin >> arr[i].dollars;
mycin >> arr[i].cents;
}
cout << "The values in money.txt are: ";
printMoney(&arr, x);
cash = addMoney(&arr, x);
cout << "These values added are :";
cout << cash.dollars << " Dollars and " << cash.cents << " cents" << endl;
cash = maxMoney(&arr, x);
cout << "Maximum value is :";
cout << cash.dollars << " Dollars and " << cash.cents << " cents" << endl;
}
These functions appear to accept an array of pointers to Money, but you're trying to use them with an array of Money.
I suggest you play with arrays of pointers to simpler types (like int) until you're comfortable with the concept, before you attempt it with Money.
This sounds a lot like homework so I'm not posting a full solution, but I will explain what appears to be the misunderstanding and give you some pointers.
First you declare your data structure as an array of Money structures, e.g. a continuous series of blocks of memory containing the Money struct, the first of which is pointed to by "arr" in your main program.
But then, in the rest of the program (functions) you seem to expect the data structure being used to be an array of Money pointers. See the difference? They're not the same and this will not work as is. You have to be consistent.
Either you're dealing with an array of structs, in which case you pass effectively a single, simple Money* to your functions everywhere (and you dereference with . not ->)
Or you're dealing with an array of pointers, in which case you pass effectively a pointer to a (Money pointer) and you dereference with -> as you've done. But then you also have to allocate each Money struct individually when you're reading them in in the main program. That is to say, allocating memory for the array of pointers does not automatically allocate memory for each Money pointer reference in the array of pointers and so you need to do this for each entry you're reading in.
So, as you should hopefully now realise, there's multiple ways to fix your program.
As per your later comment, given that the function signatures need to stay as-is, I would suggest you work with an array of Money pointers.
Money** arr = new Money*[x]
Then you need to add a line to your loop during reading, to actually make each Money * point to a Money struct:
for (int i = 0; i < x; i++)
{
arr[i] = new Money
...
Finally then, because "arr" is now a pointer to a pointer to Money, you can directly pass it to your functions, so calling them are just for example:
printMoney(arr, x);

segmentation fault with dynamic allocation and arrays/pointers

I'm working on an assignment that is introducing the principals of dynamic allocation of memory and pointers. I had made a simple program in the past that accepted 5 names and 5 scores and then used a selection sort to put them in descending order. My assignment now is to come back to that same program and ask the user how many scores they would like to input, then use pointers to dynamically allocate the necessary amount of memory. This is my first time working with pointers and these concepts so im still trying to figure it all out.
I got the code to compile but I get a segmentation fault error as soon as i enter any integer number for how many scores i would like to input (which is the first thing the program asks)
Im sure there are a few errors along the way with how i called and declared functions so if theres anything i just desperately change please let me know, but for now I dont understand why my program is crashing where it is crashing.
Here is my code
#include <iostream>
using namespace std;
void initializeData(string *names[], int *scores[], int num);
void displayData(string *names[], int *scores[], int num);
void sortData(string *names[], int *scores[], int num);
int main()
{
int num;
int **intPoint;
string **strPoint;
cout << "How many scores would you like to enter?: ";
cin >> num;
cout << " core dumped? ";
*intPoint = new int[num];
*strPoint = new string[num];
initializeData(strPoint,intPoint,num);
sortData(strPoint,intPoint,num);
displayData(strPoint,intPoint,num);
return 0;
}
void initializeData(string *names[], int *scores[], int num)
{
for(int i=0;i<num;i++)
{
cout << "Please input the name for score: " << i+1 << ": " << endl;
cin >> *(names[i]);
cout << "Please input the score for player: " << i+1 << ": " << endl;
cin >> *(scores[i]);
}
}
void sortData(string *names[], int *scores[], int num)
{
int minIndex,minValue,x;
string stringTemp;
for(int i = 0;i<(num-1);i++)
{
minIndex = i;
minValue = *(scores[i]);
for(x= i+1;x<num;x++)
{
if(*(scores[x]) > minValue)
{
minValue = *(scores[x]);
minIndex = x;
}
}
*(scores[minIndex])=*(scores[i]);
*(scores[i]) = minValue;
stringTemp = *(names[minIndex]);
*(names[minIndex]) = *(names[i]);
*(names[i]) = stringTemp;
}
}
void displayData(string *names[], int *scores[], int num)
{
cout << "Top scorers: " << endl;
for(int i=0;i<num;i++)
{
cout << names[i] <<": ";
cout << scores[i] << endl;
}
}
and my current output:
How many scores would you like to enter?: 10
Segmentation fault (core dumped)
which happens regardless of what int i put there. I put a cout statement after the
cin << num; to see if the program got that far but it never does.
Any help is greatly appreciated. Sorry if this is the most basic error ever.
int **intPoint;
At this point in your code, intPoint doesn't point to anything since you haven't assigned it a value.
*intPoint = new int[num];
Then you dereference it, but it doesn't point to anything.
Try:
int *intPoint;
intPoint = new int[num];
Now you are setting intPoint's value so that it points to the integers you allocated.
The reason you get a segmentation fault is because you dereference an uninitialized pointer.
int **intPoint; // intPoint is declared a pointer to a 'pointer to an int';
// but currently it points to nothing
*intPoint = new int[num]; // *intPoint "dereferences" intPoint, i.e., assigns w/e it
// pointed to (which is nothing) to a pointer.
Like the others have suggested, you didn't need a double pointer here.
int *intPoint; // intPoint is a pointer to an int
intPoint = new int[num]; // notice how we didn't dereference intPoint.
// all we did was assign to our newly minted memory.
Use std::vector in the place of array of int or string.
say,
std::vector<int> scores;
std::vector<string> names;
This way you can avoid all the hassles. This is simple and elegant.

Array sum is giving the wrong answer when the program is ran

The program runs smoothly and I have no errors or warnings when its compiled its just when it gets the end result I just get a load of random letters and numbers no matter what I put in.
Here is the code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int hold;
int n;
int * result = new int;
int * price = new int;
std::string items[6];
for (n=0; n<6; n++)
{
cout << "Item#" << n+1 << ": ";
cin >> items[n];
}
cout << "\nYou Entered: ";
for (int n=0; n<6; n++)
cout << items[n] << ", ";
for (n=0; n<6; n++)
{
if (items[n] == "ab"){
price[n] = 2650;
}
else if (items[n] == "ae"){
price[n] = 1925;
}
else if (items[n] == "ie"){
price[n] = 3850;
}
else if (items[n] == "bt"){
price[n] = 3000;
}
else if (items[n] == "pd"){
price[n] = 2850;
}
else if (items[n] == "ga"){
price[n] = 2600;
}
}
for (n=0; n<6; n++)
{
result += price[n];
}
cout << "\nTotal gold for this build: " << result;
cin >> hold;
return 0;
}
int * price = new int;
and
int * result = new int;
allocate a single int respectively. You probably meant new int[6].
But then again, you should be using std::vector instead.
I'm disappointed really that you took no advice from - https://stackoverflow.com/a/12868164/673730 - if you had, you wouldn't have this problem now. This is not a good way to learn.
With this declaration: int * price = new int; you only allocate space for a single int, but you go on to use price as an array of int.
To declare an array, use: int *price = new int[5];
As for result, you declare that as a pointer to int also, but you later use it as an int: result += price[n];. No need to result to be a pointer. Also note that you need to initialize your variables explicitly: set result to zero before you begin using it.
just give some comments:
new operater should be used with delete.
"int *result" you declared is a point to int, so you should dereference this point to get the result you want.
exceptions should be taken into consideration, what if the input letter is not in your given list?
Well, result is an int *. This kind of variable usually stores the address of another integer variable, which you get with new int in this specific case. However, with
result += price[n];
you'll modify that address, which would lead to segmentation faults if you were to actually write/read from *result. This is also the reason why you output is strange:
cout << "\nTotal gold for this build: " << result;
This prints the adress stored in result, not the value. Make result an integer and it should work.
Please note that price should be changed too, see Luchian's answer.
Exercise
Change your code so that there is no use of new.
Your program could still fail. What is the initial value of result?
What happens if the user provides a code which is not in your list?
Change the line:
cout << "\nTotal gold for this build: " << result;
to
cout << "\nTotal gold for this build: " << *result;
Result is a pointer, so you need to dereference it, using the * operator;
Edit: Change the declaration of the price array to
int *price = new int[6];
The previous declaration declared a variable, not an array

Taking user input with pointers

I'm trying to get better at using pointers, and not using array notation. So I have a function to read user input and return a pointer to that array. I can do it like this and it seems to work ok:
float *GetValues(float *p, size_t n)
{
float input;
int i = 0;
if ((newPtr = (float *)malloc(n * sizeof(float))) == NULL) {
cout << "Not enough memory\n";
exit(EXIT_FAILURE);
}
cout << "Enter " << n << " float values separated by whitespace: \n";
while (scanf("%f", &input) == 1) {
p[i] = input;
i++;
cout << *p;
}
return p;
}
But then if I do this:
float *GetValues(float *p, size_t n)
{
float *newPtr;
float input;
if ((newPtr = (float *)malloc(n * sizeof(float))) == NULL) {
cout << "Not enough memory\n";
exit(EXIT_FAILURE);
}
cout << "Enter " << n << " float values separated by whitespace: \n";
while (scanf("%f", &input) == 1) {
*newPtr++ = input;
}
return newPtr;
}
I get just 0s entered into p. Why is that?
Also, do I have to allocate memory here for an array of size n? I first tried it with the method above using pointers and not allocating memory but just set p = to input and I was getting garbage values. Thanks!
Edited: Sorry, I allocated a new ptr and was returning the wrong one like you said. I was just trying to input the numbers into my pointer and display it back on the screen to myself and wasn't paying attention to the return type and I was getting an output of 0 when I would cout << *newPtr.
Seeing as this is C++, have you considered:
void GetValues(std::vector<float> &values)
{
float input;
while (scanf("%f", &input) == 1) {
values.push_back(input);
}
}
And there's something called iostream classes that you can use instead of scanf. You should check it out!
A few tips:
The first GetValues allocates newPtr (which is not declared within the function, a global variable?) but then does nothing with it. There are two possible ways that your function could work with regards to memory storage:
The function gets a pointer to valid memory for an array of size large enough. In that case the signature of the function ought to be
float *GetValues(float *array, size_t arraySize)
to more clearly state the nature of the arguments. You need not to allocate anything inside the function.
The function should allocate the needed memory itself and let the caller free the memory some time later. In that case you MUST have some kind of hint in the name of the function that it allocates memory. Otherwise you are in for a disaster in terms of maintaining this code because it will be extremely easy to make mistakes in freeing memory. You will not need to pass an array pointer to the function, but if you do it needs to be a double pointer for it to be of any meaning (C and C++ passes arguments by value so it is not possible to change a pointer which is passed as an argument)
float *GetValuesAndAllocateMemmory(size_t n)
float *GetValuesAndAllocateMemmory(float **array_pp, size_t n)
The loop in the second GetValues should be
float *start_p = p;
...
while (scanf("%f", &input) == 1) {
*p++ = input;
cout << *start_p;
}
return start_p;
in order to be identical to the first GetValues.
Here there is upper limit of number of float values is n but your code does not check this
cout << "Enter " << n << " float values separated by whitespace: \n";
while (scanf("%f", &input) == 1) {
and will crash if more than n floats are entered. Never trust user input data, even when it comes from yourself. Always verify. Search for the term "input validation" for more information about this.
cout << "Enter " << n << " float values separated by whitespace: \n";
entered_values = 0;
while (entered_values < n && scanf("%f", &input) == 1) {
entered_values++;
Um, p = newPtr;?
You don't even store any values in p. And you are returning the pointer that you pass as argument, which is not necessary. A better version would be:
long GetValues(float *p, size_t max)
{
float input;
long i;
cout << "Enter at the most " << max << " float values separated by whitespace: \n";
for(i = 0; i < max && scanf("%f", &input) == 1; ++i)
{
p[i] = input;
}
// Return the number of parsed numbers
return i;
}