I know the no.of nodes of a graph. I want to assign labels the nodes of graph as A,B,C,D. If I have 5 nodes, label it as A,B,C,D,E. If I have 6 nodes, label it as A,B,C,D,E,F. Can you suggest any dynamic method for this?
enum nodes { A, B, C, D, E };
char name[] = "ABCDE";
You question is not clear at all - I don't understand why you need boost or what you're trying to do. That said, let's assume that:
You have an enum of node types A..Z.
You need a way to convert the enum value to a string representation at run-time.
gcc.godbolt.org example.
#include <cstddef>
// Use `enum class` for additional safety.
// Explictly specify the underyling type as we're going to use the
// enum values to access an array.
enum class nodes : std::size_t { A = 0, B, C, D, E, /* ... */ };
// `constexpr` allows this function to work both at run-time and
// compile-time.
constexpr auto get_char_for(nodes n) noexcept
{
// Represent the alphabet as a `constexpr` C-style string.
constexpr const char* letters = "ABCDEFGHIJKLMNOPQRSTUWXYZ";
// Access and return the alphabet letter at position `n`.
return letters[static_cast<std::size_t>(n)];
}
static_assert(get_char_for(nodes::A) == 'A');
Related
I want to make an Array with 3 differnt definitions. More specifically i want an array like this : A[i,j]=(string, int, bool
string, int, bool)
I am trying to make a template but i am confused.
If you want to use templates you can make an array of structs:
template <class A, class B, class C>
struct Vars{
A a;
B b;
C c;
};
//declaring the types of the template you want to use
Vars <std::string, int, bool> *ray;
//initializing array in heap
ray = new Vars<std::string, int, bool>[SIZE];
Alternatively, If you have decided you always want to use this combination you can much more easily do this:
struct Vars{
std::string a;
int b;
bool c;
};
Vars *ray = new Vars[SIZE];
You can make a regular class that implements this behavior.
Something like this:
class specialArray {
char *** strings;
int **integers;
bool **booleans;
public:
specialArray(int rows, int columns, unsigned char data[]) {
//initialize arrays to correct sizes
/*add a special values, such as 253, 254, 255 (which are not
used for chars, bools, or strings (since the operating system
takes control of memory locations 253, 254, 255)) every time the
type of the array changes*/
/*Use the special values to determine which array each byte of
information should go to (and use casts). Arrays which are not
filled at each index should be set to 0 at that position*/
/*create a function access(int loc) to obtain a value. In this
function, check each of the three arrays until one of the arrays
at that index value is not 0. Return a byte array.*/
/*Implementing this in c++ is extremely inefficient, by the
way as you can see by the enormous amount of code this
requires*/
}
//do something similar for operator=()
}
If I understand you correctly, arrays -AFAIK- can have only one datatype. However you can use struct/classes pair two different types then make a one dimensional array out of it.
Check this code illustration, and check if it is what you are looking for.
template<typename T, typename U>
struct MyArray
{
T a;
U b;
};
int main()
{
MyArray<int,bool> arr[2];
arr[0] = {30,1};
cout << arr[0].a;
cout << " : ";
cout << arr[0].b;
}
You may also use pair, tuples and/or vectors... etc. It all depends on your vision and needs.
My name is Michael, 13 years, and I began to do C++ programming recently.
I have a book with following exercise:
Create a class myArray that solves the overflow problem when
handling arrays. In addition, this new class will allow a user to
provide any integer (positive or negative) as the first index of the
table. Each object type myArray contains an array of any type noted
Type. When running, accessing an element of an array of type myArray, if there is buffer overflow (that is, if the index used
exceeds the size of the table in question) the program must end with an appropriate error message.
Let the following instruction:
myArray<int> tabInt(5); // (1)
myArray<double> tabDouble(2, 13); // (2)
myArray<char> tabChar(-5, 9); // (3)
The instruction (1) states tabInt as an array of 5 elements of type int : tabInt [0], tabInt [1], ..., tabInt [4]. The instruction (2) states tabDouble as an array of 11 elements of type Double: tabDouble [2], tabDouble [3], ..., tabDouble [12]. The instruction (3) states tabChar as an array of 14 elements of type char : tabChar [-5], tabChar [-4], ..., tabChar [8].
Note the use of patrons of classes for the table represented by the myArray class can be of any type. For this, you must use the following notation when declaring the class myArray:
template <class Type>
class myArray{
private:
Type * Ptr; //pointor on the array
int upperbound;
int lowerbound;
// Following declaration's class
}; // I must use this starting structure.
Furthermore, you will overload (overloading) the following operators in the class myArray : [], == and !=.
My question:
I have difficulties creating these variables tabInt() , tabDouble(), tabChar(), etc. Does someone could help me or just give me a good hint?
They aren't functions, they're objects. You are creating an instance of your array<> class, exactly as given in your instructions.
array<int> foo(5); // create foo[]
foo[2] = 12; // works fine
foo[5] = 99; // complains?
Your instructions were truncated, so I don't know what your code is supposed to do if you try to access an element out of range.
Er... okay, fine. Here's more help:
Your array<> class should have two constructors:
template <typename T>
struct array
{
array( int max_value ): _min_value(0), _max_value(max_value) { }
array( int min_value, int max_value ): _min_value(min_value), _max_value(max_value) { }
private:
int _min_value;
int _max_value;
};
I first initially learnt to program in Java and therefore when working with enums, I could use .values() in order to produce an array of all the values in that specific enum. I've noticed that now learning C++, there is not an equivalent method.
What is the best way to tackle this as I'm sure people have come up with decent workarounds?
Doing this in C++ usually requires a special sentinel value inside the enumeration or some preprocessor magic.
If your enumerators are sequential then you can use a simple sentinel value (end in this case):
enum my_enum {
a,
b,
c,
my_enum_end,
};
for (int i = 0; my_enum_end != i; ++i) {
// Loop through all of the enum values.
}
When the enumeration is more complicated and there are gaps between each of the enumerators then you can use the preprocessor:
#define ENUMS(F) F(a, 1) F(b, 5) F(c, 10)
#define AS_ENUM(ID, V) ID = V,
#define AS_VALUE(ID, V) V,
#define AS_ID(ID, V) #ID,
enum my_enum {
ENUMS(AS_ENUM)
};
my_enum const my_enum_values[] = {ENUMS(AS_VALUE)};
std::string const my_enum_keys[] = {ENUMS(AS_ID)};
for (my_enum const i : my_enum_values) {
// Loop through all of the enum values.
}
for (auto const& i : my_enum_keys) {
// Loop through all of the enum keys.
}
Here all of the enumerators are specified in the ENUMS macro rather than inside the enum definition directly.
I have an enum type with a last item 'num_of_types'. (that is, it will be 15, in example)
I'like to have a static array_of_types[num_of_types], to easily count the number of each type I create.
My idea is to have: array_of_types[the_type]++;
But, I have no idea to declare and initialize this static array?
Is this what you want?
enum MyEnum
{
Type1=0,
Type2,
Type3,
NumTypes
};
// initialize the entire array with 0
unsigned countArray[NumTypes]={0};
After you declared that array you can use it as you mentioned:
countArray[type]++;
Is this what you are looking for?
static TYPE staticArray[] = {
VAL1,
VAL2,
...
VALN
};
or
static TYPE staticArray[MAX_ELEMS];
in case you do not want to initialize the elements when you allocate the array.
What you cannot do at the same time is both specifying the number of elements and providing and initialization list.
You use it just like normal:
enum E
{
A,
N
};
int main()
{
int a[N];
// Use 'a'...
}
In the above example, the variable a is defined as an array of integers, with the size N.
You can do it this way:
enum Types { TYP_1, TYP_2, /*...*/ num_of_types};
class A {
/*...*/
static int array_of_types[num_of_types];
};
int A::array_of_types[num_of_types];
This way you will create an array filled with default values for the array data type (which is zero for int).
Here is what I am using:
class something
{
char flags[26][80];
} a;
std::fill(&a.flags[0][0], &a.flags[0][0] + 26 * 80, 0);
(Update: I should have made it clear earlier that I am using this inside a class.)
The simple way to initialize to 0 the array is in the definition:
char flags[26][80] = {};
If you want to use std::fill, or you want to reset the array, I find this a little better:
char flags[26][80];
std::fill( &flags[0][0], &flags[0][0] + sizeof(flags) /* / sizeof(flags[0][0]) */, 0 );
The fill expressed in terms of the array size will allow you to change the dimensions and keep the fill untouched. The sizeof(flags[0][0]) is 1 in your case (sizeof(char)==1), but you might want to leave it there in case you want to change the type at any point.
In this particular case (array of flags --integral type) I could even consider using memset even if it is the least safe alternative (this will break if the array type is changed to a non-pod type):
memset( &flags[0][0], 0, sizeof(flags) );
Note that in all three cases, the array sizes are typed only once, and the compiler deduces the rest. That is a little safer as it leaves less room for programmer errors (change the size in one place, forget it in the others).
EDIT: You have updated the code, and as it is it won't compile as the array is private and you are trying to initialize it externally. Depending on whether your class is actually an aggregate (and want to keep it as such) or whether you want to add a constructor to the class you can use different approaches.
const std::size_t rows = 26;
const std::size_t cols = 80;
struct Aggregate {
char array[rows][cols];
};
class Constructor {
public:
Constructor() {
std::fill( &array[0][0], &array[rows][0], 0 ); // [1]
// memset( array, 0, sizeof(array) );
}
private:
char array[rows][cols];
};
int main() {
Aggregate a = {};
Constructor b;
}
Even if the array is meant to be public, using a constructor might be a better approach as it will guarantee that the array is properly initialized in all instances of the class, while the external initialization depends on user code not forgetting to set the initial values.
[1] As #Oli Charlesworth mentioned in a comment, using constants is a different solution to the problem of having to state (and keep in synch) the sizes in more than one place. I have used that approach here with a yet different combination: a pointer to the first byte outside of the bidimensional array can be obtained by requesting the address of the first column one row beyond the bidimensional array. I have used this approach just to show that it can be done, but it is not any better than others like &array[0][0]+(rows*cols)
What is the safe way to fill multidimensional array using std::fill?
The easy default initialization would be using braced inilization.
char flags[26][80]{};
The above will initialize all the elements in the flags to default char.
2-D Array filling using std::fill or std::fill_n
However, in order to provide different value to initialize the above is not enough. The options are std::fill and std::fill_n. (Assuming that the array flags is public in your class)
std::fill(
&a.flags[0][0],
&a.flags[0][0] + sizeof(a.flags) / sizeof(a.flags[0][0]),
'0');
// or using `std::fill_n`
// std::fill_n(&a.flags[0][0], sizeof(a.flags) / sizeof(a.flags[0][0]), '1');
To generalize this for any 2d-array of any type with any initializing value, I would suggest a templated function as follows. This will also avoid the sizeof calculation of the total elements in the array.
#include <algorithm> // std::fill_n, std::fill
#include <cstddef> // std::size_t
template<typename Type, std::size_t M, std::size_t N>
constexpr void fill_2D_array(Type(&arr2D)[M][N], const Type val = Type{}) noexcept
{
std::fill_n(&arr2D[0][0], M * N, val);
// or using std::fill
// std::fill(&arr2D[0][0], &arr2D[0][0] + (M * N ), val);
}
Now you can initialize your flags like
fill_2D_array(a.flags, '0'); // flags should be `public` in your class!
(See Live Online)
3-D Array filling using std::fill or std::fill_n
Adding one more non-template size parameter to the above template function, this can be brought to 3d-arrays as well
#include <algorithm> // std::fill_n
#include <cstddef> // std::size_t
template<typename Type, std::size_t M, std::size_t N, std::size_t O>
constexpr void fill_3D_array(Type(&arr3D)[M][N][O], const Type val = Type{}) noexcept
{
std::fill_n(&arr3D[0][0][0], M * N * O, val);
}
(See Live Online)
it is safe, a two-dimensional array is an array of arrays. Since an array occupied contiguous storage, so the whole multidimensional thing will too. So yeah, it's OK, safe and portable. Assuming you are NOT asking about style, which is covered by other answers (since you're using flags, I strongly recommend std::vector<std::bitset<80> > myFlags(26))
char flags[26][80];
std::fill((char*)flags, (char*)flags + sizeof(flags)/sizeof(char), 0);
Is char[80] supposed to be a substitute for a real string type? In that case, I recommend the following:
std::vector<std::string> flags(26);
flags[0] = "hello";
flags[1] = "beautiful";
flags[2] = "world";
// ...
Or, if you have a C++ compiler that supports initialization lists, for example a recent g++ compiler:
std::vector<std::string> flags { "hello", "beautiful", "world" /* ... */ };