tags:

views:

260

answers:

8
+3  Q: 

c++ array question

I want to initialize an double array with size 200, and its value is from 0 to 199 from index 0 to 199 in c++. i know i can do it by a simple For loop, but is there a way just to initialize the double array like this?

Thanks

+10  A: 

Not really. A for loop is your best option:

double array[200];
for(int i = 0; i < 200; i++)
    array[i] = static_cast<double>(i);
Duracell
Might want to put `static_cast<double>` on those too
Matt Joiner
Oh true. Missed that.
Duracell
+1 Loop is not the only option, as other answers proved. But I prefer to read one simple loop (especially when enclosed within properly named init function) then any other solution.Maybe with an exception of C++0x std::generate+lamda version which is OK... When it's available, that is...But I'd still prefer _explicit_ loop.
Tomek Szpakowicz
This is the only answer, I think. Even a c++ newbie will understand it with no effort. Other answers (std::generate, counting_iterator<>, whatever) are to show the tricks of c++, not to solve the actual problem. Code should be kept as simple as possible (but not simplier) =)
SadSido
@Sad: The `counting_iterator` solution is simple.
GMan
@GMan: yet, it implies the knowledge of std::copy and boost::counting_iterator - things that are not obvious for those who does not use std and boost in their projects (and there are a lot of such projects)
SadSido
@Sad: Such projects are poor then. The standard library is part of the language; failure to use it indicates failure of the programmer programming in C++. Boost should be used when allowed, though that's not always possible for some poeple. (Then again, you can extract individual libraries easily.) Lack of knowledge of `std::copy` is to be in a position not to judge C++ code, for one isn't a C++ programmer.
GMan
@GMan. Projects are poor because they don't use std? Are you kidding? Tons of Playstation games are written in c++ without std, yet millions of kids are happy playing them. Tons of Windows Apps are using ATL instead of std and people are happy using them. How much do end-users care whether their favorite app is using specific libraries or not? So, please don't tell me about the poor projects. And sorry for the offtop, I have no intention to start an std::holywar here.
SadSido
@SadSido: I agree with GMan, to an extent. Every programmer need a debugged, high-performance library for basic operations. Whatever that library is actually. EA Games uses the EASTL for example, which has been geared toward higher performance using dedicated allocators, and allocation and initialization strategies. But I would say it does not matter: I expect any C++ programmer to be able to search on the internet and understand what's happening when I use some STL or Boost part as simple as those mentionned here (I am so not speaking of `boost::mpl`).
Matthieu M.
@SadSido: You may not like it, but GMan is right. C++ is the language plus the standard libraries and puts great emphasis on the latter. And that one out of not even half a dozen answers using a loop got the loop wrong at first shows why loops aren't superior.
sbi
@GMan: `failure to use it indicates failure of the programmer`; being a programmer also means knowing when using it doesn't gain you anything. This answer is just fine. It's smaller, more efficient and less abstract than any of the STL-based solutions to this question. The point is to use the standard library when *necessary*, not when possible. For such a simple task, it's definately not necessary, and I see nothing which argues in favor of a more complex solution. Your argument so reminds me of the umpteen Design Patterns advocates who never understood when a pattern does *not* make sense.
Frerich Raabe
Dear all. I am not against using std and boost. I am against using "int a = boost::zero_initializer<int>()" where "int a = 0" would do just fine. KISS. "for" is stupid simple, "for_each" is not.
SadSido
@Frerich: The `counting_iterator` or C++0x solution is much more concise than an explicit for loop. And claiming it to be more efficient is quite a claim. @Sad: If you find the standard library isn't simple you might need to brush up...
GMan
seems no such an constructor could save the work :)
Grey
+1  A: 

If all value of array are same , you can do it easily. But values are different from each other so i don't think you do it directly.

double array[200];

for(int i=0 ; i<200 ; i++) { 
    array[i] = (double)i; 
}
Judas Imam
Your code leads to an invalid memory access when `i = 200` as it will write to `array[200]`. Put the assignment to `array[i]` into the body of the `for` statement where it belongs!
Ferdinand Beyer
Oh, furthermore, `array[0]` is not written and stays uninitialized.
Ferdinand Beyer
I don't think how c++ for mechanism. If it parse sentence from left then there isn't any invalid memory access. The for loop ends until coming " array[i] = (double)i "
Judas Imam
Sorry. I think it check condition after doing "i++ , array[i] = (double)i" . I suppose it check after every operation like i++ and a condition.
Judas Imam
@Judas: No, it does the check after the assignment.
GMan
@Gman , After the whole assignment , doesn't? Is it true for all languages?
Judas Imam
@Judas: All is quite a lot. I'd say most, though, yes.
GMan
This question's evolution is a good example why what some consider over-elaborated idea (using `std::transform()` and `std::copy()`) actually are good ideas: One out of not even half a dozen `for` loop answers got the loop wrong.
sbi
A: 

