Passing unknown Array to Function by reference (C++) - c++

I have spent a good hour trying to figure this out - how do I write this function (at top of code - insertionSort) that allows me to pass an array by reference to it. In a way that allows me to call '.size' on the array. It has to be an array for this assignment.
I have tried not passing it by reference, dereferencing the array before calling size on it, etc. I keep getting errors :(.
This is the most recent compiler error for this code:
insertionSort.cpp:11: error: parameter ‘A’ includes reference to array of unknown bound ‘int []’
insertionSort.cpp: In function ‘void insertionSort(int (&)[])’:
insertionSort.cpp:13: error: request for member ‘size’ in ‘(int)A’, which is of non-class type ‘int’
#include <iostream>
//#include <array> - says no such file or directory
using namespace std;
void insertionSort(int (&A)[]) <-----ERROR HERE
{
for (int j=1; j <= A->size(); j++) <-----ERROR HERE
{
int key = A[j];
//now insert A[j] into the sorted sequence a[0...j-1].
int i = j-1;
while (i >= 0 && A[i] > key)
{
A[i+1] = A[i];
i -= 1;
}
A[i+1] = key;
}
}
int main()
{
int Asize = 0;
cout << "Hello. \nPlease enter a number value for the insertionSort Array size and then hit enter: " << endl;
cin >> Asize;
int A[Asize];
char Atype;
cout << "There are three ways to order your inserstionSort array; \nb - for best case \nw - for worst case \na - for average case" << endl << "Which type do you desire for this array? \nPlease enter 'b', 'w', or 'a': " << endl;
cin >> Atype;
if (Atype == 'b')
{
cout << "You have chosen type b." << endl;
}
else if (Atype == 'w')
{
cout << "You have chosen type w." << endl;
}
else if (Atype == 'a')
{
cout << "You have chosen type a." << endl;
}
cout << "Terminate Program" << endl;
}

It's important to remember that C array's are just pointers to the first element of the array. Passing the array is easy, you would just do something like:
void foo(int *array)
or
void foo(int array[])
However, since it's just a pointer to it's base type it has no member functions to call and it has no clue what the memory structure looks like beyond it (ie. has no concept of length). If you wanted to know the length of a dynamic array that was passed then you need to pass the length as a second parameter, presumably whatever created the array should know its length.
void foo(int *array, unsigned int length)
Or, you can avoid all of this and use vectors which are conceptually similar to an ArrayList in java.

When you do:
std::cin >> Asize;
int A[Asize]; // Not standard
You use extension of your compiler to use VLA (Variable length array).
prefer to use std::vector instead (and then you have void insertionSort(std::vector<int> &v)).
if you cannot use std::vector, you may use:
std::unique_ptr<int[]> A(new int [Asize]);
As the size is known only at runtime, you have to pass the size to your function:
void insertionSort(int* a, std::size_t size)
and call insertionSort as follow:
insertionSort(A.get(), ASize);
With a known compile time size of array,
void insertionSort(int (&A)[42])
is the right way to pass array by reference.

Arrays can be passed by reference, for example:
void somefunc(int (&arr)[30]) {}
This will ensure that you cannot pass any other size for this array (fixed size array):
So, you cannot do this:
int a[40];
func(a); // compilation error
However, arbitrary sized array is also possible to pass by reference, for example:
template<typename T, size_t N>
void somefunc2(T (&arr)[N])
{
// N can be used as size, as required, instead of querying size of the array
}
So, corrected function is as below:
template<typename T, size_t N>
void insertionSort(T (&A)[N]) // ok, now
{
for (size_t j=1; j < N; j++)
{
int key = A[j];
//now insert A[j] into the sorted sequence a[0...j-1].
int i = j-1;
while (i >= 0 && A[i] > key)
{
A[i+1] = A[i];
i -= 1;
}
A[i+1] = key;
}
}

Try using Array.length that should work it does in Borland c++ builder

Related

Passing 2D Dynamic Array in a Function with parameter from array.h in C++

I've separated my code into 3 files: main.cpp, array.h, array.cpp
My code asks the user to input size of a square 2D matrix and I implement some functions (transpose, addition of 2 2D Arrays, etc)
my array.cpp's constructor initializes a dynamic array of size s and puts all entries to 0s.
Array::Array(int s)
{
// The constructor creates a dynamic array v[s][s], and set size to s.
// initialize all entries v[i][j] to 0.
int **v = new int*[s];
for(int i = 0; i < s; ++i)
v[i] = new int[s];
for(int i = 0; i < s; i++)
for(int j = 0; j < s; j++)
v[i][j] = 0;
}
Array::~Array()
{
// The destructor deletes v.
int arraysize = sizeof(v)/sizeof(v[0]);
for(int i = 0; i < arraysize; ++i)
{
delete [] v[i];
}
delete [] v;
}
This is part of my main.cpp that i'm having trouble with.
I have a function asking the user to input entries for 2d array on the top of my main function, but I've been getting error "type 'Array' does not provide a subscript operator"
#include <iostream>
#include "array.h"
using namespace std;
// input array
void input(Array &C)
{
int i, j;
for(i = 0; C[i][0] == 0; i++)
for(j = 0; C[0][j] == 0; j++)
{
cin >> C[i][j];
}
}
int main(void)
{
//input size
int size;
cout << "Please input array size:" << endl;
cin >> size;
//input A, B
Array A(size), B(size);
cout << "Please input " << size << "x" << size << "integer array A:" << endl;
input(A);
cout << "Please input " << size << "x" << size << "integer array B:" << endl;
input(B);
........
I have to use the parameter (Array &C) for the input function, but I'm not sure how to change the body of the input funtion
First off, the expression sizeof(v)/sizeof(v[0]) does not do what you expect it to do.
This would work for a statically-allocated array, not for a dynamically-allocated array.
A sizeof expression is translated during compilation-time, by applying it on the type of of the operand.
In your case, the operand is v and its type is int**.
Therefore, sizeof(v) is equivalent to sizeof(int**), and sizeof(v[0]) is equivalent to sizeof(int*).
You expect the expression sizeof(v) to give you the size of the dynamically-allocated array pointed by v, but the compiler cannot guess (during compilation-time) what this size is going to be during runtime.
With regards to the actual question at hand (and as already mentioned in a comment to it), you'll need to implement the following functions in your Array class:
Reader - int* Array::operator[](int index) const {return v[index];}
Writer - int*& Array::operator[](int index) {return v[index];}
BTW, declaring in the constructor a local variable named v, will result in the initialization of that local variable instead of in the initialization of the member variable of the same name.

Change the function signature

I'm new to C++ and for now there is one thing I would want to make clear. As I'm going through the tutorial,there is this program that stores user's input into an array and gives a sum of all numbers when the user exits the program:
//PROTOTYPE DECLARATION:
int readArray(int integerArray[], int maxNumElements);
int sumArray(int integerArray[], int numElements);
void displayArray(int integerArray[], int numElements);
int main(int nNumberofArgs, char* pszArgs[])
{
cout << "This program sums values entered\n";
cout << "Terminate the loop by entering a negative number" << endl;
//store the numbers from the user into a local array
int inputValues [128];
int numberOfValues = readArray(inputValues, 128);
//output the values and the sum of the values
displayArray(inputValues, numberOfValues);
cout << "The sum is " << sumArray(inputValues, numberOfValues) << endl;
return 0;
}
int readArray(int integerArray[], int maxNumElements)
{
int numberOfValues;
for(numberOfValues = 0; numberOfValues < maxNumElements; numberOfValues++)
{
//fetch another number
int integerValue;
cout << "Enter next number: ";
cin >> integerValue;
if (integerValue < 0)
{
break;
}
//otherwise store the number into the storage array
integerArray[numberOfValues] = integerValue;
}
//return the number of elements read
return numberOfValues;
}
//displayArray - display the members of an array:
void displayArray(int integerArray[], int numElements)
{
cout << "The value of the array is:" << endl;
for(int i = 0; i < numElements; i++)
{
cout << i << ":" << integerArray[i] << endl;
}
cout << endl;
}
//sumArray
int sumArray(int integerArray[], int numElements)
{
int accumulator = 0;
for(int i = 0; i < numElements; i++)
{
accumulator += integerArray[i];
}
return accumulator;
}
My questions are:
Is it neccessary to declare local variables in each function (e.g. int inputValues [128];)?
Would it be correct to store the input into the arguments that were declared in the function prototype? For example, can we just store everything into integerArray[] instead of creating a storage array integerValue ?
This may look obvious but I want to understand this to avoid making mistakes in the future.
inputValues is necessary if you want to pass an array to the function.
int inputValues [128];
int numberOfValues = readArray(inputValues, 128); //passing array to function
Either way you do it is fine. So what you have is not wrong.
As noted in the comments you could also pass inputValues by reference. Which you could declare the prototype of function like this.
int readArray(int (&integerArray)[128]);
Any changes you make to the array you passed by reference will be updated when the function returns to main because you are not operating on a copy of the array anymore.
Edit:
As #Kevin pointed out, you can use a template function to get the size of the array at compile time.
template<size_t N> int readArray(int (&integerArray)[N]);
There are a lot of understanding gaps in this question.
The function parameter lists will convert their input:
If the type is "array of T" or "array of unknown bound of T", it is replaced by the type "pointer to T"
Using the implicit array to pointer assignment:
Constructs a pointer to the first element of an array.
These two together hopefully help you to see that when you declare a function like: int readArray(int integerArray[], int maxNumElements), integerArray is really just a pointer to the first element of it's first argument. You call readArray(inputValues, 128) so the parameter integerArray is equivalent to &intputArray[0].
It is not necessary and you can use global variables instead but that is bad choice in terms security and visibility etc. This program can be done few different ways but I guess what you need to learn first is difference between local and global scope, pointer/array.
In the program, memory is allocated for
int inputValues[128]; //memory allocation
Then address of that location is passed here.
int numberOfValues = readArray(inputValues, 128);
It is much more efficient this way. But it will start make more sense once you get more experience with pointer and arrays.

Deleting element from an array in c++

I have read others posts, but they don't answer my problem fully.
I'm learning to delete elements from an array from the book and try to apply that code.
As far as I can grasp I'm passing array wrong or it is sending integer by address(didn't know the meaning behind that).
#include <iostream>
#include <cstdlib>
using namespace std;
void delete_element(double x[], int& n, int k);
int main()
{
// example of a function
int mass[10]={1,2,3,45,12,87,100,101,999,999};
int len = 10;
for(int i=0;i<10;i++)
{
cout<<mass[i]<<" ";
};
delete_element(mass[10],10&,4);
for(int i=0;i<10;i++)
cout<<mass[i]<<" ";
return 0;
}
void delete_element(double x[], int& n, int k)
{
if(k<1 || k>n)
{
cout<<"Wrong index of k "<<k<<endl;
exit(1); // end program
}
for(int i = k-1;i<n-1;i++)
x[i]=x[i+1];
n--;
}
There are a couple of errors in your code. I highlight some of the major issues in question 1-3:
You call exit, which does not provide proper cleanup of any objects since it's inherited from C. This isn't such a big deal in this program but it will become one.
One proper way too handle such an error is by throwing an exception cout<<"Wrong index of k "<< k <<endl;
exit(1);
Should be something like this:
throw std::runtime_error("invalid index");
and should be handled somewhere else.
You declare function parameters as taking a int& but you call the function like this: delete_element(mass[10],10&,4); 10& is passing the address of 10. Simply pass the value 10 instead.
You are "deleting" a function from a raw C array. This inherently doesn't make sense. You can't actually delete part of such an array. It is of constant compile time size created on the stack. The function itself doesn't do any deleting, try to name the functions something more task-oriented.
You are using C-Arrays. Don't do this unless you have a very good reason. Use std::array or std::vector. These containers know their own size, and vector manages it's own memory and can be re sized with minimal effort. With containers you also have access to the full scope of the STL because of their iterator support.
I suggest you rewrite the code, implementing some type of STL container
Line 15: syntax error
you can't pass a number&
If you want to pass by reference, you need to create a variable first, like:
your delete_element function signature conflicts with your declared arrays. Either use a double array or int array and make sure the signatures match.
delete_element(mass, len , 4);
when you write the name of an array without the brackets, then it's the same as &mass[0]
ie. pointer to the first element.
complete changes should be:
#include <iostream>
#include <cstdlib>
using namespace std;
void delete_element(int x[], int& n, int k);
int main(){
// example of a function
int mass[10] = { 1, 2, 3, 45, 12, 87, 100, 101, 999, 999 };
int len = 10;
for (int i = 0; i<10; i++){ cout << mass[i] << " "; };
cout << endl;
delete_element(mass, len , 4);
for (int i = 0; i<10; i++)cout << mass[i] << " ";
cout << endl;
cin.ignore();
return 0;
}
void delete_element(int x[], int& n, int k){
if (k<1 || k>n){
cout << "Wrong index of k " << k << endl;
exit(1); // end program
}
for (int i = k - 1; i<n - 1; i++)
x[i] = x[i + 1];
n--;
}
There are a couple of mistakes in your program.
Apart from some syntax issues you are trying to pass an int array to a function which wants a double array.
You cannot pass a lvalue reference of a int literal. What you want is to pass a reference to the length of the int array. see also http://en.cppreference.com/w/cpp/language/reference.
Here is an updated version of your program.
#include <iostream>
#include <cstdlib>
using namespace std;
void delete_element(int x[], int& n, int k);
int main() {
// example of a function
int mass[10] = { 1,2,3,45,12,87,100,101,999,999 };
int len = 10;
for (int i = 0;i < len;i++)
cout << mass[i] << " "; ;
cout << endl;
delete_element(mass, len, 4);
for (int i = 0;i < len;i++) // len is 9 now
cout << mass[i] << " ";
cout << endl;
return 0;
}
void delete_element(int x[], int& n, int k) {
if (k<1 || k>n) {
cout << "Wrong index of k " << k << endl;
exit(1); // end program
}
for (int i = k - 1;i<n - 1;i++)
x[i] = x[i + 1];
n--;
}
Although it does not answer your question directly, I would like to show you how you can use C++ to solve your problem in a simpler way.
#include <vector>
#include <iostream>
void delete_element(std::vector<int>& v, const unsigned i)
{
if (i < v.size())
v.erase(v.begin() + i);
else
std::cout << "Index " << i << " out of bounds" << std::endl;
}
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7};
delete_element(v, 4);
for (int i : v)
std::cout << i << std::endl;
return 0;
}
You cannot delete elements from an array, since an array's size is fixed. Given this, the implementation of delete_element can be done with just a single call to the appropriate algorithm function std::copy.
In addition, I highly suggest you make the element to delete a 0-based value, and not 1-based.
Another note: don't call exit() in the middle of a function call.
#include <algorithm>
//...
void delete_element(int x[], int& n, int k)
{
if (k < 0 || k > n-1 )
{
cout << "Wrong index of k " << k << endl;
return;
}
std::copy(x + k + 1, x + n, x + k);
n--;
}
Live Example removing first element
The std::copy call moves the elements from the source range (defined by the element after k and the last item (denoted by n)) to the destination range (the element at k). Since the destination is not within the source range, the std::copy call works correctly.

