C++ array initialisation vs assignment - c++

I'm new to C++ and have a question on arrays. I initialise a 2-D array as follows:
int myArray[2][2] = { {1,2},{3,4} };
Is this technique for populating an array valid ONLY for initialisations? If so, why is this?
For example, if I then attempt the following, I get an error:
myArray[2][2] = { {2,4}, {6,8} };
Thanks

Yes, the technique is only used for initialization. When you apply this to assignment, you will get an error.
In
myArray[2][2] = { {2,4}, {6,8} };
myArray[2][2] is just the element of myArray, you can not assign it with that.

When you initialize the array, you are creating a new memory area and setting the values in that memory area.
When assigning you have to set the values one by one, e.g. myArray[1][0] = 6

Did you do
myArray[2][2] = { {2,4}, {6,8} };
or
int myArray[2][2] = { {2,4}, {6,8} };
??
if you tip
myArray[2][2] = { {2,4}, {6,8} };
you will get to the [2][2] case of your array

Related

How to declare a dynamic 2D array in C++

I'm trying to define a dynamic 2D Array in C++ using the following definition:
int foo(string parameter){
const int n = parameter.length();
int* Array = new int[n][n];
return 0;
}
I receive an error that array size in new expression must be constant, can't understand why because Array is supposed to be dynamic.
(someone posted a shorter version of this in the comments while I was writing it).
What you need for a 2D array allocated with new is this:
int foo(string parameter){
const int n = parameter.length();
int* Array = new int[n*n];
return 0;
}
And then access cells with appropriate indexing.
Another solution is to use vector.
int foo(string parameter){
const int n = parameter.length();
vector<vector<int>> Array(n, vector<int>(n));
return 0;
}

How do I set a whole struct to null?

struct zaidejas {
int numeris;
int aiksteleje;
bool penketas;
};
int main(){
zaidejas z[12];
z = {};
}
I get an error in the line of z = {}:
error: assigning to an array from an initializer list
I have no idea how to fix the error. I would really appreciate any help.
You can't assign to an array, only initialize it when you define it, or copy to it once it have been defined.
I recommend initialization:
zaidejas z[12] = {};
In C++11, you can initialize the array as follows:
zaidejas z[12]{};
If you want to initialize a single element of your array, you can use:
z[0] = zaidejas{};
This is the aggregate equivalent of the (constructor-based) initialization that was available in earlier versions of C++
z[0] = zaidejas();
You should just write
zaidejas z[12] = {};
// ^^^^
This will value-initialize all the array elements, which in turn will zero-initialize each element's class data members.
How do I set a whole struct to null?
Like this:
zaidejas z = {};
For your array, you should do:
zaidejas z[12] = {};
You have 12 elements. If you want to set all of them to null, do something like this
int main(){
int number_elements = 12;
zaidejas z[number_elements ];
for (int i = 0; i < number_elements ; z++) z[i] = {}
}

Choose at runtime array or vector in C++

