Is this a good use/code of arrays with pointers in C++? - c++

I'd like to ask you if you think about this code, whether it is totally bad or i'm doing a bad use of the memory
This is the code
// Ask for capacity
int capacity ;
cout << "capacity: ";
cin >> capacity;
// Declare the array with pointers, this line is very important
int *arr = new int;
// For 0 until capacity-1 print ask for the numbers
for (int i = 0; i < capacity; i++)
{
cout << "number: ";
cin >> *(arr + i);
}
// Print them
for (int i = 0; i < capacity; i++)
{
cout << "[" << i << "]: " << *(arr + i) << " in " << arr + i << endl;
}
And this is an example of its output
capacity: 9
number: 1
number: 2
number: 3
number: 4
number: 5
number: 6
number: 7
number: 8
number: 9
[0]: 1 in 0x55dee480c690
[1]: 2 in 0x55dee480c694
[2]: 3 in 0x55dee480c698
[3]: 4 in 0x55dee480c69c
[4]: 5 in 0x55dee480c6a0
[5]: 6 in 0x55dee480c6a4
[6]: 7 in 0x55dee480c6a8
[7]: 8 in 0x55dee480c6ac
[8]: 9 in 0x55dee480c6b0
Look that, effectively it's saving the numbers in the correct positions in memory (4 bits, the size of an int)
But what's the limit? How can I know if I'm touching memory that I shouldn't touch?
Because look that I'm declaring the array as
int *arr = new int
Is that okay?
the same with this code, but this could be a little bit worse because it's a string, an array of characters as you may know
// Declaring the pointer name as new char and ask for it
char *name = new char;
cout << "name in: ";
cin >> name;
cout << "name out\n";
for (int i = 0; *(name + i) != '\0' ; i++)
{
printf("[%i]: %c\n", i, *(name + i));
}
Example:
name in: Gilberto
name out
[0]: G
[1]: i
[2]: l
[3]: b
[4]: e
[5]: r
[6]: t
[7]: o

The code only allocates one int object. Fix:
int* arr = new int[capacity];
*(arr + i) can be simpler: arr[i].
The code needs to delete the array at the end:
delete[] arr;
Or, better, use a smart pointer to avoid having to delete manually:
std::unique_ptr<int[]> arr(new int[capacity]);
Or, even better, use std::vector<int> arr(capacity);.

Raw (owning) pointers and manual memory management is almost never a good idea in modern C++. You should use containers like std::array and std::vector rather than C-style arrays any day. And ownership and lifetime of dynamic resources is much better modeled with smart pointers like std::unique_ptr, std::shared_ptr & std::weak_ptr rather than raw pointers. Don't write code that's easy to get wrong. Use the facilities we have available, to write code that's easy to get right and hard(er) to get wrong.

Related

Truncate the last few elements of an array

I am new to C and C++, please help me in getting the required solution. I have used memcpy to copy the contents of 'array' to 'arr'. But since the size of 'arr' is 10, it appends 0 to the remaining elements. How can I truncate the 'arr' to size 5.
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
uint8_t array[5] = {1,2,3,4,5};
uint8_t arr[10] = {0};
memcpy( arr, array, 5);
for (auto e: arr){
cout << e << " ";
}
return 0;
}
Output for the above code: 1 2 3 4 5 0 0 0 0 0
required output : 1 2 3 4 5
You cannot truncate the size of the static array after compilation. If you were using some other data structure like vector from C++ STL then the size of that container object might have been variable.
Instead of
for (auto e: arr){
cout << e << " ";
}
you can keep array's size in a variable and cout arr that times, like:
int i, arraySize = 5;
for (i=0; i<arraySize; i++) {
cout << arr[i] << " ";
}
Best Practice is to create a pointer and free the memory or second way is to don't allow kernel to give memory to you create custom memory allocator and assign it to your array

Entering value to dynamically allocated memory at runtime

