I am trying to write code in C++ that reads from a file, a sequence of points, stores it in a dynamic array and then prints back.
This is the specification I've been given:
"We want to take advantage of the fact that we can use dynamic memory, thus instead of allocating at beginning an amount of memory large enough according to our estimations, we implement the following algorithm:
Initially, very little memory is allocated.
At each iteration of the loop (reading from the file and storing into the
dynamic array) we keep track of:
The array maximum size (the allocated memory).
The number of elements in the array.
When, because of a new insertion, the number of elements would become
greater than the array maximum size, memory reallocation needs to take
place as follows:
Allocate another dynamic array with a greater maximum size.
Copy all the elements from the previous array to the new one.
Deallocate the memory area allocated for the previous array.
Get the pointer to the previous array to point to the new one.
Add the new item at the end of the array. This is where my problem is.
From my code below, I think everything else is fine but the last requirement, which is to add the new item at the end of the array.
The code works fine when the array Max_Size exceeds file's number of
elements, but when I try extending the num_elements, the result is
that the extra digits in the file are just saved as zeros
.
Also to add, the assignment doesn't allow use of vectors just yet.
Sorry I forgot to mention this, I'm new to stackoverflow and somewhat
to programming.
Any help please
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
struct point {
double x;
double y;
};
int main () {
ifstream inputfile;
inputfile.open("datainput.txt");
if(!inputfile.is_open()){
cout << "could not open file" << endl;
exit(EXIT_FAILURE);
}
//initially very little memory is allocated
int Max_Size = 10;
int num_elements = 0;
point *pp = new point[Max_Size];
//read from file and store in dynamic array
for (int i = 0; !inputfile.eof(); i++) {
inputfile >> pp[i].x >> pp[i].y;
num_elements++; //keep track of number of elements in array
}
//detecting when number of elements exeeds max size due to new insertion:
if (num_elements > Max_Size){
// allocate another dynamic array with a greater maximum size
Max_Size *= 2; // Max_Size = 2*Max_Size to double max size whenever there's memory problem
point *pp2 = new point[Max_Size];
//copy all elements from previous array to new one
for (int j=0; j<(Max_Size/2); j++) {
pp2[j].x = pp[j].x ;
pp2[j].y = pp[j].y;
}
//deallocate memory area allocated for previous array
delete [] pp;
//get pointer to previous array to point to the new one
pp = pp2;
**//add new item at end of the array
for (int k = ((Max_Size/2)-1); k<num_elements; k++) {
inputfile.seekg(k, ios::beg) >> pp2[k].x;
inputfile.seekg(k, ios::beg) >> pp2[k].y;
}**
//print out dynamic array values
for (int l = 0; l<num_elements; l++) {
cout << pp2[l].x << ",";
cout << pp2[l].y << endl;
}
//delete dynamic array
delete [] pp2;
}
else {
//print out dynamic array values
for (int m = 0; m<num_elements; m++) {
cout << pp[m].x << ",";
cout << pp[m].y << endl;
}
//delete dynamic array
delete [] pp;
}
cout <<"Number of elements = " << num_elements <<endl;
//close file
inputfile.close();
return 0;
}
Others have already pointed out std::vector. Here's roughly how code using it could look:
#include <vector>
#include <iostream>
struct point {
double x;
double y;
friend std::istream &operator>>(std::istream &is, point &p) {
return is >> p.x >> p.y;
}
friend std::ostream &operator<<(std::ostream &os, point const &p) {
return os << p.x << "," << p.y;
}
};
int main() {
// open the file of data
std::ifstream in("datainput.txt");
// initialize the vector from the file of data:
std::vector<point> p {
std::istream_iterator<point>(in),
std::istream_iterator<point>() };
// print out the data:
std::copy(p.begin(), p.end(), std::ostream_iterator<point>(std::cout, "\n"));
}
On top of being a lot shorter and simpler than the code you posted, getting this to work is likely to be a lot simpler and (as icing on the cake) it will almost certainly run faster1 (especially if you have a lot of data).
1. In fairness, I feel obliged to point out that the big difference in speed will mostly come from using \n instead of endl to terminate each line. This avoids flushing the file buffer as each line is written, which can easily give an order of magnitude speed improvement. See also: https://stackoverflow.com/a/1926432/179910
The program logic is flawed. You run the loop until EOF but you don't check to see if you have exeeded your array size. I would add an if statement inside of the first loop to check if you have passed the Max_Size. I would also write a function to reallocate the memory so you can simply call that function inside of your first loop.
Also you have problems with your memory allocation. You should do like this:
point temp = pp;
pp = new Point[...];
// Copy the contents of temp into pp
delete temp;
You need to set your pointer to the old array first so you don't lose it. Then after you have copied the contents of you old array into the new array, you can then delete the old array.
Related
I see this code in geek for geeks and it has memory leak on 58 line as guided by valgrind ,
i don't see any way how to fix this to make it a better code, cause if we delete that new then assigned v[i] also delete and no value get inside it !!
i am a beginner to coding!!
here is the code
// C++ Program to create
// vector of pointer
#include<bits/stdc++.h>
using namespace std;
void insert_element(vector<int*>& v, int i)
{
// declaration and input of values of elements
int a;
cin >> a;
// allocating address to i element
v[i] = new int(a);
}
void print_vector(vector<int*>& v)
{
// printing elements of the vector
for (int i = 0; i < v.size(); i++) {
cout << *(v[i]) << " ";
}
cout << endl;
}
void delete_element(vector<int*>& v, int pos)
{
// Out of limit positions
if (pos <= 0 || pos > v.size())
return;
// converting position into index number
pos = pos - 1;
// free the space from pointer
delete v[pos];
// removing element from the vector
v.erase(v.begin() + pos);
}
int main()
{
cout << "Enter size of vector: ";
// size of vector
int n;
cin >> n;
// create a vector
vector<int*> v(n, nullptr);
cout << "Enter elements of vector: ";
for (int i = 0; i < n; i++) {
// inserting n elements inside v vector
insert_element(v, i);
}
cout << "Before: ";
// printing vector
print_vector(v);
cout << "Enter position to remove: ";
int pos;
cin >> pos;
// delete element from pos position
delete_element(v, pos);
cout << "After: ";
// printing vector
print_vector(v);
return 0;
}
i tried delete it but it says expected pointer in that place with delete keyword
error: type ‘class std::vector<int*>’ argument given to ‘delete’, expected pointer
15 | delete v;
The simplest way to avoid leaks is... not to use new\delete expressions anywhere outside of object construction and destruction. That's the part of RAII principle.
What valgrind reports, is that the function called on 58th line (insert_element) had created "leaked" free store memory, but that leak happens on exit from the main()function. The vector of pointers is destroyed, but the objects in free store aren't. In most cases it's a harmless scenario, but let be formal.
Our choices are
A.) Avoid extra allocation at all. It's not necessary here. we can use vector<int>. In this particular case it's a preferable solution. Usually the pointer's size is equal or greater in size than an int. Vector already works with free store.
B.) Use a vector that will delete elements automatically. Seriously, that's the responsibility of a container. But that would require multiple changes in code, because the type itself has changed. We can avoid that y declaring a type-alias.
// Use it everywhere in code.
using MyVector = std::vector<std::unique_ptr<int>>
That's not a great solution. We overengineered the container also we can't actually make a copy of it. The latter is true for original code - the vector isn't really copyable, a second copy would have pointers referring to same memory, but clearing one copy would cause pointers in the other copy to "dangle" - to point at invalid memory where object no longer exists.
You might need a smart pointer with reference counting instead -shared_ptr, even maybe a custom deleter and allocator. It's too much to store a single int.
C.) A "mechanist" solution: fix the problem by applying ducttape code where it is broken:
// printing vector
print_vector(v);
for( auto &item : v)
delete item;
return 0;
}
PS. Be sure it's not a "ducktape code", i.e. a fragile solution where you patch every hole and apply it everywhere. Aside from the copyright issues with Ducktape brand, a badly written code, while badly maintained, quickly becomes an unreadable mess where following fixes may be utterly wrong and the project falls apart. Especially if one who does fixing didn't wrote the original.
So I am trying to use a dynamic array for my program and I do not know if I am doing it right. Should I use const int or just an int only?
int size = 1;
int *num1 = new int [size];
int *num2 = new int [size];
or
const int size = 1;
int *num1 = new int [size];
int *num2 = new int [size];
If the size is a compile-time constant that you want to create an "array" from, then I suggest std::array, as in
std::array<int, 1> num1;
If the size isn't known at compile-time then use std::vector, as in
std::vector<int> num1(size);
And if you really have to use explicit dynamic allocation then opt for smart pointers like std::unique_ptr, like
auto num1 = std::make_unique<int[]>(size);
As for if the variable size should be const, constexpr, not qualified at all, or if you should possible use the literal value directly when allocating, then it really depends on use-case, value availability, and personal preference.
On another note, for a size you should rather use the size_t type instead of int. Most programmers will immediately understand that when you use size_t the variable is used to store a size. Otherwise if you use int it could be any arbitrary integer value. Furthermore, size_t is an unsigned type, so it doesn't allow negative numbers, which is one less cause of problems.
I've seen you ask a few questions about this now, so I want to show you the difference between having to resize a dynamic array and using std::vector, which packages all of the features you'd want in a dynamically-sized block of contiguous memory.
The following code is how to increase a dynamic array to hold user input. We don't know how long the user wants to input numbers for, so we have to keep resizing every time they enter a new number.
int number = 0;
std::size_t array_size = 0; // we need to track the size of the thing
int *array = nullptr; // nothing in here yet
std::cout << "Enter a number, non-number to exit: ";
while (std::cin >> number)
{
// we need to request more memory
++array_size;
int *new_array = new int[array_size];
// we have to copy the old array to the new array
// fun note: as pointed out in the comments below, using memcpy on
// either src or dest == nullptr is undefined behavior. Just goes to
// show how hard it is to get something like this correct.
// Don't do this when we have perfectly good STL containers!
std::memcpy(new_array, array, (array_size - 1) * sizeof(int));
// delete the old array, if it exists (we can safely call delete on a nullptr)
delete[] array;
// assign the new block of memory to array
array = new_array;
// add the retrieved element to array
array[array_size - 1] = number;
std::cout << "Enter a number, non-number to exit: ";
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// output the array
for (std::size_t i = 0; i < array_size; i++)
{
std::cout << array[i] << "\n";
}
// all done, delete the memory that was allocated
delete[] array;
array = nullptr; // not strictly required, but can prevent us from accidentally deleting the same block of memory twice, which would be bad
We can do the same thing using std::vector:
int number;
std::vector<int> vec; // this is a vector that holds ints, it tracks its own size and memmory
std::cout << "Enter a number, non-number to exit: ";
while (std::cin >> number)
{
vec.push_back(number); // all done
std::cout << "Enter a number, non-number to exit: ";
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
for (std::size_t i = 0; i < vec.size(); i++)
{
std::cout << vec[i] << "\n";
}
// or we can used range-based for loops, which are awesome
for (auto& v : vec)
{
std::cout << v << "\n";
}
Note that in the std::vector example, I'm outputting the contents of the std::vector twice, just to show that we have an option for iterating through a vector that is not available for an int *. We don't need to keep track of memory. We don't need to new and delete. When the current program scope exits (if this is a function, for example), the destructor of the std::vector is called and cleans up memory for us.
USE VECTORS!!!
I have to create a program that uses the 'new' operator to create a dynamic array in heap of the program. The program creates and populates its dynamic array one (int) elements at a time for each input data (cin).
Key parts.
1.) Program has to used "cin >>" for data input to accept on integer at a time until EOF is pressed on the keyboard (cntrl-z for windows).
2.) User input has to be tested using !cin.eof() && cin.good() to test whether or not the EOF key was pressed and if the data is valid. (kinda of confused about the cin.good() part).
3.) The program will create a series of longer and longer arrays to contain all previous elements and the current incoming one. Also, the program will delete the previous version of the array after completing the current version.
4.) The program also tests if heap memory has been exhausted after each use of the new operator. (need help with this)
I keep getting error message "HEAP CORRUPTION DETECTOR After normal black (#146)" (visual studio). What's the issue?
Thanks in advance!
Here's the code:
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cassert>
using namespace std;
// main
int main() {
int size = 2;
int * array1 = new int[size];
int arrayInput;
int count = 0;
do {
if (array1 != NULL) {
cout << "Enter an integer (EOF to stop): " << endl;
cin >> arrayInput;
if (size < count) {
int * tempArray;
tempArray = new int[size * 2];
if (tempArray != NULL)
{
for (int i = 0; i < size; i++) {
array1[i] = tempArray[i];
}
delete[] array1;
array1 = tempArray;
size *= 2;
delete [] tempArray;
}
else
cout << "Insufficient Heap resource." << endl; // If we get here the Heap is out of space
}
if (!cin.eof()) {
array1[count++] = arrayInput;
}
}
else
cout << "Insufficient Heap resource." << endl; // If we get here the Heap is out of space
} while (!cin.eof());
for (int i = 0; i < count; i++) {
cout << array1[i] << endl;
}
}
tempArray = new int[size * 2];
if (tempArray != NULL)
{
for (int i = 0; i < size; i++) {
array1[i] = tempArray[i];
}
You allocate a new array twice as big as your old array. Then you copy the contents of the newly allocated array into your existing array. The newly-allocated array contains random garbage, that you just used to override the existing, good data, in your old array.
That's one obvious bug, but it won't explain the crash.
delete[] array1;
array1 = tempArray;
size *= 2;
delete [] tempArray;
After copying, you delete your old array. Then you also delete your new array, that you just allocated. That smells like another bug, but it still won't explain the crash.
if (!cin.eof()) {
array1[count++] = arrayInput;
}
Now, you can answer your own question here: what happens when you continue to write to a pointer that was pointing to memory that you freed, recently?
That are multiple bugs in the shown code. They all must be fixed. I haven't looked further, past this point. There might still be other issues with this code. A rubber duck should be able to help you to find any remaining bugs in your program.
Let's say I have a dynamic array:
int* p;
ifstream inFile("pop.txt");
int x;
while (inFile >> x)
{
// ????
}
How do I resize p so I am able to to fit x in as like an array. I don't want to use a vector or static array as I am trying to learn the language. I need to use pointers because I don't know the initial size. Any attempt is appreciated.
The simplest answer is that you should use higher level components than raw arrays and raw memory for the reading. That way the library will handle this for you. A simple way of reading a set of numbers into an application (without error handling) could be done with this simple code:
std::vector<int> data;
std::copy(std::istream_iterator<int>(inFile), std::istream_iterator<int>(),
std::back_inserter(data));
The code creates a couple of input iterators out of the stream to read int values, and uses a back_inserter iterator that will push_back onto the vector. The vector itself will manage growing the memory buffer as needed.
If you want to do this manually you can, you just need to allocate a larger chunk of memory, copy the first N elements from the old buffer, release the old buffer and continue reading until the larger buffer gets filled, at which point you follow the same procedure: allocate, copy, deallocate old, continue inserting.
You can't resize it. All you can do is allocate a new bigger array, copy everything over from the old array to the new array, then free the old array.
For instance (untested code)
int array_size = 10;
int* array = new int[array_size];
int array_in_use = 0;
int x;
while (in >> x)
{
if (array_in_use == array_size)
{
int* new_array = new int[2*array_size];
for (int i = 0; i < array_size; ++i)
new_array[i] = array[i];
delete[] array;
array = new_array;
array_size *= 2;
}
array[array_in_use++] = x;
}
It's tedious, and I'm not convinced it's a good thing for a beginner to be doing. You'd learn more useful stuff if you learned how to use vectors properly.
You could always use realloc(). It's a part of the C Standard Library, and the C Standard Library is a part of the C++ Standard Library. No need for tedious news and deletes.
#include <cstdlib>
#include <iostream>
#include <fstream>
int main(void)
{
int* array = nullptr;
unsigned int array_size = 0;
std::ifstream input("pop.txt");
for(int x; input >> x;)
{
++array_size;
int* array_failsafe = array;
array = static_cast<int*>(realloc(array, sizeof(x) * array_size));
if(array == nullptr)
{
std::cerr << "realloc() failed!" << std::endl;
free(array_failsafe);
return EXIT_FAILURE;
}
array[array_size-1] = x;
}
for(unsigned int i = 0; i < array_size; ++i)
{
std::cout << "array[" << i << "] = " << array[i] << std::endl;
}
free(array); // Don't forget!
return EXIT_SUCCESS;
}
I'm just starting to learn C++ so excuse me for this simple question. What I'm doing is reading in numbers from a file and then trying to add them to an array. My problem is how do you increase the size of the array? For example I thought might be able to just do:
#include <iostream>
using namespace std;
int main() {
double *x;
x = new double[1];
x[0]=5;
x = new double[1];
x[1]=6;
cout << x[0] << "," << x[1] << endl;
return 0;
}
But this obviously just overwrites the value, 5, that I initially set to x[0] and so outputs 0,6. How would I make it so that it would output 5,6?Please realize that for the example I've included I didn't want to clutter it up with the code reading from a file or code to get numbers from a user. In the actual application I won't know how big of an array I need at compile time so please don't tell me to just make an array with two elements and set them equal to 5 and 6 respectively.Thanks for your help.
You don't want to work with arrays directly. Consider using a vector, instead. Then, you can call the push_back function to add things to the end, and it will automatically resize the vector for you.
#include <iostream>
#include <vector>
int
main() {
double value;
std::vector<double> values;
// Read in values
while (std::cin >> value) {
values.push_back(value);
}
// Print them back out
for (std::size_t i(0), len(values.size()); i != len; ++i) {
std::cout << values[i];
}
}
You should use a collection class to do this for you rather than managing it yourself. Have a look at the "vector" class. It's essentially a dynamic array that resizes automatically as required.
In your situation you would use "vector" with the "double" type. You may also need to read up on templates in C++.
http://www.cplusplus.com/reference/stl/vector/
Or, if you don't want to use STL or another dynamic thing, you can just create the array with the correct size from the beginning: x = new double[2];
Of course the problem there is how big to make it. If you don't know, then you'll need to just create it "big enough" (like a hundred, or a thousand)... which, at some point, won't be big enough and it will fail in some random looking way. So then you'll need to resize it. And once you get to that point, you'll wish you'd used the STL from the start, like the other answers are telling you to do.
#include <iostream>
using namespace std;
int main() {
double *x = new double[2];
x[0]=5;
x[1]=6;
cout << x[0] << "," << x[1] << endl;
return 0;
}
Here's an example though for good measure, so you can see the pattern:
#include <iostream>
using namespace std;
int main() {
// Allocate some memory for a double array of size 1 and store
// an address to the beginning of the memory in mem_address.
double* mem_address = new double[1];
// Assign 5 to the first element in the array.
mem_address[0] = 5;
// Save the address of the memory mem_address is currently
// referencing.
double* saved_address = mem_address;
// Allocate some memory for a double array of size 2 and store
// an address to the beginning of the memory in mem_address.
mem_address = new double[2];
// Copy over the 1 element from the first memory block
// to the new one.
mem_address[0] = saved_address[0];
// Done with the old memory, so clean it up.
delete [] saved_address;
// Assign 6 to the second element in the new array.
mem_address[1] = 6;
// Print out the 2 elements in the new array.
cout << mem_address[0] << "\n";
cout << mem_address[1] << "\n";
// Done with the new array memory now, so clean it up.
delete [] mem_address;
}
If for some reason you don't have access to STL -- or want to learn how to do this yourself -- you could use an algorithm like this:
Allocate your array as some arbitrary size, and remember how many elements are in it and how big it is:
int *a = malloc(int * ARBITRARY_SIZE);
int size = 0;
int allocated = ARBITRARY_SIZE;
each time you add a new element, increase "size". If size equals ARBITRARY_SIZE, multiply 'allocated' by 2, and reallocate the array. Either way, assign the new value to a[size].
void addElement(int value) {
++size;
if (size == allocated) {
allocated *= 2;
a = realloc(sizeof(int) * allocated);
a = new_a;
}
a[size] = value;
}
Note that your code above has at least one bug -- you aren't allocating enough space for x[1] in either case.
Also obviously in real code you'd check that the return from malloc & realloc isn't null.
An array always needs a contiguous block of memory. In a situation where you might need to resize the array later on, reallocation is probably the only solution. This is what Moishe and Shadow2531 do above.
The problem with reallocation is that it can be a costly operation. So if you need adding 5 more elements to a 5000 element array, you might end up copying all the 5000 elements across memory.
Using a linked list instead can be considered for such a scenario.