4

I have an array of numbers {1,2,3,4,5} or an array of chars or whatever. I want to a write a template method to print out the full array. It works, there are just some problems. Maybe i post first the code:

template <typename A>
void printArray(A start) {
    int i = 0;
    while (start[i] != 0) {
        std::cout << start[i] << std::endl;
        i++;
    }
}

int main(int argc, char **argv) {

    using namespace std;
    int xs[] = {1,2,3,4,5,6,7}; //works
    //int xs[] = {1,0,3,6,7}; of course its not working (because of the 0)
    int *start = xs;

    printArray(start);

    return 0;
}

Can you see the problem? while(start[i] != 0) is not the best way to read an array to end ;) What do I have for other options?

Thank you!

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
Lila
  • 41
  • 1
  • 2

5 Answers5

12

Option 1: pass a pointer and the number of elements

 template<class T>
 void doSth(T* arr, int size)

Upside - will work with both dynamic and automatic arrays.
Downside - you must know the size. You must pass it.

Option2: parametrize the template with the size which will be auto-deduced

template <class T, int N>
void doSth(T(&arr)[N])

Downside - Dynamic arrays cannot be passed

Option 3: Be a good programmer and use std::vector's

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
11

Since you are using C++, a vector<int> and iterators will do you better over the long haul.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
6

If you want to use array, not pointer, then you can write the function template as:

template <typename T, size_t N>
void printArray(T (&start)[N]) 
{
    int i = 0;
    while ( i < N) {
        std::cout << start[i] << std::endl;
        i++;
    }
}

int xs1[] = {1,2,3,4,5,6,7}; 
int xs2[] = {1,0,3,6,7}; 
printArray(xs1); //okay
printArray(xs2); //okay

int *start = xs1;
printArray(start); //error - cannot pass pointer anymore!

So better solution would be : std::vector<T>.

Or even better use range (pair of iterators) which is very idiomatic, as:

template <typename FwdIterator>
void printArray(FwdIterator begin, FwdIterator end) 
{
    while (begin != end) {
        std::cout << *begin << std::endl;
        begin++;
    }
}

int xs1[] = {1,2,3,4,5,6,7}; 
int xs2[] = {1,0,3,6,7}; 
printArray(xs1, xs1 + sizeof(xs1)/sizeof(xs1[0])); //okay
printArray(xs2, xs2 + sizeof(xs2)/sizeof(xs2[0])); //okay

int *start = xs1;
printArray(start, start + sizeof(xs1)/sizeof(xs1[0])); //okay!

printArray now can be use with std::vector<T> also:

std::vector<int> vec; //you can use std::list as well!
//populate vec

printArray(vec.begin(), vec.end());
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Two comments: unless you count on using it with several different types of containers, there's no point in making it a function template; a normal function will do. And secondly, of course, rather than `xs1, xs1 + sizeof(xs1)/sizeof(xs1[0])`, you want the usual `begin(xs1), end(xs1)`. – James Kanze Jul 25 '11 at 13:33
  • @James Kanze: 1) OP has used template, so I made this template as well, assuming he wants to make it work for many different types.2) `std::begin()` and `std::end()` is available with C++0x which I didn't assume in my solution. :-) – Nawaz Jul 25 '11 at 13:37
  • OK then for the templates:-). As for `begin` and `end`, I (and I doubt many others) didn't wait for the standard. It's been more or less standard in most people's toolkit for over 10 years now. – James Kanze Jul 25 '11 at 15:15
  • @James: That is true. Utility such as `begin` and `end` can be implemented with much less effort, even in C++03. – Nawaz Jul 25 '11 at 15:19
2

Pass both the address of array and its length.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
2

If you are using a compile-time array, you can do this with a template:

template <typename T, size_t N>
static inline void print_array(const T (&a)[N])
{
  for (size_t i = 0; i < N; ++i)
    std::cout << a[i] << std::endl;
}

int main()
{
  int a[] = {1,2};
  print_array(a);
}

If all you need is to print arrays, also check out the pretty printer, which uses this sort of stuff internally.

Community
  • 1
  • 1
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084