I have a problem described as below ::
class datad {
private:
int *a;
int _size;
vector<int> v;
public:
datad(int arr[], int size) {
_size = size;
for (int i = 0; i < size; i++)
a[i] = arr[i];
}
datad(vector<int> ve)
{
v = ve;
_size = ve.size();
}
void printdata()
{
// print data which the object has been initialized with
// if object is initialized with vector then print vector
// array print array
}
};
int main()
{
// print only vector data
int a[] = { 9,4,8,3,1,6,5 };
datad d(v1);
d.printdata();
// print only array data
datad d1(a, 7);
d1.printdata();
}
I need to find the way the object is initialized and then based on the same should be able to printdata accrodingly.
Can someone help me understand if it is possible at all?
Add a bool usesVector to your class and set it to true or false in each constructor as appropriate. Then, in printdata, simply check the value of the boolean.
Or you can set size to -1 in the vector case (as it's otherwise unused) and just check for that.
By the way, your array implementation is broken, because you never allocate any memory for it. You'd be much better off using only the vector version. You can still initialise that vector from array data if you wish.
You can set a flag in respective constructor and check that flag during the printing method.
I hope this is for learning purposes, otherwise as noted you maybe better of using just the vector version. When using dynamic memory management in class you need to be aware of things like rule of three and I guess there is also rule of five.

How to initialize string array in Classes?

how to initialize this string array consisting for four elements. Like i know how to initialize but i don't know Where?? I mean where in the classes. Its giving me error in the constructor. Help needed.
class Water :public Element
{
public:
Water () { }
Water(string n): Element (n)
{
water = n;
i=-1;
//Error Message: expected an expression
Elements [4] = {"Steam", "Mud", "Sea", "Rain"};
}
string water;
int i;
bool elementexists;
string Elements [4];//how to initialize this and where?
};
You can initialize it in constructor initialization list:
Water(string n)
: Element(n)
, water(n)
, i(-1)
, Elements{"Steam", "Mud", "Sea", "Rain"} // <- Note the curly braces here.
{}
Raw (C style) arrays cannot be assigned directly using assignment operator (=). An std::array<string, 4> Elements could be assigned, but the syntax would be Elements = {"Steam", "Mud", "Sea", "Rain"}.
It is important to note that this line:
Elements [4] = {"Steam", "Mud", "Sea", "Rain"};
does not mean 'assign these strings to the 4-element long array, Elements'. Elements [4] refers to a specific item in that array. Given that Elements is only 4 items long, attempting to write to the fifth item would be bad. To refer to the array as a whole (as you would do for modifying the whole array at once), just use Elements.
Now, plain old C-style arrays don't support initialising in quite the way you're trying to do there.
I'd recommend using a std::array... they are somewhat easier to work with than C-style arrays as you are using. If you might have different numbers of elements, you should use std::vector instead.
class Water :public Element
{
public:
Water () { }
Water(std::string n): Element (n)
{
water = n;
i=-1;
elements = {{"Steam", "Mud", "Sea", "Rain"}};
}
std::string water;
int i;
bool elementexists;
std::array<std::string, 4> elements;
};
or alternatively,
Water(std::string n): Element(n), elements{{"Steam", "Mud", "Sea", "Rain"}}
{
water = n;
i=-1;
}
Note the double braces around the array initialisers; they're required for std::array by some older compilers. Newer ones may work just fine with a single set, {"Steam", "Mud", "Sea", "Rain"}.
Elements[0] = "Steam";
Elements[1] = "Mud";
Elements[2] = "Sea";
Elements[3] = "Rain";
should be the easiest way.

C++ How to return an array from a function?

I'm brand new to C++ and am having trouble trying to get a function (which takes an array) to return an array. The function is a very basic sorting algorithm for an array of integers of size 4. What i have is below:
int[] sortArrayAscending(int arrayToSort[3]) {
int sortedArray[3];
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
I think i'm getting really confused with the syntax i need to use (the function calls to min, lower, higher, max all work fine.
I would really appreciate some help.
Thank you
EDIT2: Thank you for all the comments. I have now solved it thanks to #Rook's and #Bob Yoplait's answers. The code is used is:
int* sortArrayAscending(int arrayToSort[4], int sortedArray[4]) {
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
int _tmain(int argc, _TCHAR* argv[])
{
int testNumbers[4] = {8,14,1,27};
int testSorted[4];
sortArrayAscending(testNumbers,testSorted);
for (int i = 0; i < 4; i++) {
cout << testSorted[i] << endl;
}
system("pause");
return 0;
}
Thank you for all your help - now time to lookup vectors!
PS I appreciate #Luchian Grigore's solution is most likely the best practise way of doing things, but that wasn't specifically my question
Me, I'd probably use std::array<int, 4> if I was using a modern C++ compiler. Deals nicely with bounds checking and memory management and returning from/passing into functions. You can also use existing STL sort mechanisms and functions upon it; no need to reinvent the wheel!
Now, in your case,
int sortedArray[3];
is a local variable and you should never return a reference to it directly. You could do something like :
int* sortedArray = new int[4];
// do stuff
return sortedArray;
(also note the size of the array, 4, not 3 in your case!) but in this case you have to remember to delete the array at some point in the future or your application will leak memory.
You can also pass in the array by reference, using an approach like
void sort_array(std::array<int, 4>& the_array);
or
void sort_array(int** the_array)
and in these cases you can modify the array in place, or copy the answer into the argument when you're done sorting.
EDIT: After your edit, you, your function returns a pointer to an array. Should work.
You can either return a pointer or a std::vector.
Note that in your code, you'd be running into undefined behavior, because sortedArray goes out of scope at the end of the method, and the memory is freed.
I'd do this instead:
std::vector<int> sortArrayAscending(int arrayToSort[4]) {
std::vector<int> sortedArray(4);
sortedArray.push_back( minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]));
sortedArray.push_back( lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]));
sortedArray.push_back( higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]));
sortedArray.push_back( maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]));
return sortedArray;
}
Actually, I wouldn't. I'd just use std::sort instead of creating my own function, but that's just me.
As this is C++, suggest using a std::vector<int> instead:
std::vector<int> sortArrayAscending(int arrayToSort[3]) {
std::vector<int> sortedArray(4); // Note 4, not 3.
sortedArray[0] = ...;
sortedArray[1] = ...;
sortedArray[2] = ...;
sortedArray[3] = ...;
return sortedArray;
}
Note there are several algorithms already available that will perform some of the tasks that you appear to be performing:
max_element()
min_element()
You are returning pointer to local variable, which leads to undefined behavior. sortedArray is statically allocated array with automatic storage duration, which means that memory where it resides is being freed once you leave the scope of the function.
You should allocate it dynamically by using new[] or even better: use std::vector instead. If you choose to allocate it by using new[], don't forget to free it by calling delete[] when you don't need this memory anymore.
Also note that int sortedArray[3]; declares an array of size of 3 elements indexed from 0 to 2. If you access 4th element of the array whose size is 3 (if you access the memory "past the last element of the array object"), the behavior is undefined as well.
Use Boost::Array (or std::array in C+11) that provides proper value semantic to C array.
boost::array<int,4> sortArrayAscending(boost::array<int,4>7 arrayToSort)
{
boost::array<int,4> sortedArray;
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
It is not like in Java
Either you pass sortedArray as a parameter to the func
int* sortArrayAscending(int* arrayToSort, int* sortedArray) {
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
void toto() {
int array[4]; // and fill values...
int sortedArray[4];
sortArrayAscending(array, sortedArray);
}
or
int* sortArrayAscending(int* arrayToSort) {
int* sortedArray = new int[4];
sortedArray[0] = minOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[1] = lowerMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[2] = higherMidOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
sortedArray[3] = maxOfFour(arrayToSort[0],arrayToSort[1],arrayToSort[2],arrayToSort[3]);
return sortedArray;
}
and then you need to delete the returned array in the second case.
Arrays are always passed by reference to any function in C++.
So, just pass your array to the function. Your original array would get sorted and you can then use it in your program. I believe there is no need to return the array explicitly.