Array like data structure with negetive index in C++ - c++

I need a structure to keep track of presence of some items. I just wanted to take an array a0....aN and mark the elements as a[0]=0,a[1]=0,a[2]=1........(a[i]=1 if the element is present,a[i]=0 if element is not present).
But the items range from -1000 to +1000. It can be done by putting the negative range from 1001 to 2000. I needed to know if there is any other data structure in c++ that can work like array and with negative indexes. Thank you for your time.

map is used for this only, to have key/index of any basic/user-defined data type. See - http://www.cplusplus.com/reference/map/map/
Example for your case:
#include <iostream>
#include <map>
#include <string>
int main ()
{
std::map<int, int> mymap;
mymap[-1]=1;
mymap[-2]=0;
mymap[-3]=1;
std::cout << mymap[-1] << '\n';
std::cout << mymap[-2] << '\n';
std::cout << mymap[-3] << '\n';
return 0;
}
Example for char:
#include <iostream>
#include <map>
#include <string>
int main ()
{
std::map<char,std::string> mymap;
mymap['a']="an element";
mymap['b']="another element";
mymap['c']=mymap['b'];
std::cout << "mymap['a'] is " << mymap['a'] << '\n';
std::cout << "mymap['b'] is " << mymap['b'] << '\n';
std::cout << "mymap['c'] is " << mymap['c'] << '\n';
std::cout << "mymap['d'] is " << mymap['d'] << '\n';
std::cout << "mymap now contains " << mymap.size() << " elements.\n";
return 0;
}

You an create your own data structure which supports -ve indexes. Just add an offset to the indexs while storing them in an array.
class MyArray {
int *arr;
public:
MyArray(int offset) {
arr = new int[2*offset]; // size must to double the offset
}
~MyArray(){
delete arr;
}
void add(int index, int val) {
arr[index + offset] = val;
}
void get(int index) {
return arr[index + offset];
}
}
Then you can just use your class to add and get elements with any index.
MyArray arr = MyArray(1000); // pass max -ve index as offset
arr.add(10, -150);
cout << arr.get(100);

I need a structure to keep track of presence of some items.
If what you want is set semantics, use a set data structure.
No need to implement a custom array wrapper.
You can use a std::set (or std::unordered_set) for that. Remember that "premature optimization is the root of all evil".
Insert the values that are there, leave out the values that are missing. No need to worry about negative indices.
You can use the methods std::set::find() or std::set::count() to check the presence of an item. Have a look at the documentation to find some example code.
If you later find it's a performance critical optimization, you can replace a std::set<int> with a data structure that you wrote yourself on the basis of an array of bits anytime. If it's not, doing so prematurely might turn out to be an unnecessary source of unexpected errors and a waste of time.
For reference:
http://en.cppreference.com/w/cpp/container/set
http://en.cppreference.com/w/cpp/container/unordered_set
http://en.cppreference.com/w/cpp/container/set/find
http://en.cppreference.com/w/cpp/container/set/count
How to check that an element is in a std::set?

Most efficient approach will be just shifting your array indexes so all of them are non-negative. In your case just use a[i+1000] and it will be sufficient.
If you really need to use negative indexes it is also possible.
C / C++ calculates memory address of array element using address of table and then adding index value to it. Using negative numbers just points to memory area placed before your table (which is not you normally want).
int a[2001];
int *b = &a[1000];
int x = b[-1000]; // This points to 1000 places before b which translates to a[0] (valid place)
Another approach will be using containers. Then any number can be translated to string and stored in proper container.

I think that the answer of #Rajev is almost fine. I have just replaced a plain array with a std::vector. Thus, the memory management is secure and copying and moving is easy.
template <typname T>
class MyArray {
private:
std::vector<T> arr;
public:
MyArray(int offset) {
arr.resize(2*offset); // size must to double the offset
}
void set(int index, int val) {
arr[index + offset] = val;
}
void get(int index) {
return arr[index + offset];
}
}
You can expand this further by overloading the operator [] of MyArray.

Related

C++ Creating Dynamic 2D Array With One Statement but Without auto

