Name integers in a loop - c++

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 = …

Related

Proper way to use large amount of known constant variables

The program receives a vector that represents a character.
It then compares the received vector with all the known vectors that represents characters.
I'm not sure how should I use the known vectors.
A few options I thought of:
1) Using global variables:
vector<int> charA{1,2,3,4,5};
vector<int> charB{5,3,7,1};
...
vector<int> charZ{3,2,5,6,8,9,0}
char getLetter(const vector<int> &input){
if(compareVec(input,charA) return 'A';
if(compareVec(input,charB) return 'B';
....
if(compareVec(input,charZ) return 'Z';
}
2) Declaring all variables in function:
char getLetter(const vector<int> &input){
vector<int> charA{1,2,3,4,5};
vector<int> charB{5,3,7,1};
...
vector<int> charZ{3,2,5,6,8,9,0}
if(compareVec(input,charA) return 'A';
if(compareVec(input,charB) return 'B';
....
if(compareVec(input,charZ) return 'Z';
}
3) Passing the variables
char getLetter(const vector<int> &input, vector<int> charA,
vector<int> charB... , vecotr<int> charZ){
if(compareVec(input,charA) return 'A';
if(compareVec(input,charB) return 'B';
....
if(compareVec(input,charZ) return 'Z';
}
This sounds like an application for a perfect hash generator (link to GNU gperf).
To quote the documentation
gperf is a perfect hash function generator written in C++. It
transforms an n element user-specified keyword set W into a perfect
hash function F. F uniquely maps keywords in W onto the range 0..k,
where k >= n-1. If k = n-1 then F is a minimal perfect hash function.
gperf generates a 0..k element static lookup table and a pair of C
functions. These functions determine whether a given character string
s occurs in W, using at most one probe into the lookup table.
If this is not a suitable solution then I'd recommend using function statics. You want to avoid function locals as this will badly affect performance, and globals will pollute your namespace.
So something like
char getLetter(const vector<int> &input){
static vector<int> charA{1,2,3,4,5};
static vector<int> charB{5,3,7,1};
Giving you snippet, I'd go for:
char getLetter(const vector<int> &input)
{
struct
{
char result;
std::vector<char> data;
} const data[]=
{
{ 'A', {1,2,3,4,5}, },
{ 'B', {5,3,7,1}, },
...
};
for(auto const & probe : data)
{
if (comparevec(input, probe.data))
return probe.result;
}
// input does not match any of the given values
throw "That's not the input I'm looking for!";
}
For 40 such pairs, if this is not called in a tight inner loop, the linear search is good enough.
Alternatives:
use a std::map<std::vector<char>, char> to map valid values to results, and turn compareVec into a functor suitable as key-comaprison for the map, and initialize it the same way.
as above, but use a std::unordered_map.
use gperf, as suggested by #PaulFloyd above
I would start by suggesting that you hash or represent the numbers in their binary collection so that you are not comparing vectors each time as that would prove very costly. That said, your question is about how to make a dictionary, so whether you improve your keys as I suggested or not, I'd prefer the use of a map:
map<vector<int>, char, function<bool(const vector<int>&, const vector<int>&)>> dictionary([](const auto& lhs, const auto& rhs){
const auto its = mismatch(cbegin(lhs), cend(lhs), cbegin(rhs), cend(rhs));
return its.second != cend(rhs) && (its.first == cend(lhs) || *its.first < *its.second);
});
If possible dictionary should be constructed constant with an initializer_list containing all mappings and the comparator. If mappings must be looked up before you are guaranteed to have finished all letters then you obviously can't construct constant. Either way this map should be a private member of the class responsible for translating strings. Adding and mapping should be public functions of the class.
Live Example

Find in Vector of a Struct

I made the following program where there is a struct
struct data
{
int integers; //input of integers
int times; //number of times of appearance
}
and there is a vector of this struct
std::vector<data> inputs;
and then I'll get from a file an integer of current_int
std::fstream openFile("input.txt")
int current_int; //current_int is what I want to check if it's in my vector of struct (particularly in inputs.integers)
openFile >> current_int;
and I wanna check if current_int is already stored in my vector inputs.
I've tried researching about finding data in a vector and supposedly you use an iterator like this:
it = std::find(inputs.begin(),inputs.end(),current_int)
but will this work if it's in a struct? Please help.
There are two variants of find:
find() searches for a plain value. In you case you have a vector of data, so the values passed to find() should be data.
find_if() takes a predicate, and returns the first position where the predicates returns true.
Using the latter, you can easily match one field of your struct:
auto it = std::find_if(inputs.begin(), inputs.end(),
[current_int] (const data& d) {
return d.integers == current_int;
});
Note that the above uses a C++11 lambda function. Doing this in earlier versions of C++ requires you to create a functor instead.

Initialize a C++ vector with a variable inital value

I was coding up a Union find data structure , and was trying to initialize the parent vector with a value parent[i]=i, Is there a way in c++ to initialize the vector like this , that is declaring a vector of size N , and not assigning fixed values to each element, rather position dependent value to each element. (without using any obvious for loops)
This is what I was looking for:
std::vector<int> parent(Initializer);
where Initializer is some class or a function.
To try out my hand a bit, I wrote this:
#include <iostream>
#include <vector>
using namespace std;
class Initializer {
private:
static int i;
public:
int operator() ()
{
return i++;
}
};
int main()
{
vector<int> parent(Initializer);
cout << parent[0];
return 0;
}
However I think I have messed up my concepts pretty bad here, and I am not getting what the declaration means, or what it is doing.
Please answer both the questions,
(1) How to initialize a vector with variable initial values.
(2) What exactly is the code I wrote doing?
This is a function declaration:
vector<int> parent(Initializer);
Becasue Initializer is a type name, you declared a function parent that takes Initializer as a (unnamed) parameter and returns vector<int>. See Most vexing parse.
To do what you want, you can do this:
std::vector<int> parent(N); // where N is the size you want
std::iota(parent.begin(), parent.end(), 0); // fill it with consecutive values
// starting with 0
There's std::generate algorithm that you can use to save result of a function (or function object) in a range:
std::generate(parent.begin(), parent.end(), Initializer());
Live demo.
There are several alternatives. If you want to initialize the vector with increasing values, then you can use std::iota.
std::vector<int> vec(size);
std::iota(std::begin(vec), std::end(vec), 0);
If you want something more general you could use std::generate.
std::vector<int> vec(size);
int n = 0;
std::generate(std::begin(vec), std::end(vec), [&n]() {return n++;});

Count strings in string array c++?

How to sum number of strings in string array in which is not explicit defined how many elements it takes?
string str[] = { "astring", "bstring", "cstring", "dstring", "zstring" };
Need to find out how many elements array have?
template< typename T, size_t N >
/*constexpr*/ size_t size( T(&arr)[N]) )
{
return N;
}
constexpr if available (C++11) will allow you to use the return value for static (compile time) usage as a size of another array.
If str[] is statically defined (as shown), then this will work:
const size_t numElements = sizeof(str) / sizeof(str[0]);
If it's dynamically created, then you are going to need a marker to signal the last element (0 is being typically used if it's an array of pointers). Either that or the caller tells you how many elements there are (also common).
In addition to the methods already listed in other answers, another way to do this might be to add a guard value to the end of the array, such as an empty string. You can then iterate through the array until you hit the guard value.
Personally, I'd probably use C++11 and
std::vector<std::string> la = { "foo", "bar", "baz" };
so you can just query la.size() to get what you wanted... at runtime, anyway. Unfortunately, i don't see a way to use this trick with std::array, so it isn't a perfect alternative.
one way using pointers to count the elements of the array:
#include <iostream>
using namespace std;
int main() {
string str[] = { "astring", "bstring", "cstring", "dstring", "zstring" };
cout << ((&str)[1] - str); // 5
cout << endl;
return 0;
}
output:
5
I usually use a separate variable for tracking array size.
String str[] = { "astring", "bstring", "cstring", "dstring", "zstring" };
int strNum = 5;
And then if I need to reference any of the strings, I can just call it as such:
String foo = str[strNum-1];
And any time I update the array in a loop, i simply use strNum as the index to start writing new strings to, and then place a strNum++ within the loop immediately after each new string.

More than one variable type in array

I am busy with a dynamic 2d array and I have declared it as follows:
string** MakeArray(int row,int col)
{
string** array;
array = new string* [col];
for(int r = 0; r < row; r++)
{
array[r] = new string [col];
}
return array;
}
Now I can place string values in the array. How can I place Integer values in the first column and strings in second and integers in third, if my array is 4 by 99?
The elements in an array are all the same type. To get what you're after, you probably want to start off rather differently, with an array of structs:
struct whatever {
int a;
std::string b;
int c;
};
std::vector<whatever> your_array;
Edit: although it's almost certainly a lousy idea, if you really need this to be a 2D array, you could try making all your elements the same type of union:
union whatever {
int a;
std::string b;
};
This has some pretty severe limitations though -- in fact, putting a std::string in a union isn't officially supported at all. There's a fairly decent chance it'll work, but no guarantee of it at all. If you really, really need to do something like this, you can make that member of the union a pointer instead. That is guaranteed to work, but also guaranteed to be so clumsy that making mistakes with it is nearly inevitable.
Don't do that. Instead create a struct that will represent single record in a table, and contain a string and two integers. Then create one dimensional array of those structures.
struct record
{
int a;
std::string b;
int c;
};
record* MakeArray(int row)
{
return new record[row];
}
better yet, ditch arrays and use std::vector:
std::vector<record> array(99);
Have you looked at having a vector/array of tuples, if you have C++11 available to you? So you could do something such as:
#include <tuple>
#include <vector>
typedef std::tuple<int, std::string, int> MyTuple;
std::vector<MyTuple> MakeVector()
{
std::vector<MyTuple> vecTuples;
for( int i = 0; i < 5; ++i )
{
vecTuples.emplace_back( std::make_tuple<int, std::string, int>( i, "Test"+i, i+5 ) );
}
return vecTuples;
}
C++ is a "strong-typed" language. One of the things that means is you cannot mix data types (unless they are related, like base-derived class hierarchical relationship).
In other words what you are doing is not what C++ directly supports.
Having said that there's something you can do that would do what you want - have an array of triplets, like this:
struct triplet
{
int first;
string second;
int third;
};
triplet** MakeArray(...
What you are doing in your example looks alot like a JS code though. Maybe what you want is to store all your data as strings? Then yes, you can use a 2D array of strings, but that requires you to convert datum into string when storing it and converting back from string for calculations. Which is a major performance issue