How to get size of array of vectors? [duplicate]

I'm studying C++ and I need to create structure Airplane and work with it.
My structure Airplane.h
#include "stdafx.h"
using namespace std;
struct Airplane {
string destination;
int number;
string type;
};
and it's my code
#include "stdafx.h"
#include "Airplane.h"
string SetDestination(int n);
string SetType(int n);
void PrintAirplaneList(Airplane * &airplaneList, int n, string title);
void SortByDestination (Airplane *&airplaneList, int n);
void FindAirplanesAndPrint(Airplane *&airplaneList, int n, string type);
int _tmain(int argc, _TCHAR* argv[])
{
using namespace std;
srand((unsigned)time(NULL));
int n;
cout << "Input n = ";
cin >> n;
Airplane * airplaneList = new Airplane[n];
for (int i = 0; i < n; ++i)
{
airplaneList[i].destination = SetDestination(rand()%5);
airplaneList[i].number = rand()%9001 + 1000;
airplaneList[i].type = SetType(rand()%3);
}
PrintAirplaneList(airplaneList, n, "List:");
SortByDestination (airplaneList, n);
PrintAirplaneList(airplaneList, n, "Sorted list (by destination):");
string type;
cout << "Input type: ";
getline(cin, type);
FindAirplanesAndPrint(airplaneList, n, type);
delete [] airplaneList;
system("PAUSE");
return 0;
}
string SetDestination (int n)
{
string destination;
switch(n){
case 0: destination = "Tokio"; break;
case 1: destination = "Amsterdam"; break;
case 2: destination = "Moscow"; break;
case 3: destination = "Philadelphia"; break;
case 4: destination = "San Diego"; break;
default: destination = "Unknown city"; break;
}
return destination;
}
string SetType (int n)
{
string type;
switch(n){
case 0: type = "passenger"; break;
case 1: type = "cargo"; break;
case 2: type = "post"; break;
default: type = "unknown type"; break;
}
return type;
}
void PrintAirplaneList(Airplane *&airplaneList, int n, string title)
{
cout << "\n";
cout << title << "\n\n";
for (int i = 0; i < n; ++i)
{
cout << "Destination: " << airplaneList[i].destination << "\n";
cout << "Number: " << airplaneList[i].number << "\n";
cout << "Type: " << airplaneList[i].type << "\n\n";
}
}
void SortByDestination (Airplane *&airplaneList, int n)
{
for (int i = 0; i < n - 1; ++i)
{
for (int j = 0; j < n -1; ++j)
{
if(airplaneList[j + 1].destination > airplaneList[j].destination) continue;
Airplane tempAirplane = airplaneList[j];
airplaneList[j] = airplaneList[j + 1];
airplaneList[j + 1] = tempAirplane;
}
}
}
void FindAirplanesAndPrint(Airplane *&airplaneList, int n, string type) {
cout << "Type - " << type << "\n";
int count = 0;
for (int i = 0; i < n; ++i)
{
if (airplaneList[i].type == type)
{
cout << "Destination: " << airplaneList[i].destination << "\n";
cout << "Number: " << airplaneList[i].number << "\n";
++count;
}
}
if (count == 0)
{
cout << "Not found\n";
}
}
I have two questions.
1. I can't input type in
string type;
cout << "Input type: ";
getline(cin, type);
FindAirplanesAndPrint(airplaneList, n, type);
and my function FindAirplanesAndPrint starts to work without any value for type. How to make my programm to get value?
2. How to get size of dynamic array in functions? Because it seems the passing size of array n in every function is the wrong way.
"How to get size of dynamic array in functions? Because it seems the passing size of array n in every function is the wrong way."
Yet it is the only way when you use dynamically allocated C-style array.
If you want to avoid sending the size explicitly then pass some object that wraps this raw memory buffer and provides other means of retrieving the size. The most reasonable solution here would be using std::vector<Airplane>.
1) Ommiting the irrelevant, this is basically what you got:
cin >> n;
getline(cin, type);
operator>> leaves a new-line character in the input buffer and that's the first character that getline sees. Since '\n' is the default line delimiter, you get an empty line. To fix it call cin.ignore() before you call getline to discard the '\n'.
2) If you wish to stick with raw pointers, passing the size as a parameter is your only choice. Switch to std::vector and you get size() method that you can query at any time.
The problem with entering type is that the input buffer contains the new line character after entering n. You should use member function ignore to clear the buffer before using function getline.
As for your second question then in general you should track the size of a dynamically allocated array yourself. Or you can set the last element of the array as NULL and use it as a sentinel.
you could probably make a dynamic array with 0 items, make an int counter, make a while loop with getline as a statement, while (getline(cin, string_var) != SomeText) /* SomeText = some kind of text so the user show you there are not going to be any more inputs*/, what you were going to do it in the for do it in the while and at the end of the while increase the counter by one, i++. And about the access to the array, if your dynamic array has 0 items, then SomeDynamicArray[1].something = SomeValue will just add a second item to the array and the "something" of that item will be equal to SomeValue.
type *ArrayPointer = new type[0];
string StringVar;
int i = 0;
while (getline(cin, StringVar) != "Text that show there are not going to be any more inputs") {
/*code*/
i++;
}
idk if it will work on your case, but try it if you want. Also, about everyone saying about vectors, as I know at least, vectors are slower and spend more memory, bcs they double there size instead of just increasing it every time needed. I hope I will be some help.
One approach that i use when i work with dynamic arrays, is to pass the array as a reference to the function. This will help you to keep the size information of the array.
For Example:
string list1[3] = {
"item1",
"item2",
"item3"
};
string list2[2] = {
"item1",
"item2"
};
template<typename T, size_t N>
void PrintItems(T(&items)[N]) {
for (int i = 0; i < N; i++) {
cout << items[i] << endl;
}
}
int main() {
PrintItems(list1);
PrintItems(list2);
}
In the previous example, N stores the correct size information for the array. More information here
You cannot portalby find out the size of a dynamically allocated array in C++.
This is actually not entirely correct. There is widespread support for a particular kind of size retrieval - the size of an array of objects with destructors.
To anyone considering using this however - I have to warn you that to my knowledge, this is not in any way guaranteed by any standard or compiler vendor. It may change at any point in time and should not be relied upon for anything other than hobby projects.
The size of the array of destructible objects is stored right before the objects themselves, and can be accessed with a basic pointer cast: ((size_t*)mem)[-1].
When you think about it - when you call delete [], you are not passing the size of the array, so C++ must store the exact size somehow to know how many objects to call the destructor on, in a way that can be trivially and efficiently accessed from the pointer itself. However - there is no guarantee that it has to be the number of elements - it can also be the number of bytes or the end pointer, possibly with some flag bits mixed in. That said, once they've decided on a convention, it would likely break some kind of backwards compatibility to change it later.
For those interested to test this, here's the code: https://ideone.com/Z0Sta1
#include <stdio.h>
struct bytes10
{
~bytes10() { printf("dtor %p", this); }
char _[10]; // to test whether the size or the count is returned
};
int main()
{
size_t size1 = ((size_t*)new int[10])[-1]; // doesn't work (pointer on some platforms, allocation size-based number on others)
printf("%zu (0x%zx)\n", size1, size1);
printf("%zu\n", ((size_t*)new bytes10[5])[-1]);
printf("%zu\n", ((size_t*)new bytes10[6])[-1]);
printf("%zu\n", ((size_t*)new bytes10[7])[-1]);
printf("%zu\n", ((size_t*)new bytes10[65536])[-1]);
return 0;
}
Possible output (the first value may differ):
49 (0x31)
5
6
7
65536
P.S. In my view, the C++ committee should consider either standardizing access to the array size for all new[] allocations, or providing a new type of new-like operator that is capable of guaranteeing a size prefix. This has the power to allow certain uses of new[] for lower level code (e.g. much easier single-pointer immutable strings).

