C++ Static array - c++

I would like to create a custom lower / upper case function for wstrings.
Therefore I am using a map of integers.
Currently I am automatically creating a function from these maps:
(...)
else if (iCharCode==65)
{
iRet=97;
}
else if (iCharCode==66)
{
iRet=98;
}
else if (iCharCode==67)
{
iRet=99;
}
else if (iCharCode==68)
{
iRet=100;
}
else if (iCharCode==69)
{
iRet=101;
}
else if (iCharCode==70)
{
iRet=102;
}
else if (iCharCode==42818)
{
iRet=42819;
}
(...)
However, the function is going to be pretty large if I turn my map into a if-statement like this.
I would therefore like a use a real map instead, but I don't want to load it at runtime.
I would prefer having a static map, but I am not sure how to do that.
Can somebody share his thoughts?

Maybe the following code can help:
#include<iostream>
#include<map>
std::map<int, int> code_map = {
{65, 97},
{66, 98},
{67, 99},
{68, 100},
{69, 101},
{70, 102},
};
int main() {
for(const auto & pair : code_map) {
std::cout<<pair.first<<" maps to "<<pair.second<<std::endl;
}
return 0;
}
Compiling with g++ example.cpp -std=c++11 -Wall -Wextra (OS X 10.7.4 GCC 4.8.1) yields:
$ ./a.out
65 maps to 97
66 maps to 98
67 maps to 99
68 maps to 100
69 maps to 101
70 maps to 102

You could implement the map as a sorted array of pairs. This can be initialised statically. Look up a value using a binary search, e.g. std::lower_bound with a comparator comparing the first element of each pair.
As further optimisation, you might consider mapping ranges rather than individual characters, using an array of (range_begin, range_end, offset) triplets. This would reduce the whole ASCII alphabet to a single entry; but might be less effective for other alphabets.

Related

Unite elements that share the same value of a variable in a vector of structs

For example, I have this struct :
struct Time
{
char Day[10];
int pay;
int earn;
}
And suppose that the vector of this Time struct has the following elements:
vector<Time> mySelf = ({"Monday", 20, 40}, {"Tuesday", 15, 20}, {"Monday", 30, 10}, {"Tuesday", 10, 5});
So is there any algorithm to unite the data so that elements with the same day name will appear once and the other variables of those elements will combine together to form a new vector like this :
vector<Time> mySelf = ({"Monday", 50, 50}, {"Tuesday", 25, 25});
You can try to insert your elements to unordered_map, and then reconstruct a vector. Search and insertion to the map have constant-time complexity, so all the operation will be O(n), because we need to iterate over a vector twice.
std::unordered_map<std::string, Time> timeMap;
for (const auto& t : mySelf)
{
if (timeMap.count(t.day) == 0)
{
timeMap[t.day] = t;
}
else
{
timeMap[t.day].pay += t.pay;
timeMap[t.day].earn += t.earn;
}
}
or shorter version, since insert already checks if the element exists and will not overwrite it:
for (const auto& t : mySelf)
{
timeMap.insert({t.day, {t.day,0,0}});
timeMap[t.day].pay += t.pay;
timeMap[t.day].earn += t.earn;
}
and then the vector reconstruction:
std::vector<Time> result;
result.reserve(timeMap.size());
for (const auto&[key, val] : timeMap)
{
result.push_back(val);
}
Alternatively you could use std::unordered_set but then you need some hash function for your struct. Probably you could improve it further with move semantics.
live demo

STL algorithm similar to transform which allows access to previously transformed element, similar to accumulate