The only way to initialize values of arrays is at the point of declarations (if the initializer is smaller than the array all other elements are initialized to zero;

double arr[5] = {0, 1, 2}; // arr = [0.0 ,1.0 ,2.0 ,0.0 ,0.0]

Otherwise there's no way to initialize the values and you'll have to loop over the array.

So what you can do is:

double arr[] = {0, 1, 2, 3, /* ... */, 199}; 

Although looping would be much better in most cases.

Motti
As an additional advantage over the loop notation is that this can be resolved at compilation. The disadvantage being this is a pain to write...
paercebal
@paercebel, of course the fact that it's done at compilation time is the *only* advantage. As for writing it, I would generate it with a script once so as not to risk making an error.
Motti
+1  A: 

Same as Duracell, but with C++ vectors (or lists, or deque):

std::vector<double> array ;
array.reserve(200) ; // only for vectors, if you want
                     // to avoid reallocations

for(int i = 0; i < 200; i++)
    array.push_back(i) ;
paercebal
+7  A: 

Here's a way with std::generate:

template <typename T>
class nexter
{
public:
    nexter(T start = T())
        : value_(start)
    {
    }

    T operator()()
    {
        return value_++;
    }

private:
    T value_;
};

int main()
{
    double data[200];
    std::generate(data, data + 200, nexter<double>());
}

And if you were using C++0x, you could skip the functor:

int main()
{
    double data[200];
    double next = 0.0;
    std::generate(data, data + 200, [&next]() { return next++; } );
}
R Samuel Klatchko
Strictly speaking, I think `for_each` isn't actually suppose to mutate the elements. Also, if you want to ignore a parameter just don't name it. Lastly, might as well use `std::generate` if you're gonna use a functor. :)
GMan
@GMan - thanks, I forgot about `std::generate` - updated my example and also gave an example using C++0x lambdas.
R Samuel Klatchko
@RSamuel: +1 Nice, the C++0x solution is arguably cleanest thus far. (If only the standard library used damn ranges instead of iterators!) For the record that -1 isn't me.
GMan
@GMan - thanks. And I can't wait until lambda's aren't considered cutting edge as they are so damn nice to use.
R Samuel Klatchko
In the C++0x example I would strongly recommend wrapping up the `double next` in a scope of its own so `next` has a small and clearly limited scope. BTW, +1, the C++0x example is very clean.
Omnifarious
+1 But only for showing a glimpse of nice C++0x lambda. Functor version is... No. Please. Don't do that.
Tomek Szpakowicz
So, C++0x allows naming a variable `next`?
Christopher Creutzig
@ChristopherCreutzig - C++0x allows lambda (aka anonymous) functions. The code `[ }` is a lambda function.
R Samuel Klatchko
+7  A: 

Using counting_iterator:

const int SIZE = 200;
double array[SIZE];
std::copy(counting_iterator<int>(0), counting_iterator<int>(SIZE), array);
Matthew Flaschen
IMHO, `::std:;copy` should've been written to require the destination begin and end, and the source begin instead of the other way around. You can get buffer overflows either way, but harder to exploit when the overflow is only reading, not writing.
Omnifarious
@Omnifarious: better yet, requiring both ;) But I agree that a reading overflow is less likely to cause a problem.
Matthieu M.
@Matthew: like GMan I didn't know about this little marvel. So simple and so useful!
Matthieu M.
A: 

If the 200 is a fixed constant and you don't want runtime overhead, I see basically two solutions.

For a C solution, you could solve it through the preprocessor. In think Boost has preprocessor for loops for such a thing. This would have the advantage to be done at compile time, no runtime overhead at all.

The constant 200 by itself might be a bit big for all compilers/preprocessors, though, but most modern ones should be able to handle this.

For a C++ solution, you could do it with template metaprogramming, I think. A recursive type with the number of elements in the template parameter could do the trick. But for constants that large the compile time overhead can be prohibitive.

Jens Gustedt
Interesting options but neither could reasonable be called easier than a loop. Especially the template recursion is a difficult thing to understand
Elemental
@Elemental: depends for whom it is simpler. If you have e.g a generic macro that does that, the call side becomes extremely simple, something like `double A[] = INIT_DARRAY(200);`. Sure the implementation of such a macro ain't simple, but that is really a different side of the coin. And whether such a macro hides a genuine macro definition à la Boost or a recursive template doesn't matter in that respect.
Jens Gustedt
@Jens Fair enough, simpler is a point of view
Elemental
A: 

I think that for-loop is the simplest and most appropriate solution for your case. If you want just to know one more way to do it you could use std::transform:

#include <vector>
#include <algorithm>

double op_increase (double i) { return static_cast<double>(static_cast<int>(i)+1); }

int main() 
{ 
    std::vector<double> x( 200 ); // all elements were initialized to 0.0 here
    std::transform( x.begin(), x.end()-1, x.begin()+1, op_increase );

    return 0; 
} 
Kirill V. Lyadvinsky