xls.each(function(v, k) {
oid = v.OrderID;
xlsindexed[oid] = v;//This gives me a struct with 9999 empty values.
});
I'm trying to get an array/structure with each element named as the orderID, and the value of each to be the struct with the order details.
I've tried all kinds of combinations of
xlsindexed[oid] = v;
xlsindexed.oid = v;
xlsindexed.#oid# = v;
etc
also, tried:
xlsindexed[oid] = 'blah';
and still get struct with 9999 [undefined array element]s
My xls variable has about 30 elements.
(From comments...)
This gives me a struct with 9999 empty values
Technically you get an array with that many undefined elements. The reason that happens is that when xlsindexed is undefined, CF has to guess what type of object this:
xlsindexed[ someNumericValue ] = v;
.. should produce: an array or a structure. Apparently, it sees the numeric value and guesses you want an array. So it creates and initializes an array with that many elements.
If you declare xlsindexed as a structure beforehand, it removes the ambiguity and produces the expected result.
// initialize as a structure
xlsindexed = {};
xls.each(function(v, k) {
xlsindexed[v.OrderID] = v;
});
Related
I need to give these integers names like ex_number_1, ex_number_2, ex_number_3, etc... These are each going to be saved as a different branch of a tree. So I have done:
char m_variable2 [40];
For (……){
sprintf(m_variable2, "ex_number_%d",iSyst);
int m_variable2 = …
}
This is within another couple of loops, e.g. to vary iSyst. It complains about conflicting variable declarations, how do I give the integers the names of m_variable2?
I'm trying to copy what's already been done in huge chunks of the code for histograms, which are in this same loop and accept the following syntax:
hist (TString("example_"+x.at(iSyst)).Data() )->Fill (jets->at(jets.first)->phi(), weight );
But replacing hist with int does not work, and I have to use assignment not this Fill method.
It sounds like you want an associative container such as std::map or std::unordered_map.
std::map<std::string, int> numbers;
numbers["ex_number_1"] = 42;
// or with a dynamic key:
std::map<std::string, int> numbers;
for (...) {
int iSyst = ...;
numbers[std::format("ex_number_{}", iSyst)] = 69;
}
It complains about conflicting variable declarations
Simply give the array variable a different name than what you gave for the integer variable. Example:
char m_variable2_array [40];
…
int m_variable2 = …
But then the integers won't be called ex_number_1, right?
You can name the integers like that by doing this:
int ex_number_1 = …
If I were to create an array with int* array = new int[10]; and fill part of the array with values, how can I check how much of the array is filled? I want to loop through and check if each value is the default value but I'm not sure what the default value of each array element is. Would it be null 0 or garbage values?
This is how to set a default value in C++ when making an array.
int array[100] = {0};
Now every element is set to 0. Without doing this every element it garbage and will be undefined behavior if used.
Not all languages are like this. Java has default values when declaring a data structure but C++ does not.
There is no default value so it's garbage.
You can't do what are you hoping to, not when the type is int.
The uninitialized elements of the array will have unpredictable values. In addition, accessing those elements is cause for undefined behavior.
You can initialize the elements of the array to a sentinel value at the time of allocation using:
int* ptr = new int[10]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
Use whatever sentinel value works for you if -1 does not.
The default value of array is indeterminate means garbage.
how can I check how much of the array is filled?
You cannot check, C/C++ has no array bounds check. You have to do it yourself.You need to keep track of the data inserted by a user. When your counter reaches the size of the array, the array is full
You can solve your problem by a more C++ way. You can create struct or class, which contain your value and bool flag. Bool flag must be set to false in default constructor and set to true in operator=. There is ready implementation of such class - boost.optional. std::optional will be in C++17.
#include <boost/optional.hpp>
#include <iostream>
int main()
{
const size_t nArr = 100;
auto pArr = new boost::optional<int>[nArr];
const size_t nInit = 30;
for (size_t i = 0; i < nInit; ++i)
{
pArr[i] = i; //initialize nInit first values of pArr
}
size_t n = 0;
for (; n < nArr; ++n)
{
if (!pArr[n].is_initialized()) break;
// or more compact form:
//if(!pArr[n]) break;
assert(*pArr[n] == n);
}
std::cout << "nInit = " << nInit << ", n = " << n << std::endl;
assert(nInit == n);
delete[] pArr;
}
It should be pointed out the default is uninitialized only for basic types like int. classes will use their defined parameterless constructor. Here is a MWE that wraps an int in such a class. OP also asked about checking the values so that is here too:
#include <iostream>
struct Element {
int Value;
Element() : Value{42} {}
};
struct Array {
Element Values[10];
};
int main() {
Array array;
for(Element element: array.Values)
std::cout << element.Value << " ";
}
Note: POD (or record) classes, which have no custom constructor, will remain uninitialised. Non-POD classes that have no parameterless constructor cannot usually be held in arrays.
I don't know if this helps but in c++17 onwards there's the std::array class that can be used. In this class you have the option to use class functions such as std::array.fill(...)
std::array<int, 10> arr;
arr.fill(-1);
cpp docs: cpp-docs
This get's you closer to the experience from other languages such as Java and Python both having Arrays.fill(arr, -1); and arr = [-1]*N respectively to fill the array with non-default values.
By default, the objects allocated by new are default initialized. This mean when you wrote:
int* array = new int[10]; //block of 10 uninitialized ints
Here, all of the 10 ints are uninitialized. That is, they have indeterminate value.
It is possible to value initialize the elements by adding an empty pair of parenthesis as shown below:
int* array = new int[10](); //block of 10 ints value initialized to 0
Here all of the 10 ints are initialized to 0.
But note that although we can use empty parentheses to value initialize the elements of an array, we cannot supply an element initializer inside the parentheses. This means for example,
int* array = new int[10](55); // INVALID
The above statement is invalid because we cannot supply an element initializer inside the parenthesize.
You can use std::fill_n instead of supplying an element initializer inside the parentheses as shown below:
int* array = new int[10]; //block of 10 uninitialized ints
std::fill_n(array, 10, 55); // all elements will now hold 55
private:
struct info{
int size = 0;
int key = 0;
int capacity = 1;
std::vector<int*> *value = new std::vector<int*>(capacity);
};
int keyCapacity_;
int size_;
std::vector<info*> *keys_;
within a function...
//some code
keys_ = new std::vector<info*>(keyCapacity_);
//some code
(*keys_)[size_] = new info;
(*keys_)[size_]->(*value)[size] = inputValue; //getting error on this line
(*keys_)[size_]->size += 1;
(*keys_)[size_]->key = key;
I have a pointer to a vector of struct info. Then within info there is a pointer to a vector that will hold values. Very large amounts of data may be input and the program resizes the vectors if needed. The current input value is added to the first open spot on the vector which is size_. On the line I've identified above I am getting an error:
a3.hpp:67:20: error: expected unqualified-id before ‘(’ token
(*keys_)[size_]->(*value)[size] = value;
^
a3.hpp:67:22: error: invalid type argument of unary ‘*’ (have ‘int’)
(*keys_)[size_]->(*value)[size] = value;
How can I access this vector to change the value?
Well, *value is not in scope in this context. It's in parentheses, so it will be evaluated separately. To get to value, you need:
(*keys_)[size_]->value
And then you want to dereference that:
*((*keys_)[size_]->value)
The extra set of parens probably isn't necessary, but it makes things clear. Then you want to index that:
(*((*keys_)[size_]->value))[size]
And I am assuming that size_ and size are correct, different indices. Be careful with your naming. That similarity could trip you up very easily.
As a side note, do realize that using new is almost never what you want to do in modern C++. You probably want to be using smart pointers instead.
(*keys_)[size_]
this one is right
(*keys_)[size_]->(*value)[size]
but this one is not. it will look like you are calling (*value)[size] which doesnt make any sense. its a syntax error.
so you have to call the value first and then dereference it as a whole. like this (*keys_)
int size = yourSize;
(*((*keys_)[size_]->value))
after that you will can now access its index and object inside it.
(*((*keys_)[size_]->value))[size] = &value;
The quick fix for your line is this: (*((*keys_)[size_]->value))[size] = inputValue;
But seriously, don't use C style pointers. Change your code to this instead:
private:
struct info {
int size = 0;
int key = 0;
int capacity = 1;
std::vector<int> value;
}
int keyCapacity_;
int size_;
std::vector<std::unique_ptr<info>> keys_;
And in that function:
//some code
keys_.resize(keyCapacity_);
//some code
keys_[size_] = std::make_unique<info>();
keys_[size_]->value[size] = inputValue;
keys_[size_]->size += 1;
keys_[size_]->key = key;
Since you haven't given a complete example, I can't be entirely sure, but the code still looks wrong to me, because it seems you try to write to a vector that has size 0. From what I can see this should work, but take it was a grain of salt:
//some code
keys_.resize(keyCapacity_);
//some code
keys_[size_] = std::make_unique<info>();
keys_[size_]->value.push_back(inputValue);
keys_[size_]->size += 1;
keys_[size_]->key = key;
If I were to create an array with int* array = new int[10]; and fill part of the array with values, how can I check how much of the array is filled? I want to loop through and check if each value is the default value but I'm not sure what the default value of each array element is. Would it be null 0 or garbage values?
This is how to set a default value in C++ when making an array.
int array[100] = {0};
Now every element is set to 0. Without doing this every element it garbage and will be undefined behavior if used.
Not all languages are like this. Java has default values when declaring a data structure but C++ does not.
There is no default value so it's garbage.
You can't do what are you hoping to, not when the type is int.
The uninitialized elements of the array will have unpredictable values. In addition, accessing those elements is cause for undefined behavior.
You can initialize the elements of the array to a sentinel value at the time of allocation using:
int* ptr = new int[10]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
Use whatever sentinel value works for you if -1 does not.
The default value of array is indeterminate means garbage.
how can I check how much of the array is filled?
You cannot check, C/C++ has no array bounds check. You have to do it yourself.You need to keep track of the data inserted by a user. When your counter reaches the size of the array, the array is full
You can solve your problem by a more C++ way. You can create struct or class, which contain your value and bool flag. Bool flag must be set to false in default constructor and set to true in operator=. There is ready implementation of such class - boost.optional. std::optional will be in C++17.
#include <boost/optional.hpp>
#include <iostream>
int main()
{
const size_t nArr = 100;
auto pArr = new boost::optional<int>[nArr];
const size_t nInit = 30;
for (size_t i = 0; i < nInit; ++i)
{
pArr[i] = i; //initialize nInit first values of pArr
}
size_t n = 0;
for (; n < nArr; ++n)
{
if (!pArr[n].is_initialized()) break;
// or more compact form:
//if(!pArr[n]) break;
assert(*pArr[n] == n);
}
std::cout << "nInit = " << nInit << ", n = " << n << std::endl;
assert(nInit == n);
delete[] pArr;
}
It should be pointed out the default is uninitialized only for basic types like int. classes will use their defined parameterless constructor. Here is a MWE that wraps an int in such a class. OP also asked about checking the values so that is here too:
#include <iostream>
struct Element {
int Value;
Element() : Value{42} {}
};
struct Array {
Element Values[10];
};
int main() {
Array array;
for(Element element: array.Values)
std::cout << element.Value << " ";
}
Note: POD (or record) classes, which have no custom constructor, will remain uninitialised. Non-POD classes that have no parameterless constructor cannot usually be held in arrays.
I don't know if this helps but in c++17 onwards there's the std::array class that can be used. In this class you have the option to use class functions such as std::array.fill(...)
std::array<int, 10> arr;
arr.fill(-1);
cpp docs: cpp-docs
This get's you closer to the experience from other languages such as Java and Python both having Arrays.fill(arr, -1); and arr = [-1]*N respectively to fill the array with non-default values.
By default, the objects allocated by new are default initialized. This mean when you wrote:
int* array = new int[10]; //block of 10 uninitialized ints
Here, all of the 10 ints are uninitialized. That is, they have indeterminate value.
It is possible to value initialize the elements by adding an empty pair of parenthesis as shown below:
int* array = new int[10](); //block of 10 ints value initialized to 0
Here all of the 10 ints are initialized to 0.
But note that although we can use empty parentheses to value initialize the elements of an array, we cannot supply an element initializer inside the parentheses. This means for example,
int* array = new int[10](55); // INVALID
The above statement is invalid because we cannot supply an element initializer inside the parenthesize.
You can use std::fill_n instead of supplying an element initializer inside the parentheses as shown below:
int* array = new int[10]; //block of 10 uninitialized ints
std::fill_n(array, 10, 55); // all elements will now hold 55
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.