How to get size c++ dynamic array

I'm studying C++ and I need to create structure Airplane and work with it.
My structure Airplane.h
#include "stdafx.h"
using namespace std;
struct Airplane {
string destination;
int number;
string type;
};
and it's my code
#include "stdafx.h"
#include "Airplane.h"
string SetDestination(int n);
string SetType(int n);
void PrintAirplaneList(Airplane * &airplaneList, int n, string title);
void SortByDestination (Airplane *&airplaneList, int n);
void FindAirplanesAndPrint(Airplane *&airplaneList, int n, string type);
int _tmain(int argc, _TCHAR* argv[])
{
using namespace std;
srand((unsigned)time(NULL));
int n;
cout << "Input n = ";
cin >> n;
Airplane * airplaneList = new Airplane[n];
for (int i = 0; i < n; ++i)
{
airplaneList[i].destination = SetDestination(rand()%5);
airplaneList[i].number = rand()%9001 + 1000;
airplaneList[i].type = SetType(rand()%3);
}
PrintAirplaneList(airplaneList, n, "List:");
SortByDestination (airplaneList, n);
PrintAirplaneList(airplaneList, n, "Sorted list (by destination):");
string type;
cout << "Input type: ";
getline(cin, type);
FindAirplanesAndPrint(airplaneList, n, type);
delete [] airplaneList;
system("PAUSE");
return 0;
}
string SetDestination (int n)
{
string destination;
switch(n){
case 0: destination = "Tokio"; break;
case 1: destination = "Amsterdam"; break;
case 2: destination = "Moscow"; break;
case 3: destination = "Philadelphia"; break;
case 4: destination = "San Diego"; break;
default: destination = "Unknown city"; break;
}
return destination;
}
string SetType (int n)
{
string type;
switch(n){
case 0: type = "passenger"; break;
case 1: type = "cargo"; break;
case 2: type = "post"; break;
default: type = "unknown type"; break;
}
return type;
}
void PrintAirplaneList(Airplane *&airplaneList, int n, string title)
{
cout << "\n";
cout << title << "\n\n";
for (int i = 0; i < n; ++i)
{
cout << "Destination: " << airplaneList[i].destination << "\n";
cout << "Number: " << airplaneList[i].number << "\n";
cout << "Type: " << airplaneList[i].type << "\n\n";
}
}
void SortByDestination (Airplane *&airplaneList, int n)
{
for (int i = 0; i < n - 1; ++i)
{
for (int j = 0; j < n -1; ++j)
{
if(airplaneList[j + 1].destination > airplaneList[j].destination) continue;
Airplane tempAirplane = airplaneList[j];
airplaneList[j] = airplaneList[j + 1];
airplaneList[j + 1] = tempAirplane;
}
}
}
void FindAirplanesAndPrint(Airplane *&airplaneList, int n, string type) {
cout << "Type - " << type << "\n";
int count = 0;
for (int i = 0; i < n; ++i)
{
if (airplaneList[i].type == type)
{
cout << "Destination: " << airplaneList[i].destination << "\n";
cout << "Number: " << airplaneList[i].number << "\n";
++count;
}
}
if (count == 0)
{
cout << "Not found\n";
}
}
I have two questions.
1. I can't input type in
string type;
cout << "Input type: ";
getline(cin, type);
FindAirplanesAndPrint(airplaneList, n, type);
and my function FindAirplanesAndPrint starts to work without any value for type. How to make my programm to get value?
2. How to get size of dynamic array in functions? Because it seems the passing size of array n in every function is the wrong way.
"How to get size of dynamic array in functions? Because it seems the passing size of array n in every function is the wrong way."
Yet it is the only way when you use dynamically allocated C-style array.
If you want to avoid sending the size explicitly then pass some object that wraps this raw memory buffer and provides other means of retrieving the size. The most reasonable solution here would be using std::vector<Airplane>.
1) Ommiting the irrelevant, this is basically what you got:
cin >> n;
getline(cin, type);
operator>> leaves a new-line character in the input buffer and that's the first character that getline sees. Since '\n' is the default line delimiter, you get an empty line. To fix it call cin.ignore() before you call getline to discard the '\n'.
2) If you wish to stick with raw pointers, passing the size as a parameter is your only choice. Switch to std::vector and you get size() method that you can query at any time.
The problem with entering type is that the input buffer contains the new line character after entering n. You should use member function ignore to clear the buffer before using function getline.
As for your second question then in general you should track the size of a dynamically allocated array yourself. Or you can set the last element of the array as NULL and use it as a sentinel.
you could probably make a dynamic array with 0 items, make an int counter, make a while loop with getline as a statement, while (getline(cin, string_var) != SomeText) /* SomeText = some kind of text so the user show you there are not going to be any more inputs*/, what you were going to do it in the for do it in the while and at the end of the while increase the counter by one, i++. And about the access to the array, if your dynamic array has 0 items, then SomeDynamicArray[1].something = SomeValue will just add a second item to the array and the "something" of that item will be equal to SomeValue.
type *ArrayPointer = new type[0];
string StringVar;
int i = 0;
while (getline(cin, StringVar) != "Text that show there are not going to be any more inputs") {
/*code*/
i++;
}
idk if it will work on your case, but try it if you want. Also, about everyone saying about vectors, as I know at least, vectors are slower and spend more memory, bcs they double there size instead of just increasing it every time needed. I hope I will be some help.
One approach that i use when i work with dynamic arrays, is to pass the array as a reference to the function. This will help you to keep the size information of the array.
For Example:
string list1[3] = {
"item1",
"item2",
"item3"
};
string list2[2] = {
"item1",
"item2"
};
template<typename T, size_t N>
void PrintItems(T(&items)[N]) {
for (int i = 0; i < N; i++) {
cout << items[i] << endl;
}
}
int main() {
PrintItems(list1);
PrintItems(list2);
}
In the previous example, N stores the correct size information for the array. More information here
You cannot portalby find out the size of a dynamically allocated array in C++.
This is actually not entirely correct. There is widespread support for a particular kind of size retrieval - the size of an array of objects with destructors.
To anyone considering using this however - I have to warn you that to my knowledge, this is not in any way guaranteed by any standard or compiler vendor. It may change at any point in time and should not be relied upon for anything other than hobby projects.
The size of the array of destructible objects is stored right before the objects themselves, and can be accessed with a basic pointer cast: ((size_t*)mem)[-1].
When you think about it - when you call delete [], you are not passing the size of the array, so C++ must store the exact size somehow to know how many objects to call the destructor on, in a way that can be trivially and efficiently accessed from the pointer itself. However - there is no guarantee that it has to be the number of elements - it can also be the number of bytes or the end pointer, possibly with some flag bits mixed in. That said, once they've decided on a convention, it would likely break some kind of backwards compatibility to change it later.
For those interested to test this, here's the code: https://ideone.com/Z0Sta1
#include <stdio.h>
struct bytes10
{
~bytes10() { printf("dtor %p", this); }
char _[10]; // to test whether the size or the count is returned
};
int main()
{
size_t size1 = ((size_t*)new int[10])[-1]; // doesn't work (pointer on some platforms, allocation size-based number on others)
printf("%zu (0x%zx)\n", size1, size1);
printf("%zu\n", ((size_t*)new bytes10[5])[-1]);
printf("%zu\n", ((size_t*)new bytes10[6])[-1]);
printf("%zu\n", ((size_t*)new bytes10[7])[-1]);
printf("%zu\n", ((size_t*)new bytes10[65536])[-1]);
return 0;
}
Possible output (the first value may differ):
49 (0x31)
5
6
7
65536
P.S. In my view, the C++ committee should consider either standardizing access to the array size for all new[] allocations, or providing a new type of new-like operator that is capable of guaranteeing a size prefix. This has the power to allow certain uses of new[] for lower level code (e.g. much easier single-pointer immutable strings).