This is relatively simple program. But I want to get some feedback about how I can improve this program (if any), for example, unnecessary statements?
#include<iostream>
#include<fstream>
using namespace std;
double Average(double*,int);
int main()
{
ifstream inFile("data2.txt");
const int SIZE = 4;
double *array = new double(SIZE);
double *temp;
temp = array;
for (int i = 0; i < SIZE; i++)
{
inFile >> *array++;
}
cout << "Average is: " << Average(temp, SIZE) << endl;
}
double Average(double *pointer, int x)
{
double sum = 0;
for (int i = 0; i < x; i++)
{
sum += *pointer++;
}
return (sum/x);
}
The codes are valid and the program is working fine. But I just want to hear what you guys think, since most of you have more experience than I do (well I am only a freshman ... lol)
Thanks.
Fix the memory leak.
i.e delete temp;
Also, check if the file is open/created..etc
ideally, you should manipulate/traverse the array using your temp variable instead of using *array itself
You are not initializing your array correctly. This statement:
double *array = new double(SIZE);
Allocates one double and initializes it to the value of SIZE. What you should be doing is using array allocation:
double *array = new double[SIZE];
Another general problem is you rarely ever want to assign dynamically allocated memory to a raw pointer. If you want to use base types instead of higher level objects such as std::vector, you should always use a smart pointer:
boost::scoped_array<double> array(new double[SIZE]);
Now the array will automatically get freed regardless of how you leave your scope (i.e. from a newly added return or from an exception).
Since we're talking about C++, I would suggest using STL containers and algorithms. I also find that in most cases it's better to use references or smart pointers (e.g. boost::shared_ptr) instead of raw pointers. In this case there's no need for pointers at all.
Here is how you could write your program:
#include <fstream>
#include <vector>
#include <iostream>
#include <numeric>
#include <iterator>
using namespace std;
int main()
{
ifstream f("doubles.txt");
istream_iterator<double> start(f), end;
vector<double> v(start, end);
if (v.empty())
{
cout << "no data" << endl;
return 0;
}
double res = accumulate(v.begin(), v.end(), 0.0);
cout << "Average: " << res / v.size() << endl;
return 0;
}
If x is 0, then Average will generate a divide-by-zero error.
Here are some "code review" comments:
In main():
Change SIZE to "size_t" instead of int
Why SIZE is uppercase? (May be the author's convention is to have constants as uppercase, in that case it is fine.)
Combine temp declaration and assignment into one statement as: double * temp = array;
What if inFile is not available or can't be opened for reading?
What if inFile have less than SIZE number of items?
Change the loop variable i to size_t.
Remove blank line before declaration of inFile.
Return some number (e.g. 0) from main().
Correct the allocation of array.
In Average():
Change the second argument of Average to size_t.
Assert and/or guard for pointer being non-NULL
Assert and/or guard against division by zero.
Acknowledgement: Some points are collected from other answers. I tried to make a complete list as far as I could.
Related
I'm trying to create a dynamic array or what should you call that, using pointer, but when I try to cout the length of the array after setting the elements, it gives me 0. I'm not sure what I'm doing wrong here.
Here's the code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int *p = NULL;
int kek = 0;
cin >> kek;
p = new int[kek];
for (int i = 0; i < kek; i++)
{
p[i] = 0;
}
int sizeOfArray = sizeof(p) / 8;
cout << sizeOfArray << endl;
delete[] p;
}
Better use the stl vector, this have the size() method
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> p;
int kek = 0;
cin >> kek;
p.resize(kek);
for (int i = 0; i < kek; i++)
{
p[i] = 0;
}
int sizeOfArray = p.size();
cout << sizeOfArray << endl;
p.clear();
return 0;
}
You are just taking the size of the pointer.
But just use std::vector
You can't use sizeof() to determine the size of a dynamically allocated array because the size can't be determined at compile time, and therefore is not stored anywhere.
When you have a statically allocated array like:
int numbers[40];
The compiler is able to figure out that the size of the block of memory called numbers is 40 items * 8 bytes each = 320 bytes, and determine that a statement like sizeof(numbers) is equivalent to 320, and do the proper substitutions.
But when you have something like
int *numbers = new int[n];
numbers is defined explicitly as a pointer to some memory, and when you do sizeof(numbers), it'll try to evaluate the size of the pointer, which will be 4 or 8 bytes depending on the compiler and platform you're on.
Again, numbers is a pointer, pointing to the first item in a block of memory. There's no easy way to tell which one of the blocks of memory in the computer it's pointing to, and how big the block is in bytes
So that means you'll have to keep track of the size of the array yourself.
You already have the variable kek, so size in bytes should be kek * sizeof(int)
Or like the others have said, you can also use a vector to keep track of the length for you:
vector<int> numbers;
int sizeInBytes = numbers.size() * sizeof(int);
It is not possible to determine the length of a new[]ed array in C++ from a pointer returned by new[]. So, your attempt to "to cout the length" does not really do that. sizeof does not do that and will not help you with that.
The only way to "cout" the size of a new[]ed array is to remember that size and manually carry it from the point where you allocated the array to the point where you need to "cout" the size. If you somehow lose knowledge of that size along the way, you will never be able to restore it.
In your case the size is kek. This is what you "cout".
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 am working on a program that reads in altitude values from a file into a 2-D array, a matrix, and I am trying to pass that array to another function that finds the maximum value. I understand that, by default, arrays are passed by reference, but I am not trying to change the values of the array in the function so this shouldn't matter much. I have gone through several pages about calling arrays but I haven't been able to find any mention of the type of error I am getting when I compile the code. The problem seems to be in the number of arguments that are called or the way in which the are called, but I can't see any discrepancies in the various appearances of the function. My guess is there is something about passing a 2-D array that I wasn't told in class and that I haven't learned yet on my own. Any help would be greatly appreciated.
The code is:
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
// First instance of function declaration
double find_max(double elevations[][3600], double ilat, double ilon, int nlat, int nlon);
int main(int argc, char *argv[]) {
// Declare program variables
double lat_init, lon_init;
double lat_res, lon_res;
double peak, valley;
int lon_col, lat_row;
string indat, inpoints;
.
.
.
double elevations[lat_row][lon_col];
// Open and read topographic data file
ifstream topo_points;
topo_points.open(inpoints.c_str());
for (int i=0; i<lat_row; i++) {
for (int j=0; j<lon_col; j++)
topo_points >> elevations[i][j];
}
// Call function to find peak in the data
peak = find_max(elevations, lat_init, lon_init, lat_row, lon_col);
return 0;
}
// ***** Here lie the functions *****
// This function reads in the array of elevations, initial latitude and longitude
// of the data, and the number of data points and uses this information to find
// the latidude and longitude of the highest point on earth
double find_max(double elev[][3600], double ilat, double ilon, int nlat, int nlon) {
double num, max;
double latpos, lonpos;
max = 0;
for (int i=0; i<nlat; i++) {
for (int j=0; j<nlon; j++) {
num = elev[i][j];
if (num > max) {
max=num;
latpos= ilat - i;
lonpos= ilon + j;
}
}
}
cout << "The tallest peak on earth has an altitude of " << max;
cout << " and is located at " << latpos << "deg latitude and ";
cout << lonpos << "deg longitude";
return max;
}
However, when I call the function I get the following error:
error: cannot convert 'double (*)[(((long unsigned int)(((long int)lon_col) - 1)) + 1u)]' to 'double (*)[3600]' for argument '1' to 'double find_max(double (*)[3600], double, double, int, int)'
From what i see in the code, there are a few glitches.
You have defined the array elevations as
double elevations[lat_row][lon_col];
which isn't gonna work, because the size of the c-style arrays must be determinable during compile-time. And since lat_row and lon_col are variables, that's an error.
So, you could either use arrays with dynamic memory allocation, or std::vector, which in most cases is preferable. So, in your case you could have something like:
typedef std::vector< std::vector<double> > ElevationsType;
ElevationsType elevations;
and then just use that array or array of double.
Then, your find_max function can be declared as:
double find_max(const ElevationsType &elevations, double ilat, double ilon);
Note that in this case you won't need to pass nlat and nlon, because you could just do:
ElevationsType::size_type nlat, nlon, i, j;
nlat = elevations.size();
for (i = 0; i != nlat; ++i) {
nlon = elevations[i].size();
for (j = 0; j != nlon; ++j) {
const double element = elevations[i][j];
// do whatever you need to do with the element
}
}
Of course, if your arrays will have fixed size you could set it (std::vector::resize) once you create the object of type ElevationsType, or just allocate enough space (std::vector::reserve) and then initialize it. If it's large, that may increase performance.
However, if you choose to go with c-style arrays, it would be something like:
double **elevations = (double **)malloc(sizeof(double*) * lat_row);
for (size_t i = 0; i != lat_row; ++i) {
elevations[i] = (double*)malloc(sizeof(double) * lat_col);
// initialize the elements
for (size_t j = 0; j != lat_col; ++j) {
elevations[i][j] = 100.0; /* your value */
std::cout << "elevations[" << i << "][" << j << "] = " << elevations[i][j] << std::endl;
}
}
which is more tedious for many people.. so to speak. And if you go in that route, just don't forget to deallocate all allocated memory with free().
you could also use the c++ new operator to allocate the memory, but the principle is pretty much the same.
So I'd suggest you to use the std::vector. It's easier to work with, at least if you have limited experience. It will also take care of memory allocation/deallocation, and that causes many bad things, overflows, leaks, etc. which will be avoided if you use the vector.
You're trying to pass an array whose size is determined dynamically (i.e. at runtime), and pass it to a function which expects the array to have its 2nd dimension determined at compile time to be 3600 (which seems like a pretty reasonable thing to complain about, actually).
I have to use a dynamic length int array in my program, and want to be able to get the number of objects in it at various points in my code. I am not that familiar with C++, but here is what I have. Why is it not giving me the right length? Thanks.
<#include <iostream>
Using Namespace std;
int length(int*);
void main()
{
int temp[0];
temp[0] = 7;
temp [1] = 10;
temp[2] = '\0';
cout << length(temp) << endl;
}
int length(int* temp)
{
int i = 0;
int count = 0;
while (*temp + i != '\0')
{
count++;
i++;
}
return count;
}
currently it just goes into an endless loop ;_;
In C++ arrays are not dynamic. Your temp array has zero length, and attempting to write to members beyond its length is undefined behaviour. It's most likely not working as it will be writing over some part of the stack.
Either create a fixed size array with enough space to put everything you want to in it, or use a std::vector<int> which is a dynamic data structure.
#include <iostream>
#include <vector>
using namespace std;
int length(int*);
int main () // error: ‘::main’ must return ‘int’
{
int temp[3];
temp[0] = 7;
temp[1] = 10;
// don't use char constants for int values without reason
temp[2] = 0;
cout << length(temp) << endl;
vector<int> vec_temp;
vec_temp.push_back(7);
vec_temp.push_back(10);
cout << vec_temp.size() << endl;
}
int length(int* temp)
{
int i = 0;
int count = 0;
while (*(temp + i) != 0) // *temp + i == (*temp) + i
{
count++;
i++; // don't really need both i and count
}
return count;
}
For the vector, there's no need to specify the size at the start, and you can put a zero in, and finding the length is a simple operation rather than requiring a loop.
Another bug inside your loop was that you were looking at the first member of the array and adding i to that value, rather than incrementing the pointer by i. You don't really need both i and count, so could write that a couple of other ways, either incrementing temp directly:
int length(int* temp)
{
int count = 0;
while (*temp != 0)
{
++count;
++temp;
}
return count;
}
or using count to index temp:
int length(int* temp)
{
int count = 0;
while (temp[count] != 0)
++count;
return count;
}
This approach is a bad idea for a couple of reasons, but first here's some problems:
int temp[0];
This is an array of 0 items, which I don't even think is permitted for stack elements. When declaring an array like this you must specify the maximum number of values you will ever use: E.g. int temp[10];
This is super important! - if you do specify a number less (e.g. [10] and you use [11]) then you will cause a memory overwrite which at best crashes and at worst causes strange bugs that are a nightmare to track down.
The next problem is this line:
while (*temp + i != '\0')
That this line does is take the value stores in the address specified by 'temp' and add i. What you want is to get the value at nth element of the address specified by temp, like so:
while (*(temp + i) != '\0')
So that's what's wrong, but you should take five minutes to think about a better way to do this.
The reasons I mentioned it's a bad idea are:
You need to iterate over the entire array anytime you require its length
You can never store the terminating element (in this case 0) in the array
Instead I would suggest you maintain a separate value that stores the number of elements in the array. A very common way of doing this is to create a class that wraps this concept (a block of elements and the current size).
The C++ standard library comes with a template class named "vector" which can be used for this purpose. It's not quite the same as an array (you must add items first before indexing) but it's very similar. It also provides support for copying/resizing which is handy too.
Here's your program written to use std::vector. Instead of the 'length' function I've added something to print out the values:
#include <vector>
#include <iostream>
void print(std::vector<int> const& vec)
{
using namespace std;
for (size_t i = 0; i < vec.size(); i++)
{
cout << vec[i] << " ";
}
cout << endl;
}
int main()
{
std::vector<int> temp;
temp.push_back(7);
temp.push_back(10);
print(temp);
return 0;
}
You could try:
while (*(temp + i) != '\0')
Your current solution is calculating temp[0] + i (equals 7+i), which apparently is not what you want.
Not only C++ arrays are not dynamic as Pete points out, but only strings (char *) terminate with '\0'. (This is not to say that you can't use a similar convention for other types, but it's rather unusual, and for good reasons: in particular, relying on a terminator symbol requires you to loop through an array to find its size!)
In cases like yours it's better to use the standard library.
#include <vector>
#include <iostream>
int main()
{
std::vector<int> v;
v.push_back(7);
v.push_back(10);
std::cout << v.size() << std::endl;
return 0;
}
If you don't want to use std::vector, try this:
#include <iostream>
using namespace std;
int main () {
int vet[] = {1,2,3,4,5,6};
cout << (sizeof (vet) / sizeof *(vet)) << endl;
return 0;
}
The most common way to get the size of a fixed-length array is something like this:
int temp[256];
int len = sizeof (temp) / sizeof (temp[0]);
// len == 256 * 4 / 4 == 256 on many platforms.
This doesn't work for dynamic arrays because they're actually pointers.
int* temp = new int[256];
int len = sizeof (temp) / sizeof (temp[0]);
// len == 4 / 4 == 1 on many platforms.
For a dynamic-length array if you care about the size, you're best off storing it somewhere when you allocate the array.
The problem with your loop, as pointed out by many is that you have an operator precedence problem here:
*temp + i
should be:
*(temp + i)
But the bigger problem, also pointed out above, is that you don't appear to understand pointers versus fixed-length arrays and are writing off the end of your array.
If you want to use array properly, you have to allocate enough memory for storing values. Once you specified its length, you can't change it. To know array size, you should store it in variable e.g.:
int n;
cin>>n;
int array = new int[n];
int array_length=n;
If you want to change array's length, best way is to use std container, for example std::vector.
Here is the answer to your question
int myarr [] = {1, 2, 3, 4, 5};
int length = sizeof(myarr) / sizeof(myarr[0]);
cout << length;
Because you only allocate space for an array of zero elements.
The following lines
temp [1] = 10;
temp[2] = '\0';
do not allocate more memory or resize the array. You are simply writing data outside the array, corrupting some other part of the application state. Don't do that. ;)
If you want a resizable array, you can use std::vector (and use the push_back member function to insert new values)
A vector also has the size() member function which tells you the current size.
If you want to use the primitive array, you have to track the size yourself. (and, when resizing the array is necessary, copy all elements from the old array to the new, larger one)
To get dynamic behavior in arrays, use a std::vector, or fall back on the old school c style using int * with manual memory allocation (new and delete)[*]
[*] C implementations (discussed in the context of character arrays as C dynamic string length) used malloc, realloc, and free, but these should be avoided in c++ code.
Try this out:
int length(int* temp)
{
int count = 0;
while (*temp != 0 && *temp != -858993460)
{
++count;
++temp;
}
return count;
}
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.