Int Array Length C++ - c++

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;
}

Related

Dynamic resizing array code not working in C++?

I am trying to create an array, which doubles every time it is completely filled.
#include <iostream>
using namespace std;
int* array_doubler(int* array, int size){
int *new_array = new int[size*2];
for(int i = 0; i < size; i++){
new_array[i] = array[i];
}
delete[] array;
return new_array;
}
int main()
{
int N = 10; // Size of array to be created
int *array = new int[0];
for(int i = 0; i < N; i++)
{
if(array[i] == '\0')
array = array_doubler(array, i);
array[i] = i*2;
}
//Printing array elemensts
for(int i = 0; i < N; i++)
cout << array[i] << '\t';
cout << '\n';
return 0;
}
Problem is when I create dynamic memory with new, all the spots have the null character \0 value in them (not just the last spot). i.e. If i write:
int* p = new int[5];
then all the 5 blocks in memory p[0],p[1],p[2],p[3],p[4],p[5] have \0 in them, not just the p[5]. So the if(array[i] == '\0') in my main() calls array_doubler for every single iteration of for loop. I want it to fill the available spots in the array first and when it reaches the last element, then call array_doubler.
Problem is when I create dynamic memory with new, all the spots have the null character \0 value in them (not just the last spot).
Actually they have undefined values in them. 0 is a valid value for them to have, but tomorrow the compiler might suddenly decide that they should all have 1 instead of 0.
If you want to detect the end of an array, then you have to remember how big the array is. C++ doesn't do it for you. Actually, it does do it for you if you use std::vector, but I suppose that's not the point of this exercise.
I'm not sure why you'd want to do this, as std::vector offer this kind of feature, and are more idiomatic of c++ (see isocpp faq on why C-style array are evil).
One of the issue of C-style array is the fact that they don´t know their own size, and that they don't have default value, thus stay uninitialized.
If for some reason you need to not use std::vector, the next best solution would be to wrap the array with it's size in a structure or a class (which is kinda what std::vector is doing), or to initialize your array using std::memset (which is the C function you would use if you were in C).
Do keep in mind that this is not considered as good practices, and that the STL offer plenty of solution when you need containers.

Using pointer variables to print specific array variables

I am a C++ beginner and my task is as follows:
Define and initialise a single-dimensional integer array. Next, define a pointer that points to the first element in the array and passes the pointer to a function.
Using only pointer variables (and looping constructs), print only the array values that are exact multiples of 7 from start to finish to standard output. The only program output should be the numbers, one per line with no white space.
I have tried:
void print_sevens(int* nums, int length)
{
int array[5] = { 5,8,21,43,70 };
int* ptr = array;
int* num = array;
for (int i = 0; i < length; i++)
{
*num++;
if (num[i] % 7 == 0) {
cout << num[i] << endl;
}
}
}
int main()
{
int array[5] = { 5,8,21,43,70 };
int* ptr = array;
print_sevens(ptr, 5);
}
It compiles but does not output anything.
I am also confused about passing the pointer to a function. Should this be done in the main file or in the function file?
You are creating an additional array in the print_sevens function, which is unnecessary as you already passed the pointer to the first element of the array created in the main()(i.e. array).
Removing that unnecessary array and related codes from the function will make the program run perfectly. (See online)
void print_sevens(int* nums, int length)
{
for (int i = 0; i < length; i++)
{
if (nums[i] % 7 == 0)
std::cout << nums[i] << std::endl;
}
}
and in the main you only need to do the follows, as arrays decay to the pointer pointing to its first element.
int main()
{
int array[5]{ 5,8,21,43,70 };
print_sevens(array, 5);
}
Note that,
num++ increments the pointer, not the underline element it is
pointing to (due to the higher operator precedence of operator++ than operator*). If you meant to increment the element(pointee) you
should have (*num)++.
Secondly, do not practice with using namespace std;. Read more:
Why is "using namespace std;" considered bad practice?
You are modifying the contents of your array when you do *num++.

C++: creating a dynamic array using dynamic memory

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".

pushback data from vector to vector of map

i have created a map called select_p and vector of this map is called pts. i have stored data in a array and i want to pushbcak these data into my vector of map. i tried this by inserting value of array into new vector and then pushback into my map.but it is not working please help me to correct these codes? thanks
#include<iostream>
#include<cstdlib>
#include <map>
#include <vector>
using namespace std;
int main()
{
int M=7;
int N=6;
int i=0;
int * temp;
map<int,vector<int> > select_p;
vector<int>pts;
for (int m=0; m<M; m++)
{
for (int n=0; n<N; n++)
{
vector<int>id;
if (n==0 && m==5)
{
temp = new int[3,i+N,i+N+1,i+1];
unsigned ArraySize = sizeof(temp) / sizeof(int);
id.insert(id.begin(),temp[0], temp[ArraySize]);
select_p[i].push_back(id);
}
i++;
}
}
delete[] temp;
system("PAUSE");
return 0;
}
for (int m=0; m<M; m++) {
for (int n=0; n<N; n++) {
if (n==0 && m==5) {
Why are you looping when you only actually do anything for a single pair of values of m and n? The loops are completely useless here; you would get the same effect by just setting n = 0 and m = 5.
temp = new int[3,i+N,i+N+1,i+1];
Whatever you think this does, that's not what it does. This is equivalent to temp = new int[i+1];. The rest of the expression inside of the [] has no effect.
That said, you should not use new to create arrays in your program. Use std::vector; it is far easier to use correctly.
unsigned ArraySize = sizeof(temp) / sizeof(int);
This does not work. When you dynamically allocate an array, you are responsible for keeping track of how many elements are in it. Given a pointer to a dynamically allocated array (like temp here) there is no way to determine the number of elements in the array.
What you have is equivalent to sizeof(int*) / sizeof(int), which is not going to do what you expect.
id.insert(id.begin(),temp[0], temp[ArraySize]);
std::vector::insert takes a range of iterators: you have provided it with two values. Presumably you want to use temp, which points to the initial element of the dynamically allocated array, and temp + i + 1, which points one past the end of the array. That said, since you haven't set the values of the elements in the array, you are copying uninitialized memory, which probably isn't what you mean to do.
select_p[i].push_back(id);
select_p[i] is a std::vector<int>. std::vector<int>::push_back() takes a single int that is appended to the sequence. Presumably you just mean to use assignment to assign id to select_p[i].
You should get a good introductory C++ book if you want to learn to program in C++. I am sorry to say that your program is nonsensical.

give feedback on this pointer program

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.