I've seen that a dynamic 2D array in C++ can be created as follows:
auto arr{ new int[nRows][nCols] };
nRows and nCols are compile-time known and the size of the array will not change during runtime.
I've tested what is the type of arr is PAx_i (where x is nCols). But I cannot figure out what to put instead of auto (if I don't want to use it) to create a dynamic 2D array with a single statement.
So, the question: Is it possible in C++ to specify the type of a dynamic 2D array directly (C-style like)? If yes, how?
C++ does not support dynamically-sized raw arrays (aka Variable Length Arrays, or VLAs). Whenever you come across the need for such a dynamic array (how ever many dimensions it may have), you should be immediately thinking of using the std::vector container.
Once properly created, you can use the [] operator (concatenated, for 2-D vectors) in much the same way as you would with raw arrays.
Here's a short code demo that creates a dynamic, 2-dimensional 'array' of integers, using the std::vector class, and initializes all elements with an especially significant, non-zero value:
#include <iostream>
#include <vector>
int main()
{
size_t nCols, nRows;
std::cout << "Enter nRows and nCols: ";
std::cin >> nRows >> nCols;
if (nCols < 2 || nRows < 2) {
std::cout << "Matrix is too small!\n";
return 1;
}
// The following SINGLE LINE declares and initializes the matrix...
std::vector<std::vector<int>> arr(nRows, std::vector<int>(nCols, 42));
std::cout << "nRows = " << arr.size() << "\n";
std::cout << "nCols = " << arr[0].size() << "\n";
for (auto& row : arr) {
for (auto i : row) {
std::cout << i << " ";
}
std::cout << std::endl;
}
// Demo for how to use the "[][]" operator ...
arr[0][0] = arr[nRows - 1][nCols - 1] = 33; // Change 1st and last
std::cout << "------------\n";
for (auto& row : arr) {
for (auto i : row) {
std::cout << i << " ";
}
std::cout << std::endl;
}
return 0;
}
One of the great benefits of using std::vector over new[] is that you don't have to worry about subsequently calling delete[] – the container class takes care of all memory allocation and deallocation internally.
In C++ try to avoid new/delete unless you have no other choice.
Next up is std::make_unique (or std::make_shared).
For dynamic arrays C++ has 'std::vector'
Like this :
#include <vector>
#include <iostream>
int main()
{
// 2x2 vector
std::vector<std::vector<int>> values{ {0,1},{2,3},{4,5} };
std::cout << values[1][1];
return 0;
}
Thusly, vector of vector, in this case the values are uninitialized.
std::vector<std::vector<int>> arr(nRows,std::vector<int>(nCols));
You can also do this with gcc compiler, but its not per standard, and won't work if nRows or nCols is variable in Visual Studio:
int arr[nRows][nCols];
It's better for you to get comfortable with C++ standard library, as it will open up new worlds for you.
Another way:
int *arr = new int[nRow*nCol];
You can then index into the flat buffer like:
arr[0][1]

Vector of structs which contains another vector

I need to have dynamically allocated space of structs and those structs have to contain another dynamically allocated. If I do it by manual allocation, that would laborious.
So I want to do it through vectors:
using namespace std;
struct lol{
int value;
vector<int> vekt;
};
vector<lol> vektt;
It is logically, that I am going to do it like the code above but I dont know how to do 2 things that I am going to need for my program:
1.iterate through both of them to get values
2.push something into vekt( the vector of struct );
I tried something like this for pushing but doesnt work:
vektt[0] . vekt . push_back( 2 );
So I need to know how to iterate through both of these vectors and how to access members and methods of the vector vect.
// Iterating
for (auto &i: vektt) // or const auto &i according to requirements
{
cout << i.value << ", ";
for (auto j: i.vekt) cout << j << ' ';
cout << '\n';
}
// Inserting int to vekt of i-th element of vektt
int a;
vektt[i].vekt.push_back(a);

Using an array in a for loop - C++