Following is the code I wrote for reading a value at run time to dynamically allocated memory:
void main()
{
clrscr();
int *p = new int[5];
int *a = new int();
cin >> *a; // **line 5**
cout << *a << "\n"; // **line 6**
cout << &p; // line 7
cout << *p; // line 8
cout << "\nEnter 5 no for array\n";
for (int i = 0; i <= 4; i++)
{
cout << &p[i] << " :- ";
cin >> p[i]; // LINE 12
}
for (i = 0; i <= 4; i++)
cout << "\n" << p[i]; // LINE 16
delete[] p;
delete a;
getch();
}
I would like to know that while entering data for user in integer, we have to use *a with cin and cout for entering data in line 5 & 6 but in case of array we just gave the pointer variable name in line 12 & 16. Can anyone please tell me why we are having this difference?
Moreover can anyone also please tell me the difference between output of line 7 & 8.
You don't "have to"; you could have written cin >> a[0].
For built-in types and pointers and such, a[b] is *(a+b) is *(b+a) is b[a] and you can interchange them all.
It's only convention that leads to a choice. Like generally if you'd allocated more than one int you'd use "array notation" (a[i]) and if you'd allocated only one int you'd use a straight-up dereference (*(a+0), or *a).
But the language doesn't really care how many elements you allocated because either way you just have a pointer to "one or more" consecutive elements.
tl;dr this is just how the syntax was designed.
As for your second question, &p and *p give different results because they mean different things, and I'll leave discerning that difference as an exercise to the reader.

Creating array of pointers using input from stdin

I understand how to create it in general. For example:
int ar1[3] = {1, 2, 3};
int ar2[4] = {4, 5, 6, 7};
int* ar[2] = {ar1, ar2};
cout << *(ar[1]+2);
will output:
6
Now, I would like to create the same array using cin. The format of the input is the following. The first line stores the number of arrays n. The other n lines store first the number of elements in the array, and then the elements of the arrays. For example:
2
3 1 2 3
4 4 5 6 7
To parse the input and create the array I have the following code:
int n;
cin >> n;
cout << "The number of variable-length arrays: " << n << endl;
int* ar [n];
for (int k = 0; k < n; k++){
cout << "..reading the array number: " << k + 1 << endl;
int n_el; cin >> n_el;
cout << "The array contains " << n_el << " elements." << endl;
int ar_k [n_el];
for (int j = 0; j < n_el; j++) {
cin >> ar_k[j] ;
}
ar[k] = ar_k;
for (int j = 0; j < n_el; j++) {
cout << *(ar[k] + j) << endl;
}
}
Which outputs:
The number of variable-length arrays: 2
..reading the array number: 1
The array contains 3 elements.
1
2
3
..reading the array number: 2
The array contains 4 elements.
4
5
6
7
However, if I try to access the arrays outside the loop, it does not work. Given the code:
for (int j = 0; j < 3; j++) {
cout << *(ar[0] + j) << endl;
}
the output is:
4
32766
44613906
I guess it happens because as soon as you are out of the loop, the memory where the arrays are stored gets freed. How to prevent this? Or should I use a different approach to solve the task?
You are right, the memory is getting freed when you exit the loop.
Also your code is illegal int* ar [n]; where n is a variable is not legal C++. Even though your compiler accepts it (another compiler would not).
One other approach is to use dynamic memory allocation using new. Replace
int* ar [n];
with
int** ar = new int*[n];
and
int ar_k [n_el];
with
int* ar_k = new int[n_el];
The point of dynamic allocation is that the memory doesn't get freed until you delete it.
Dynamic memory allocation is a big topic, and this answer just scratches the surface. Time for some reading.

C++ arrays store wrong values

