C++ Class, Assigning values during Constructor initialization - c++

I have a 2D array which I declared part of the classes private members. When I call the constructor, I start assigning values to the 2D array. But every time I do so, I'm hit with an error C2059. To make sure nothing else was causing that error I commented out that line and the compiler finished putting together a binary file.
tried:
Variable[row] = { 0, 1, 2, 3};
Variable[row][] = { 0, 1, 2, 3};
Variable[row][4] = { 0, 1, 2, 3};
No luck, any clues. Thanks in advance.

This syntax is only to be used for the creation of the object.
int array[4] = {1, 2, 3, 4};
Once the array is created, you have to use a loop to assign values to it.
Here's a short example :
class A
{
int array[4];
public:
A()
{
// Here, array is already created
// You can _assign_ values to it
}
};
If you want to give it values when it's instantiated in the constructor, the only way is to use initialization lists. Unfortunatly, you can't do this with a static array.
See this this thread.

Unfortunately, we can't yet properly initialize arrays that are members of classes. I don't know exactly how yours is declared, but here's an example of what to do:
class X
{
int Variable[3][4];
public:
X()
{
const int temp[][4] = { { 1, 2, 3, 4}, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
const int sz = sizeof(Variable)/sizeof(**Variable);
std::copy(*temp, (*temp) + sz, *Variable);
}
};

Since your question is not clear enough, all I can do is demonstrating a simple example.
2D array is initialized as,
//you may "optionally" provide the size of first dimension
int arr[][4] = {
{1,2,3,4},
{11,12,13,14},
{21,22,23,24}
};
And is acessed as,
for ( int i = 0 ; i < 3 ; ++i )
{
for ( int j = 0 ; j < 4 ; ++j )
{
cout << arr[i][j] << endl;
}
}
Online demonstration at ideone : http://www.ideone.com/KmwOg
Are you doing similarly?

Related

I am getting this error while sorting 0,1 and 2 in array - Runtime Error Time Limit Exceeded Your program took more time than expected

class Solution
{
public:
void sort012(int a[], int n)
{
// code here
int low = 0;
int high = n-1;
int mid = 0;
while(mid<high)
{
int high = n-1;
if(a[mid]==0 && mid<=high)
{ swap(a[mid++],a[low++]);
}
else if(a[mid]==2 && mid<=high)
{ swap(a[mid],a[high--]);
}
else if(a[mid]==1 && mid<=high)
{
mid++;
}
}
}
};
Problem number one is you are redefining the int high = n - 1 inside of the while loop, at each iteration it's reset to this value, so high-- has no effect, and you're getting inside an infinite loop.
Problem number two is that potentially if you pass an array a which has a single value that is not a 0, 1 or 2, you are 100% getting into an infinite loop as well.
Check out this compiler explorer link for an interactive demo: https://godbolt.org/z/EbKPqrxz4
For what it's worth, you program looks like bad C instead of being C++. Non exhaustive list of issues:
The sort012 is an instance method on a class while it doesn't use the instance state. It's probably better as a free function, or at worse a static method on that class.
You're using C arrays.
As a result, you're also not using the algorithms provided by the STL.
I'm assuming this is a kind of coding exercise, but anyways, for the sake of completeness you could achieve the same thing (and more, it'd work with several containers, and regardless of your values/types) with fewer lines of code with this (Compiler Explorer):
#include <fmt/format.h>
#include <algorithm>
#include <array>
int main() {
std::array<int, 10> a{1, 2, 0, 1, 2, 1, 2, 1, 0, 2};
// Could also be a vector: `std::vector<int> a{1, 2, 0, 1, 2, 1, 2, 1, 0, 2};`
std::sort(a.begin(), a.end());
fmt::print("sorted a=");
for (auto x: a) {
fmt::print("{}, ", x);
}
}

How do I measure the length of an int array in C++?