I want to set a test condition to determine the size of an array, and then move through each value of the array in a for loop.
Take this array for example
std::string expenses[] = {"housing", "utilities", "household expenses", "transportation", "food", "medical", "insurance", "entertainment", "clothing", "misc"};
The brackets are empty, and there are 10 elements in there. How would you create a for loop for this without creating a separate variable that holds an int of 10?
Use the countof macro, declared like this:
#define countof(a) (sizeof(a)/sizeof((a)[0]))
so you can say:
for (i = 0; i < countof(expenses); i++) ...
As everybody's pointing out, you gotta be a good enough hot-shot to know the difference between an array and a pointer.
If you pass a pointer to expenses, of course, countof will be bogus.
My immediate inclination would be to tell you to use a vector instead of an array. With a vector, you can get the size quite easily, and (better still) avoid getting the size by using a range-based for loop:
std::vector<std::string> expenses {"housing", "utilities", "household expenses", "transportation", "food", "medical", "insurance", "entertainment", "clothing", "misc"};
// print out the strings, one per line:
for (auto const &s : expenses)
std::cout << s << "\n";
If you really have to use an array instead of a vector, you can use a function template to compute the size:
template <class T, size_t N>
size_t size(T (&array)[N]) {
return N;
}
for (int i=0; i<size(expenses); i++)
std::cout << expenses[i] << '\n';
The primary advantage of this template function over the usual macro ((sizeof(x)/sizeof(x[0]))) is that it's strongly typed--any attempt at passing a pointer instead of an array simply won't compile (and given how easy it is for an array's name to decay to a pointer, that's significant).
If you have C++11 available, you can use the std::begin and std::end from the standard library to accomplish (roughly) the same:
for (auto s = std::begin(expenses); s != std::end(expenses); ++s)
std::cout << *s;
Note that although std::begin and std::end were added in C++11, you can use code similar to the size template above to create similar templates for a C++98/03 compiler.
template <class T, size_t N>
T *begin(T (&array)[N]) {
return array;
}
template <class T, size_t N>
T *end(T (&array)[N]) {
return array + N;
}
These can also be used with standard algorithms, so you could do something like this:
std::copy(begin(expenses), end(expenses),
std::ostream_iterator<std::string>(std::cout, "\n"));
Again, note that we've avoided dealing directly with the count or creating subscripts into the array, and just deal with iterators into the array, and the items to which those iterators refer.
If you mean to run through each element (within the same scope), then 'The Dark' is correct:
#include <string>
#include <iostream>
int main()
{
std::string expenses[] = {"housing", "utilities", "household expenses", "transportation", "food", "medical", "insurance", "entertainment", "clothing", "misc"};
std::cout<< "NumEls = " << sizeof(expenses) / sizeof(expenses[0]) << std::endl;
}
produces an output of 10, and replacing the cout with a for loop would allow testing of the strings, for example
for (int i=0; i< (sizeof(expenses)/sizeof(expenses[0])); i++)
{
std::cout<< "The " << i << "th string is : " << expenses[i] << std::endl;
}
Note this will produce "0th", "1th", etc...
* Caveat *
Reflecting the comments given in the question, our answers seem incomplete without mention of the fact that the sizeof(POINTER) won't give you useful information - or at least, not useful for this. As such, if you want instead to use:
myFunction (std::string someArray[])
{
for( all the strings in someArray )
{
std::cout << someArray[i];
}
}
then you'll find yourself unable to do so.
Instead, you could use:
myFunction (std::string someArray[], int sizeOfArray)
{
for(int i=0; i<sizeOfArray; i++)
{
std::cout<< someArray[i];
}
}
but this goes exactly against your question (not storing a separate int)
* Enter std::vector *
A simpler solution is to use a std::vector
The use of a vector allows function calls such as myVector.size() and also loops based automatically on the size of the vector, in the case of more recent (C++11) compilers/compiler options.
Vectors can be happily passed into and out of functions, and if you want to change them, references to vectors are also a simple way to do so - referring to your answer:
inputFunction (std::vector<string> &expenses, budget &info)
{
for (int i=0; i< expenses.size(); i++)
{
std::cout<< "Enter your expense for " << expenses[i] << ": ";
// Operation to store input as needed
}
}
On a side note, it seems like you want to link the string for the name of the expense to the value of the expense? If so, consider perhaps using a map. In this case, you'd probably want to consider std::map<std::string, float>.
* Using a std::map *
In using a map, you'll probably want an iterator. An example might be like:
void input(const std::vector<std::string> &exp, std::map<std::string, float> &map)
{
for (int i=0; i<exp.size(); i++)
{
float tempFloat;
std::cout<< "Please enter the amount for " << exp[i] << ": ";
std::cin >> tempFloat;
map.emplace(exp[i], tempFloat);
}
};
and in main(),
std::map<std::string, float> myMap;
input(myVec, myMap);
for (std::map<std::string, float>::iterator it=myMap.begin(); it!=myMap.end(); it++)
{
std::cout << "myMap values -> " << it->first << " = " << it->second << std::endl;
}
This will output each pair you have, using an iterator starting at myMap.begin() and ending at the last entry to your map.
emplace(...) constructs a pair, and then adds it to the map. You should take care not to use insert, which requires a different set of parameters, and is not likely to be what you want here.
The outputs are referenced by iterator->first and iterator->second, the first and second values of each map pair. In this case, those are the string and float that are stored in the map.
You can use sizeof(expenses) / sizeof (expenses[0]). Note that you don't need the brackets, but I prefer it.
A number of people have mentioned the (sizeof(expenses)/sizeof(expenses[0])) trick, but if you're going to go that route, in C++ there is a slightly better way to do it using a templated function:
/* returns # of items in array, or will error out at compile time if you try to pass it a pointer instead of an array */
template<typename T, int size> unsigned int array_size(T(&)[size]) {return size;}
This is safer, since it will give you a compile-time error if you accidentally pass in a pointer rather than an array. (The sizeof() version would compile and then do something unexpected at runtime, which is undesirable)
Two possibilities. If you want to iterate over it in the same scope that you define it, you can simply use a ranged based for loop:
for(auto& expense : expenses)
{
std::cout << expense << std::endl;
}
If you want to be able to pass it to a function, you'd have to to some ugly stuff to fit it into a std::array, then you can use the above range loop on it anywhere.