I tried to input two array numbers, A and B. But every time I input the last B number, besides it changed the value of B[i+n], it also replace the value of A[0]
Here is the code:
#include <iostream>
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
int a[] = {};
int b[] = {};
int t, i;
cout << "Amount of numbers: ";
cin >> t;
for (i = 0; i < t; i++) {
cout << "Enter number for A" << i+1 << ": ";
cin >> a[i];
cout << "Enter number for B" << i+1 << ": ";
cin >> b[i];
}
for (i = 0; i < t; i++) {
cout << a[i] << " ";
cout << b[i] << " ";
}
return 0;
}
For example
Amount of numbers: 2
Enter number for A1: 1
Enter number for B1: 2
Enter number for A2: 3
Enter number for A3: 4
The output supposed to be 1 2 3 4, but from the code I got 4 2 3 4 (the B[1] replace the value of A[0].
Can someone help me to fix this? Thanks
The problem is that you are using a two stack allocated arrays with unspecified size, which is 0 since you initialize them with { }.
These arrays are not dynamic, you can't add elements like you are doing. Their size must be specified a priori directly or through initialization and it's reserved on the stack at compile time, which means that if you try to access an element of a over its size, then you'll end up in b since they are stored next to its other.
Use two std::vector<int> instead so that you can do
std::vector<int> a;
..
a.resize(t);
..
cin >> a[i]
You're allocating arrays without a size.
Try std::vector if you want dynamically sized arrays.
As others have mentioned, what is happening is that you are allocating empty arrays in the stack, and then accessing past the bounds of said array. This has far more dire consequences than you may at first realize.
The first of which is, as #Jack mentioned, that writing past a[0] will start writing in b, giving you duplicate and nonsensical values at the end of your program. Perhaps less obvious is the fact that you will also start overwriting t and i, since they are allocated in the stack after a and b. To illustrate my point, look at the output below:
Amount of numbers: 2
Enter number for A1: 1
Enter number for B1: 2
Enter number for A2: 3
Enter number for B2: 4
Enter number for A3: 5
Enter number for B3: 6
a[0] 0x7fffffffe2e0 -> 1
b[0] 0x7fffffffe2e4 -> 3
a[1] 0x7fffffffe2e4 -> 3
b[1] 0x7fffffffe2e8 -> 5
a[2] 0x7fffffffe2e8 -> 5
b[2] 0x7fffffffe2ec -> 2
a[3] 0x7fffffffe2ec -> 3
b[3] 0x7fffffffe2f0 -> 4197280
a[4] 0x7fffffffe2f0 -> 4197280
b[4] 0x7fffffffe2f4 -> 0
t 0x7fffffffe2e8 -> 5
i 0x7fffffffe2ec -> 5
You'll note that the program does not behave as expected, and you are prompted for A/B3, not just the expected 2. That is because t is overwritten when b[1] or a[2] are written to, as they all correspond the the same address, which of course makes the loop condition fail.
To allocate arrays in the stack, a size has to be provided at compile time. int a[10], etc. This is used when the size is known prior to execution. If the size unknown, as is your case, you can allocate an array in the heap with new[], as below.
cout << "Amount of numbers: ";
cin >> t;
int* a = new int[t];
int* b = new int[t];
Which will of course give you the expected results:
Amount of numbers: 2
Enter number for A1: 1
Enter number for B1: 2
Enter number for A2: 3
Enter number for B2: 4
a[0] 0x603010 -> 1
b[0] 0x603030 -> 2
a[1] 0x603014 -> 3
b[1] 0x603034 -> 4
t 0x7fffffffe2d8 -> 2
i 0x7fffffffe2dc -> 2
The recommended solution is, of course, to use an std container, namely std::vector, where the heap allocation is done for you, and you can simply write:
std::vector<int> a;
std::cin >> input;
a.push_back(input);
The zero size arrays are not valid in C++, and this code doesn't compile with the two compilers I tried.
Instead of raw arrays you can use std::vector.
With std::vector you can use the push_back member function to add items at the end.

C++ program only lists last value entered into an array

I am trying to output the values present in the array, that are accepted during runtime, onto the console. But when I run this program I get the 5 values in the array as the last value only.
For example: if i give 0 1 2 3 4 as the five values for this program then the output is shown as 4 4 4 4 4.
#include "stdafx.h"
#include<iostream>
using namespace std;
int main()
{
int arrsize = 5;
int *ptr = new int[arrsize];
*ptr = 7;
cout << *ptr << endl;
cout << "enter 5 values:";
for (int i = 0; i < arrsize; i++)
{
cin >> *ptr;
cin.get();
}
cout << "the values in the array are:\n ";
for (int i = 0; i < arrsize; i++)
{
cout << *ptr << " ";
}
delete[] ptr;
cin.get();
return 0;
}
Both of your loops:
for (int i = 0; i < arrsize; i++)
...
loop over a variable i that is never used inside the loop. You are always using *ptr which refers always to the first element of the dynamically allocated array. You should use ptr[i] instead.
A part from that, dynamic allocation is an advanced topic. I'd recommend sticking with simpler and more commonly used things first:
std::cout << "Enter values:";
std::vector<int> array(std::istream_iterator<int>(std::cin), {});
std::cout << "\nThe values in the array are:\n";
std::copy(begin(array), end(array), std::ostream_iterator<int>(std::cout, " "));
Live demo
Following issues I think you could tackle:
The first include can be omitted I think. Your code works without that.
You use cin.get(), not sure why you need that. I think you can remove that. Even the one at the very end. You could put a cout << endl for the last newline. I am using Linux.
And use ptr like an array with index: ptr[i] in the loops as mentioned in the other answer. ptr[i] is equivalent to *(ptr+i). You have to offset it, otherwise you're overwriting the same value (that is why you get that result), because ptr points to the first element of the array.
P.S.: It seems that if you're using Windows (or other systems) you need the cin.get() to avoid the console to close down or so. So maybe you'd need to check it. See comments below.