Is there an STL algorithm which allows me to apply a function to each element in a range, transforming the element, with the previously transformed element as input?
I am thinking something like this (obviously does not work since the second iterator will be invalid):
struct Input
{
int width;
};
struct Output
{
int x;
int width;
};
Output transform_input(const Input &input, const Output &previous)
{
return { previous.x + previous.width, input.width };
}
int main()
{
std::vector<Input> input = { { 30 }, { 60 }, { 10 } };
std::vector<Output> output;
std::transform(std::begin(input)
, std::end(input)
, std::prev(std::begin(output))
, std::back_inserter(output)
, transform_input
);
}
Expected result here is for output to contain 3 elements of type Output, with the following content:
Element 0 where x == 0 and width == 30
Element 1 where x == 30 and width == 60
Element 2 where x == 90 and width == 10
For this to work, I imagine the algorithm would have to allow me to specify a seed, alternatively default construct one for me.
I have already looked at transform and adjacent_difference.
Using transform might work with some kind of custom iterator, or perhaps there is one built-in to STL which I could use?
While adjacent_difference seemed promising, it will only give me access to the previous element for the input iterator.
If there's no built-in algorithm satisfying my requirements, what is an algorithm such as this called?
You can use std::transform and pass a lambda that captures your output container.
std::transform(std::begin(input)
, std::end(input)
, std::back_inserter(output)
, [&](auto& input) {
if (output.empty()) {
return transform_input(input, {});
} else {
return transform_input(input, output.back());
}
);

How best to compare two arrays in C++ with unit tests to verify they match?

Currently, I've got a program which reads and extracts multiple pieces of data from a file, and i would like to ensure those values correctly match the expected values, I'm aware of how this should work in other programming languages such as python with lists and tuples etc, however i am unsure as to the best approach to use unit tests within C++ whilst keeping the code as minimal and efficient as possible. I've currently got multiple arrays all of which i wish to verify that they meet their expected values, so i can test the program with differing input files.
To describe this, in essence, i wish to verify the contents of e.g.
int arrayone [5] = { 11, 12, 13, 14, 15 };
are equal to
{ 11, 12, 13, 14, 15 }
and to complete the unit test successfully if the values are equal, and to fail if they are not equal or not in the same order. Thus, i am looking for the best method to approach this.
Use a C++ std::array instead and you'll get the benefit from all the methods it exposes, like operator==:
#include <iostream>
#include <array>
int main() {
std::array arrayone{ 11, 12, 13, 14, 15 };
std::array facit{ 11, 12, 13, 14, 15 };
if(arrayone==facit) {
std::cout << "true\n";
} else {
std::cout << "false\n";
}
}
Or for C++11 and C++14:
std::array<int, 5> arrayone{ 11, 12, 13, 14, 15 };
std::array<int, 5> facit{ 11, 12, 13, 14, 15 };
std::mismatch() will get the job done and provides more information than std::equal. This will work with pre-C++11 compilers if you change auto to std::pair<int*, int*>
#include <algorithm>
int expectedResult[5] = {11, 12, 13, 14, 15};
int* arr1end = arrayone + 5;
//I assume here that expectedResult is the same length as arrayone (5).
auto res = std::mismatch(arrayone, arr1end, expectedResult);
if(res.first != arr1end) {
std::cout << "Arrays not matching at " << std::distance(arrayone, res.first) << ", expected: " << *res.second << ", got: " << *res.first;
}
Better version, provided that arrayone is an array type (it could decay to a pointer if you for example pass it as a function argument). It requires C++11 due to usage of auto and std::begin()
#include <algorithm>
#include <iterator>
int expectedResult[5] = {11, 12, 13, 14, 15};
auto res = std::mismatch(std::begin(arrayone), std:end(arrayone), std::begin(expectedResult));
if(res.first != std::end(arrayone)) {
std::cout << "Arrays not matching at " << std::distance(arrayone, res.first) << ", expected: " << *res.second << ", got: " << *res.first;
}
This being said, I recommend you to choose one framework and work with it. These libraries are built explicitly for making unit testing easy and fast (i.e. above sequence is one liner in GoogleTest and is not prone to different array length errors).
I'd also advice you to not use plain C-style arrays. As mentioned by Ted Lyngmo, if you use standard containers you have a lot more options available (e.g. built-in opearator ==) and they also manage resources for you.
If you insist that you must not use the STL and use primitives, this pretty much is a C question since it's not using C++ features. If you can safely assume they'd of size n, the following should be ok.
Given two primitive integer arrays of size n, the general implementation would be
bool equal(int *arr1, int *arr2, int n) {
for (int i = 0; i < n; i++) {
if arr1[i] != arr2[i] return false;
}
return true
}
In general though, std::array would be a better idea than the old C-style arrays, but my understanding of the question is unclear, if you can use the STL then the other solutions are superior.
Edit: In case it's unclear what some problems with the above solution are:
There's no pointer validation
If the arrays are different sizes, this won't work
If you want to validate non-int arrays you'll need another (admittedly) function
(Subjective) the output time is different based on how similar the two arrays are
If you want a bit of a better solution, using memcmp like suggested in the comments (this doesn't use libraries to the best of my knowledge):
For two arrays of type X, and size n, you could simple say
bool eql = !(memcmp(arr1, arr2, n*sizeof(X))

How to sort 2d array by first, then second, then third, ... columns using C++?

I have an array in C++ that looks like
95 52
95 20
95 67
76 25
76 250
and I want to sort it by the first column, and then by the second. In general, I may have $n$ columns so I may need a recursive function. Anyone have any fast and efficient ways of doing this? The end goal is to get a list of the unique rows.
Put the data in a vector of vectors, and use std::sort:
vector<vector<int> > vv;
// Put data in the vector...
vector<int> v3 = {95, 67};
vv.push_back(v3);
vector<int> v4 = {76, 25};
vv.push_back(v4);
vector<int> v1 = {95, 52};
vv.push_back(v1);
vector<int> v2 = {95, 20};
vv.push_back(v2);
vector<int> v5 = {76, 250};
vv.push_back(v5);
// Sort the data
sort(vv.begin(), vv.end());
Demo.
std::vector comparison is lexicographic, it works regardless of the number of items in it.
If you want to sort the array, taking column 1 as main index, column 2 as secondary, etc, AND GET THE FINAL RESULT.
An custom sort function will do the work.
struct SortAll {
bool operator() (int *item1, int *item2) {
for (int i = 0; i < COLUMN_COUNT; ++i) {
if (item1[i] < item2[i]) {
return true;
} else if (item1[i] > item2[i]) {
return false;
}
}
return false;
}
} sort_all;
If you want to sort the array, specifying which column to sort, AND GET ONE RESULT EACH TIME.
Create a sort object each time you want to sort.
struct SortEach {
public:
SortEach(int column) : column(column) { }
bool operator() (int *item1, int *item2) {
return item1[column] < item2[column];
}
private:
int column;
}
Usage:
int arr[LENGTH][COLUMN_COUNT];
SortEach sort_2(2);
std::sort(&arr[0], &arr[LENGTH], sort_all); // sort by all column
std::sort(&arr[0], &arr[LENGTH], sort_2); // sort by column 2

Algorithm for index range of values in stl vector

I have a table of data as shown below. Note here is that keyID can be duplicates. I have collected below data in vector structure, which is sorted.
struct myData {
int keyID;
int value;
}
vector<myData> vecReadFromFile;
Now user enters a particular keyID, and I have to check if that value exits in vector, if exits I have to return that value. If not I have to check between which values it fall for example if user enters 120030, value falls between 120028 and 120039 here I should get index of these values i.e., lowerIndex and upperIndex in this example '2' and '3' (as vector index starts at 0)
If user enters less keyID i.e., 120001 then return no value. Similarly user enters keyID greater than last key value then return an different error code.
Basically I want to find index range of given key value effectively. I have added code which is present seems not working for above example I mentioned what is bug?
I can change logic to use STL provided algortihms. Please suggest.
How we can achive this algorithm effectively in C++? Request with sample code as function. Note here I will call function many times in my project so it has to effective.
keyID Value
120002 10
120025 20
120028 25
120039 30
120042 -
120048 40
120052 50
120112 60
120117 70
120123 70
120126 80
120130 90
I have some code here
//==========================================================================
// FindBounds
bool FindBounds(const KEY& cTarget, UINT& uLower, UINT& uUpper)
{
uLower = -1;
uUpper = -1;
// start with full range of data.
uLower = 0;
uUpper = m_uCount-1; // Here I have m_uCount as vector.size()
// narrow the bounds as much as possible.
while (uUpper - uLower > 1 && cTarget != m_pKeys[uLower])
{
// split the range in half and discard the half that the key does not belong to.
UINT uBound = uUpper - (uUpper-uLower)/2;
// keep the lower range.
if (KeyInRange(uLower, uBound, cTarget))
{
uUpper = uBound;
}
// keep the upper range.
else
{
uLower = uBound;
}
}
}
bool KeyInRange(UINT uLower, UINT uUpper, const KEY& cTarget)
{
// check if target is within range.
if (m_pKeys[uLower] <= cTarget)
{
if (m_pKeys[uUpper] > cTarget || (m_pKeys[uLower] == cTarget && m_pKeys[uLower] == m_pKeys[uUpper]))
{
return true;
}
}
// target is not within range.
return false;
}
Thanks for your time and help
There is the std::equal_range algorithm.
std::lower_bound() from STL, <algorithm> header:
http://en.cppreference.com/w/cpp/algorithm/lower_bound
1)I think if you are going to lookup some values by their keys better to choose STL container multiset, which allows key duplicates.
2) see methods lower_bound() and upper_bound() they might be applicable to that you are trying to do