Simulate std::vector with mixed const and non-const elements

I'd like to simulate a std::vector that has mixed const and non-const elements. More specifically, I want to have functions that operate on a vector and are allowed to see the entire vector but may only write to specific elements. The elements that can and cannot be written will be determined at runtime and may change during runtime.
One solution is to create a container that holds an array of elements and an equal sized array of booleans. All non-const access would be through a function that checks against the boolean array if the write is valid and throws an exception otherwise. This has the downside of adding a conditional to every write.
A second solution might be to have the same container but this time write access is done by passing an array editing function to a member function of the container. The container member function would let the array editing function go at the array and then check that it didn't write to the non-writable elements. This has the downside that the array editing function could be sneaky and pass around non-const pointers to the array elements, let the container function check that all is well, and then write to non-writable elements.
The last issue seems difficult to solve. It seems like offering direct writable access ever means we have to assume direct writable access always.
Are there better solutions?
EDIT: Ben's comment has a good point I should have addressed in the question: why not a vector of const and a vector of non-const?
The issue is that the scenario I have in mind is that we have elements that are conceptually part of one single array. Their placement in that array is meaningful. To use vectors of const and non-const requires mapping the single array that exist in concept to the two vectors that would implement it. Also, if the list of writable elements changes then the elements or pointers in the two vectors would need to be moved about.
I think you can accomplish what you wish with the following class, which is very simplified to illustrate the main concept.
template <typename T>
struct Container
{
void push_back(bool isconst, T const& item)
{
data.push_back(std::make_pair(isconst, item));
}
T& at(size_t index)
{
// Check whether the object at the index is const.
if ( data[index].first )
{
throw std::runtime_error("Trying to access a const-member");
}
return data[index].second;
}
T const& at(size_t index) const
{
return data[index].second;
}
T const& at(size_t index, int dummy) // Without dummy, can't differentiate
// between the two functions.
{
return data[index].second;
}
T const& at(size_t index, int dummy) const // Without dummy, can't differentiate
// between the two functions.
{
return data[index].second;
}
std::vector<std::pair<bool, T> > data;
};
Here's a test program and its output.
#include <stdio.h>
#include <iostream>
#include <utility>
#include <stdexcept>
#include <vector>
//--------------------------------
// Put the class definition here.
//--------------------------------
int main()
{
Container<int> c;
c.push_back(true, 10);
c.push_back(false, 20);
try
{
int value = c.at(0); // Show throw exception.
}
catch (...)
{
std::cout << "Expected to see this.\n";
}
int value = c.at(0, 1); // Should work.
std::cout << "Got c[0]: " << value << "\n";
value = c.at(1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
value = c.at(1, 1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
// Accessing the data through a const object.
// All functions should work since they are returning
// const&.
Container<int> const& cref = c;
value = cref.at(0); // Should work.
std::cout << "Got c[0]: " << value << "\n";
value = cref.at(0, 1); // Should work.
std::cout << "Got c[0]: " << value << "\n";
value = cref.at(1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
value = cref.at(1, 1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
// Changing values ... should only work for '1'
try
{
c.at(0) = 100; // Show throw exception.
}
catch (...)
{
std::cout << "Expected to see this.\n";
}
c.at(1) = 200; // Should work.
std::cout << "Got c[1]: " << c.at(1) << "\n";
}
Output from running the program:
Expected to see this.
Got c[0]: 10
Got c[1]: 20
Got c[1]: 20
Got c[0]: 10
Got c[0]: 10
Got c[1]: 20
Got c[1]: 20
Expected to see this.
Got c[1]: 200

Is it possible to print vector content with width of 5?

Here is what I have to do!
Write a program to perform the following steps.
Allocate memory dynamically to store an array of 10 ints.
Assign each int a random value between 1 and 100.
Copy each of the 10 random ints to a vector of ints.
Print the dynamically allocated array of ints and the vector of ints, each with a width of 5, as shown in the sample output below.
I have trouble with the last point. My code is working perfectly, but I don't know how to set width in vector of ints so it is the same as array of ints.
#include<iostream>
#include<iomanip>
#include<cstdlib>
#include <vector>
#include <algorithm>
#include <iterator>
#include <stdexcept>
using namespace std;
int main(){
const int SIZE = 10;
int *arr = new int[SIZE];
//assign rand numbers between 0 and 100
for (int i = 0; i < SIZE; ++i){
*(arr + i) = rand() % 100+1;
}
//print array
for (int i = 0; i < SIZE; ++i){
cout << setw(5) << *(arr +i) << " ";
}
std::vector<int> integers (arr, arr + 10);
std::ostream_iterator<int> output(cout, " ");
cout << endl;
cout << "Vector integers contain: " << endl;
std::copy(integers.begin(), integers.end(), output);
return 0;
}
Your code works fine as is. cout << setw(5); sets the width just fine. You could also use cout.width(5);.
If you really want to do this with an ostream_iterator, the cleanest way is probably with a small proxy class:
class integer {
int i;
public:
integer(int i) : i(i) {}
friend std::ostream &operator<<(std::ostream &os, integer i) {
return os << std::setw(5) < i.i;
}
};
Then to write them out, use that type as the template parameter to the ostream_iterator:
std::copy(integers.begin(), integers.end(),
std::ostream_iterator<integer>(std::cout, ' '));
This will create a temporary integer object, then write it out using the operator<< for integer, which sets the width. At least in theory, this probably imposes some overhead, but I'd expect (at least with optimization enabled) most compilers will probably see through the subterfuge (so to speak) and eliminate any extra copies and such.
Of course, if the width isn't cast in concrete, you could make integer a template, and supply the width as a template parameter:
template <int N>
class integer {
// ...
return os << std::setw(N) < i.i;
Unless I really needed to use an ostream_iterator, I think I'd use a range-based for loop though:
for (int i : integers)
std::cout << std::setw(5) << i << ' ';
Since the width of a stream is reset to 0 everytime it is used, you can't use a std::ostream_iterator<int> (well, you could by using a custom std::num_get<char> facet which restores the width but that seems a bit radical).
You can print the std::vector<int> like this, however:
std::for_each(integers.begin(), integers.end(),
[](int v){ std::cout << std::setw(5) << v << ' '; });