How to get size of array of vectors? [duplicate] - c++

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

Related

How to return the number of values input into an array?

At the moment, I am stumped and cannot progress on this problem. Any help or guidance would be greatly appreciated. The first part is working, however when I try to return the # of user inputs in the second part I get a Segmentation Fault. Below are the descriptions of both parts::
P2.1 Write a program consisting of main and displayArray functions. The main function declares an integer array with 10 elements and at the same time initializes them with up to 10 arbitrary values. The main function then calls displayArray function to display the contents of the array.
P2.2 Expand P2.1 with an additional fillArray function that prompts the user to enter up to 10 (size of the array) integers. Since a statically allocated array is often partially filled with values less than the actual size or storage capacity of the array (10 in our case), so the fillArray function must return a positive integer value representing the actual # of input values entered by the user.
#include <iostream>
using namespace std;
int displayArray(int arr[]);
int fillArray(int newArray[], int &inputs);
const int size = 10;
int main() {
int x, inputs = 0;
int arr[size] = {0,1,2,3,4,5};
int newArray[] = {};
displayArray(arr);
cout << "Enter .5 when finished. ";
fillArray(newArray, inputs);
cout << inputs;
cin >> x;
return 0;
}
int displayArray(int arr[]) {
for (int i = 0; i < size; i++)
cout << arr[i] << " " << endl;
}
int fillArray(int newArray[], int &inputs) {
for(int i = 0; ; i++) {
cout << "Enter an integer: " << endl;
cin >> newArray[i];
if(newArray[i] == .5) {
inputs = i + 1;
return inputs;
break;
}
}
}
You do not reserve memory for your newArray, since int newArray[] = {} will allocate an array of size 0 (actually not even defined as far as I know). So when calling fillArray, you will exceed array bounds.
Write
int newArray[10] = { 0 }
and it should at least work if you do not enter more than 10 values then.
Further, in fillArray, to not run out of bounds, I'd write...
int fillArray(int newArray[], int &inputs) {
for(inputs = 0; inputs < 10 ; inputs++) {
cout << "Enter an integer: " << endl;
cin >> newArray[i];
if(newArray[i] == 0) {
break;
}
}
inputs++;
return inputs;
}
Note further that the newArray[i] == .5 is at least misleading, since newArray is of type int and .5 is a floating point value. It will never evaluate to true, since the integral value newArray[i] will be converted to a float before comparison, and this conversion will never result in 0.5.

How can I modify the values of an array within a function and then use the "new" array where the function was called

So for part of my homework I need to make a yahtzee style text game. At the moment I am working on an array to hold the dice values. My issue is being able to pass an array into a function to modify values, and then use that modified array again. Initially I wanted to do it with references or pointers. I had issues with doing it that way and I haven't been able to get either way to compile. Today I talked to my teacher who told me that arrays can be modified normally inside of a function and then used again, essentially saying that they are passed by reference automatically.
Can someone please clarify what my teacher means and if it is correct. Also, what method would you guys recommend. Below is my current implementation attempting to use references
/******************************************************
** Function: runGame
** Description: Runs game and keeps track of players
** Parameters: # of players
** Pre-Conditions: c is an integer from 1 to 9
** Post-Conditions:
******************************************************/
void runGame(int players) {
Player p = new Player[players]; //needs to be deleted at the end
int dice[] = { -1, -1, -1, -1, -1 };
int category; // used to hold category chosen
while (isGameOver(p)) {
for (int i = 0; i < players; i++) {
rollDice(dice); //uses reference
p[i].scoreBoard= updateScore(p[i], dice);
p[i].catsLeft--;
}
}
}
/******************************************************
** Function: rollDice
** Description: rolls dice, prints array and either rerolls
** Parameters: int[] dice
** Pre-Conditions:
** Post-Conditions:
******************************************************/
void rollDice(int (&dice) [5]) {
int again;
string indices; // indices of dice to reroll
cout << "Your dice are" << endl;
for (int i = 0; i < 5; i++) {
dice[i] = rand() % (6) + 1;
cout << dice[i];
}
for (int i = 0; i < 2; i++) {
cout << "Roll again? Type anything except 0 to go again." << endl;
cin >> again;
if (again) {
cout << "Type each index without a space that you would like to reroll";
cin.ignore();
getline(cin, indices);
for (int i = 0; i < indices.length(); i++) {
dice[(int)indices[i] - '0'] = rand() % (6) + 1;
}
}
else
break;
}
}
At the moment I am getting compiler errors saying
error: no match for ‘operator[]’ (operand types are ‘Player’ and
‘int’)
p[i].scoreBoard= updateScore(p[i], dice);
And consequent ones for the other times I attempt to use p[i]
What your teacher meant that you can pass an array to another function as a pointer and use this to modify the values inside the array in another function. Use the following example to check the values printed before modifying the array and after modifying it. Note how the array is being passed from main funtion to modifyArray funtion.
#include "stdafx.h"
#include <iostream>
using namespace std;
void modifyArray(int * arr, int len)
{
for (int i = 0; i < len; i++)
{
arr[i] += 1;
}
}
void printArr(int *arr, int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i];
}
cout << endl;
}
int main()
{
int arr[5] = { 1,2,3,4,5 };
cout << "Before :" << endl;
printArr(arr, 5);
modifyArray(arr, 5);
cout << endl << "After : " << endl;
printArr(arr, 5);
return 0;
}
What your teacher means is that if you have a pointer with a buffer integers and with that always hold the values.
Ex:
int* p = new int[5];
This will create an array with 5 slots now everytime you fill it it will always change, there are some things that can be a little bit different if you are doing object oriented but mostly it will be like that. You can use is as a global variable for testing.
The way you can move around it is by writing either p[slot number you want]. This way will make it possible for you to use the array, another way is to return the array with the numbers(instead of having void).

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.

Passing unknown Array to Function by reference (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

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