My goal is to print all elements of an array of integers regardless of its length. I would like to print it in Python list format, but then I got this error.
Here is my code
int measure(int n[])
{
int num=0;
while (n[num]) { num++; }
return num;
}
void show(int n[])
{
int a = measure(n);
for (int i=0; i<a; i++) {
if (i==0) { printf("[%d,",n[i]); }
else if (i==a-1) { printf(" %d]",n[i]); }
else { printf(" %d,",n[i]); }
}
}
int main(void)
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
show(arr);
}
It is supposed to print this: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
but I got this instead: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1935094528, -1664206169]
then I replace show() with this:
int i=0;
while (n[i]) {
if (i==0) { printf("[%d,",n[i]); i++; }
else if (n[i+1] == NULL) { printf(" %d]",n[i]); break; }
else { printf(" %d,",n[i]); i++; }
}
and then I got these:
main.cpp:23:28: warning: NULL used in arithmetic [-Wpointer-arith]
23 | else if (n[i+1] == NULL) { printf(" %d]",n[i]); break; }
| ^~~~
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -680101376, -1228044632]
Why does this happen?
How do I measure the length of an int array in C++?
You can use std::size to get the size of an array with known size:
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
std::cout << std::size(arr);
Why does this happen?
Because the continue condition for your loop is "while the element is not 0". There are no elements with the value 0, so the loop doesn't end before exceeding the end of the array, at which point your overflow the array and the behaviour of the program becomes undefined.
The parameter n of the functions measure and show is not an array of known size. Since n isn't an array of known size, you cannot use std::size to get its size. In fact, although it looks like an array of unspecified size, n is adjusted to be a pointer to element of such array. There is no general way to measure the size of an array given a pointer to its element.
In cases where you want to pass array of any size into a function, and also need to know the size of the array within the function, a good solution is to use a span parameter:
void show(std::span<int> n)
There simply is no "measuring" the length of arrays in C++. You have to know up front, and pass that info to any functions or methods you pass the array to. You can also use a specific "tag" value (as you have implicitly done here) but if you do that, you have to set the tag yourself, and that means you have to know the array length to set the tag. And you must be very sure that the tag does not equal any valid data value in your array.A different approach would be to use std::vector instead of an array. That data type gives you all the functionality of an array but also provides variable length arrays and the ability to inquire the current length.

C++ Initializing a 2D array of structs

