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.
Related
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]
I'm struggling to create multi-variable output from a function: I want to return 2D array sites(16x15) and the integer number N.
I tried:
std::make_tuple here
std:make_pair here
My problem is that I probably do not know how to define a 2D array in the declaration of the function std::pair <int [][],int> correctly.
Piece of code named function.cpp:
#include <iostream>
std::pair <int[16][15],int> sites_diamond()
{
int sites[16][15]={0};
int N=0;
for (int r=0; r<7; r++) {
N=N+1+2*r;
for (int c=0; c<(7-r);c++){
sites[r][c]=0;
sites[15-r][c]=0;
sites[r][14-c]=0;
sites[15-r][14-c]=0;
}
}
N=2*(N+15);
return std::make_pair(sites, N);
}
using namespace std;
int main(){
std::pair <int[16][15], int> result = sites_diamond();
cout << " sites \n"<<result.first<< endl;
cout << "number \n"<<result.second<< endl;
return 0;
}
Error I'm getting:
function.cpp: In function ‘std::pair<int [16][15], int> sites_diamond()’:
function.cpp:21:26: error: could not convert ‘std::make_pair<int (&)[16][15], int&>(sites, N)’ from ‘std::pair<int (*)[15], int>’ to ‘std::pair<int [16][15], int>’
return std::make_pair(sites, N);
Thank you ahead for any suggestions.
I work primarily in Python, but I want to rewrite a code to C++.
You can go with std::array. It is more C++-ish and you don't need to care about memory allocation/deallocation.
std::pair <std::array<std::array<int, 15>, 16>, int> sites_diamond()
{
std::array<std::array<int, 15>, 16> sites;
// ...
return std::make_pair(sites, N);
}
and then the usage would be:
auto result = sites_diamond();
cout << " sites \n" << result.first.size() << endl;
cout << " number \n" << result.second << endl;
As the error is quite explanatory, I will just suggest the solution. Use pointers.
Define your pair like this:
std::pair<int**, int> result;
Of-course, inside your function, change how you define sites:
int **sites;
sites = new int*[16];
for (int i = 0;i < 16;i++)
sites[i] = new int[15];
Regarding
cout << " sites \n"<<result.first<< endl;
I don’t know what are you trying to print here, it's gonna print some random address anyway.
Don’t forget to delete this dynamically allocated memory when you are done.
But all in all, I would just suggest to use something like vectors (2-d vector in this case, leak-proof too) in place of C-styled arrays.
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.
This may be a very basic question but while digging through STL reference I can't find anything suitable. As an example
std::ostringstream oss;
oss << "One hundred and one: " << 101;
would result in One hundred and one: 101 stored in oss, means the numeric value 101 is converted to text. What I'm looking for is a stream object that keeps the numeric value so that something like:
numstream nums;
nums << 10 << 0 << 15;
would result in a byte or string buffer containing not a textual representation of 10, 0 and 15 but just these three numbers.
Any idea what could be used for this?
A buffer containing a sequence of integers is what std::vector<int>
controls.
You can override the global operator << to append
any type T to any container type C for which such an operation is
meaningful:
#include <vector>
#include <iostream>
std::vector<int> & operator<<(std::vector<int> & vi, int i)
{
vi.push_back(i);
return vi;
}
int main()
{
std::vector<int> vi;
vi << 1 << 2 << 3;
for(auto i : vi) {
std::cout << i << std::endl;
}
return 0;
}
However, if all you want to achieve is an abbreviation of, e.g.
si.push_back(i);
for some integer sequence si and int i, and to be able to shorten, e.g.
si.push_back(i);
si.push_back(j);
si.push_back(k);
to:
si << i << j << k;
remember that the brevity you gain comes at the cost of
making otherwise skilled readers research what your abbreviations are -
and how safe they are.
I suggest that shortening si.push_back(i) to si << i is not worthwhile
and that if you want to get tiresomely long sequences of push_back(n) onto
one line then it would be sufficient and less eccentric to define
a type-safe variadic function template for the purpose, e.g.
void push_back(std::vector<int> & vi){}
template<typename ...Ts>
void push_back(std::vector<int> & vi, int i, Ts... ts)
{
vi.push_back(i);
if (sizeof...(Ts)) {
push_back(vi,ts...);
}
}
With which you would write, e.g.
push_back(si,i,j,k);
rather than:
si << i << j << k;
With this semantic (stream insertion): no there isn't.
From your example it looks like you want to fill a vector of integers with integers.
You will need a functor (ostream manipulator) which would translate the ostream-like semantics into vector-element-addition.
Something along the lines of:
struct functor {
functor(std::vector<int>& viref):
myVector(viref)
{}
// this operator overload translates stream-insert operator
// into vector element addition
functor& operator<<(const int i) {
myVector.push_back(i);
return *this;
}
std::vector<int>& myVector;
};
int main() {
std::vector<int> vi;
functor f( vi );
f << 1 << 2 << 3;
}
Alternatively, you could always write your own streambuffer class (http://www.cplusplus.com/reference/streambuf/streambuf/) but I doubt that that will go down very well because the whole string/stream buf mechanism really is meant to be dealing with single characters being inserted/removed.
is there a possibility to use difference_type with std::distance in the BOOST_FOREACH loop?
#define foreach_ BOOST_FOREACH
class iObj { /* some def and impl */ };
typedef set<iObj*> iSet;
int main() {
iSet *iobjs = new iSet();
// fill set with integers
for( int i=0; i<100; i++) {
iobjs->insert( new iObj(i+1+i*2) );
}
// output content of set
cout << "print objects ASC" << endl;
for( iSet::const_iterator oIt = iobjs->begin();
oIt != iobjs->end(); ++oIt) {
iSet::difference_type oIndex = std::distance( iobjs->begin(), oIt );
if( oIndex < 50 ) {
cout << " #" << oIndex << ": " << **oIt << endl;
} else {
break;
}
}
// output with BOOST
cout << "print objects ASC" << endl;
foreach_( iObj *o, *iobjs ) {
cout << *o << endl;
// no access of index?
}
delete iobjs;
return 0;
}
it is more convenient to display e.g. the first 50 entries of a big set, not the whole content and with std::distance it is not necessary to insert a new counter var and increment it by myselfe
You want to know the loop iteration from within the body of a BOOST_FOREACH loop? No, you can't do that. You can't do it with a C++11 range-based for loop, either. For this purpose, the ordinary for loop is best. (And please, please, please stop using BOOST_FOREACH. C++11's range-based for is the final word on the subject.)
I should also point out that your code is needlessly inefficient. std::set's iterators are not random-access, so std::distance is O(N). Far better is to keep a separate loop counter, and simply increment it each time through the loop.
Also, your code is leaking memory. Although you are deleting the std::set you have new'ed, you're not deleting all the iObj objects you've new'ed. It doesn't seem like there is any need to be dynamically allocating anything in the code you've shown. Try just storing objects by value instead of new'ing them, and use a local std::set stack variable too. You'll save yourself a world of trouble.