I'm writing a program that allows the user to play sudoku puzzles. Each puzzle is a 2d array of structs, but I'm unable to intialize the array in one go. Is there any way to do this without needing to intialize each part of the structure for each element of the array? Here is some of my code.
class Sudoku {
protected:
struct Puzz {
int Ans;
// IsClue is used further in the program so the user cannot change the clues given.
bool IsClue;
};
Puzz Puzzle[9][9]; // I chose a 2D array so represent the 9 rows and columns of a sudoku puzzle
};
I've tried some of the following:
Puzzle[][9] = {{0, false, 8, true, 0, false, 6, true, 7, true, 0, false, 0, false, 0, false, 0, false}, //...etc, going on for each row
Puzzle[9][9] = // etc, etc, but I get an error saying "Expected an expression
Is the only way to initialize each element to do
Puzzle[x][y].Ans = x; Puzzle[x][y].IsClue = true/false;?
The problem is that you try to assign to an array, and it's simply not possible. You need to actually initialize it, which is something completely different.
If you don't mind writing lot of lines that are almost the same, then you could use a constructor member initializer list. Like e.g.
Sudoku::Sudoku()
: Puzzle{{...}, {... }, ... }
{}
If only a few structures in the arrays differ from some default values, then you could set all entries in the arrays to the same default value, using e.g. std::fill and then change those few entries that have special values.
Here's an example showing how a 2 x 2 array can be initialized. I'll leave it to you to extend that to a 9 x 9 array.
class Sudoku {
Sudoku();
protected:
struct Puzz {
int Ans;
bool IsClue;
};
Puzz Puzzle[2][2];
};
Sudoku::Sudoku() : Puzzle{{{0, false}, {1, true}}, {{2, false}, {3, true}}}
{
}
Having said that, it might be easier to create a default constructor of Puzz which does the sensible thing for most objects and then modify only a select elements of Puzzle in Sudoku's constructor.
class Sudoku {
Sudoku();
protected:
struct Puzz {
int Ans;
bool IsClue;
Puzz() : Ans(0), IsClue(false) {}
};
Puzz Puzzle[2][2];
};
Sudoku::Sudoku()
{
// Change specific elements of Puzzle
}
You can initialize with an initializer list in c++11 or higher:
Puzz Puzzle[2][2] = {
{ {8, true}, {9, false} },
{ {10, true}, {11, false} }
};
If in a class you can default construct it the same way:
class PuzzHolder {
PuzzHolder() : Puzzle{
{ {8, true}, {9, false} },
{ {10, true}, {11, false} }
} { }
Puzz Puzzle[2][2];
};
Although, if it is very big, this might get pretty messy. So the final approach could be to initialize it in a loop.
Live example.
To initialize a two-dimensional array, use a for-loop. As in:
for (int i = 0; i < row_count; i++) {
for (int j = 0; j < col_count; j++) {
item[i][j] = initial_value;
}
}
If you want to use an initializer list like in the above, you can do so by simply wrapping each instance of the struct in brackets. However, initializing your sodoku board with a literal is not a particularly scalable approach to generating a sodoku board for the player. That is, instead of:
Puzzle puzz[9][9] = {{0, false, 8, true, 0, false, 6, true, 7, true, 0, false, 0, false, 0, false, 0, false, ...}};
You would use:
Puzzle puzz[9][9] = {
{ // First row
{0, false}, // first column
{8, true}, // second column
...
},
{ // Second row
...
},
...
};
Since this is C++, though, you may wish to consider representing your board using nested vectors (that is vector<vector<Cell>>). While this may be overkill, especially for a Sodoku board (especially if it is always 9x9), that will allow you to more easily represent non-standard board sizes, and the vector data structure comes with the ability to default initialize/fill all members with a pre-specifed value. As #paddy aptly notes in the comments, however, there are also other functions (like std::fill that can be used with ordinary arrays to handle common use cases.

C++ for_each() and the function pointer

I am try to make the myFunction give me a sum of the values in the array, but I know I can not use a return value, and when I run my program with the code as so all I get is a print out of the values and no sum why is that?
void myFunction (int i) {
int total = 0;
total += i;
cout << total;
}
int main() {
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for_each( array, array+10, myFunction);
return 0;
}
You really need a functor to store state between iterations:
struct Sum
{
Sum(int& v): value(v) {}
void operator()(int data) const { value += data;}
int& value;
};
int main()
{
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int total = 0;
std::for_each( array, array+10, Sum(total));
std::cout << total << std::endl;
}
When you declare a variable (i.e. int total) it exists for the duration of its scope (usually equivalent to the nearest surrounding pair of { and }. So, in your function myFunction, total ceases to exist when the function returns. It returns once per call--once per element in your array, that is. In order to actually sum its values (or otherwise preserve a variable beyond the end of myFunction, you must give it a broader scope.
There are two relevant ways to do this. One is a "good" way, and one is an "easier-but-badly-styled" way. The good way involves a functor or context object--#Martin has already posted an example. The "bad" way is marking int total as static. It'll work the first time you use it, if your code is single-threaded... and then never again. If somebody suggests it... don't do it. :)
total is a variable with automatic storage duration. Every time myFunction() is called, a new total is created and initialized to 0. You could:
give total static storage duration (with the static keyword), but you won't be able to assign its value to anything, because it is still local scope. A bad idea if you want to reuse this function, anyhow.
make total a global variable. Also a bad idea if you want to reuse this function
make a "functor", as described in Martin York's answer. This is the most reusable implementation
But, my chosen solution is "you're asking the wrong question" and you should be using std::accumulate():
#include <iostream>
#include <numeric>
int main() {
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int total = std::accumulate(array, array+10, 0);
std::cout << total << '\n';
return 0;
}
Your total is local at each function call. It's initialized with 0 at every iteration. You could just declare it global (or pack into a parameter, etc.)
myFunction is being called each time and total is local to the function... try marking total as static instead:
static int total = 0
You need to make the total persistent across function calls. You also need to access the result separately from adding the intermediate results to it, which rules out (at least straightforward use of) a function at all -- you really need a class instead.
The total is a local variable. It will be destroyed once the myFunction finished processing one data.
The typical way to have a state is to make myFunction a function object (a struct that overloads the () operator).
The dirty way is to make total a global variable.
In your case I'd recommend you use the accumulate function instead (assuming that cout << total is just for debugging).
You reset the value of 'total' to 0 each time you call the function.
Declare it 'static'
void myFunction (int i) {
static int total = 0;
total += i;
cout << total;
}
EDIT:
Alternatively, if you want to access the value of 'total' later, you will need to either use a global variable (of some kind! Could be in a class or functor! don't flame me!), or just use a for loop, and pass it in as a pointer (i.e., not use for_each):
void myFunction (int i, int * p_total) {
//No initialization
*p_total += i;
cout << *p_total;
}
int main() {
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int total = 0;
for(int i = 0; i < 10, i++)
myFunction(array[i], &total);
//total is now 55
return 0;
}
Note: I'm a C programmer trying to learn C++. This is how I would do it (which is very C-like), it might not be the standard C++ way.

What is the easiest way to set the value of an entire array?

My current project requires me to fill an array based upon some other values. I know there's the shortcut:
int arr[4][4] = { {0,0,0,0} , {0,0,0,0} , {0,0,0,0} , {0,0,0,0} };
But in this case, I need to fill the array after its declaration. I currently have my code formatted like this:
int arr[4][4];
if(someothervariable == 1){
arr = { {1,1,1,1},
{1,2,3,4},
{2,,3,4,5},
{3,4,5,6} };
}
But it won't compile. Is there a way to make use of the mentioned shortcut in my case? If not, whats the best fix available? I'd appreciate a way to set it without explicitly assigning each element? ie: arr[0][0] = ...
How about using std::copy() ?
int arr[4][4];
if(someothervariable == 1){
const static int a2[4][4] = { {1,1,1,1},
{1,2,3,4},
{2,3,4,5},
{3,4,5,6} };
std::copy(&a2[0][0], &a2[0][0]+16, &arr[0][0]);
}
No, array initialization syntax is for array initialization. Although, you can use memset if all the values are the same byte.
The boost.assign library adds some interesting syntax for modifying/filling collections, but AFAIK it doesn't support C style arrays (only C++ and Boost containers).
In the current version of C++ language the only way to do it is to copy it from some original
int arr[4][4];
if (someothervariable == 1)
{
const int SOURCE[4][4] = // make it `static` if you prefer
{
{1, 1, 1, 1},
{1, 2, 3, 4},
{2, 3, 4, 5},
{3, 4, 5, 6}
};
assert(sizeof arr == sizeof SOURCE); // static assert is more appropriate
memcpy(&arr, &SOURCE, sizeof arr);
}
The source "constant" can be declared as static in order to avoid re-initialization, if the compiler is not smart enough to optimize it by itself.
In the future version of the language a feature similar to C's compound literals is planned, which will provide support for immediate initialization (basically what you tried to do in your original post).
If you wish to fill the array with a single value:
#include<algorithm>
#include<vector>
// ...
std::vector<int> arr;
std::fill(arr.begin(), arr.end(), VALUE); // VALUE is an integer
If you wish to calculate the value for each element:
struct get_value {
int operator()() const { /* calculate and return value ... */ }
};
std::generate(arr.begin(), arr.end(), get_value());
If you are setting everything to the same value (such as zero), you may be able to get away with ...
memset (arr, 0, sizeof (arr));
Note that this is fraught with perils. You have to know your type sizes and all that jazz.
However, it appears that that will not suffice for you. If you want to fill the array with different values, I can only only think of two ways of doing this.
Method #1. (Can be a pain the butt)
arr[0][0] = 1;
...
arr[0][3] = 1;
arr[1][0] = 1;
...
arr[1][3] = 4;
arr[2][0] = 2;
...
arr[2][3] = 5;
arr[3][0] = 3;
...
arr[3][3] = 6;
Method #2.
Predefine a set of arrays and switch between them using a pointer;
int arr1[4][4] = {
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0} };
int arr2[4][4] = {
{1,1,1,1},
{1,2,3,4},
{2,,3,4,5},
{3,4,5,6} };
int *arr[4];
Now you only have the four (4) values of *arr[] to set instead of setting everything. Of course, this really only works if your arrays will be filled with predetermined constants.
Hope this helps.
I'm not sure if I like this solution or not, but C/C++ will give you assignment convenience if you wrap the array inside a struct with the minor cost of then having to use the struct name to get at the array:
typedef struct {
int data[4][4];
} info_t;
info_t arr;
if (someothervariable == 1){
static const info_t newdata = {{ // since this is static const, there generally
// won't be a copy - that data will be 'baked'
// into the binary image (or at worst a
// single copy will occur)
{1,1,1,1},
{1,2,3,4},
{2,3,4,5},
{3,4,5,6}
}};
arr = newdata; // easy to assign new data to the array
}
int somethingelse = arr.data[1][2]; // a tiny bit less convenient to get
// to the array data
int arr[4][4];
if (someothervariable == 1) {
int tmp[4][4] = { {1, 1, 1, 1}, {1, 2, 3, 4}, {2, 3, 4, 5}, {3, 4, 5, 6} };
arr = tmp;
}