0

I was making a simple program related to arrays. My Code:

#include <iostream>
#include <cmath>
using namespace std;

int main() {
int a;
cout << "Please enter the length of the array: " << endl;
cin >> a;
bool array[a];

for (int n = 0; n < a; n++) {
    array[n] = true;

}
array[0] = false;
array[1] = false;
for (int k = 2; k < a; k++) {
        if (array[k] == true){

    for (int i = 0; pow(k,2)+ i*k < a; i++) {
        array[ pow(k,2) + i * k] = false;

             }
        }

}

    for (int j = 0 ; j < a ; j++){
        if (array[j] == true){
        cout << j <<endl;
        }
    }

}

I get an error in the line

array[ pow(k,2) + i * k] = false;

It says

"Invalid Types"
||=== Build: Debug in Test (compiler: GNU GCC Compiler) ===|
C:\Users\Momo\Documents\CodeBlocks Projects\Test\main.cpp||In function 'int main()':|
C:\Users\Momo\Documents\CodeBlocks Projects\Test\main.cpp|21|error: invalid types 'bool [(((sizetype)(((ssizetype)a) + -1)) + 1)][__gnu_cxx::__promote_2<int, int, double, double>::__type {aka double}]' for array subscript|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

That is the error. I am trying to switch from Java to C++. However such kind of error is new to me as I never encountered such error in Java. Can you guys and girls help me understand what this means? And what can I do to resolve it? Thanks.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
m0mosenpai
  • 67
  • 3
  • 10
  • `bool array[a];` This is not legal ANSI C++. Array sizes in C++ must be declared using a compile-time expression, not at runtime. You're using a compiler extension. – PaulMcKenzie Feb 06 '16 at 07:36
  • *I am trying to switch from java to c++. However such kind of error is new to me as i never encountered such error in java* -- C++ is not Java. Pretend Java doesn't exist, otherwise you'll wind up developing C++ that attempts to look like Java. – PaulMcKenzie Feb 06 '16 at 07:38
  • Okay i'll try my best to forget it . But how should i take the size of the array from the user and then use it to create the suitable array? – m0mosenpai Feb 06 '16 at 07:44
  • Note that using floating point index, even in Java, will get you in trouble w.r.t. floating point inaccuracies. See my answer below. – PaulMcKenzie Feb 06 '16 at 08:18
  • *"However such kind of error is new to me as I never encountered such error in Java."* - This is exactly the **same error** as the one you'd get in Java when you try to use the result of `Math.pow` as an array index. – Christian Hackl Feb 06 '16 at 09:32

4 Answers4

2

Using man pow ,you can get the following:

  double pow(double x, double y);

From that we know pow() return double.But array subscript must be an size_t variable.So you can change that line into:

array[ static_cast<size_t>(pow(k,2)) + i * k] = false;
Curious
  • 20,870
  • 8
  • 61
  • 146
icecity96
  • 1,177
  • 12
  • 26
2

First, this:

bool array[a];

is not legal C++. What you're probably using is a compiler that supports Variable Length Arrays. But again, VLA's are not standard C++. In its place you can use:

#include <vector>
//...
std::vector<bool> a(n);

But this also has issues, however for your purposes it shouldn't be a problem.


Now for this:

array[ pow(k,2) + i * k] = false;

the error is as stated. In C++, you cannot use double as an index type. The pow function returns a double, thus that expression in total becomes double.

You can only use an integral type for an array index. If you truly want to use a double as a type, either:

  1. Create your own class and overload operator [] to take a double, or
  2. Less desirable (see cautionary note below), you can use a std::map<double, bool>. It isn't the same as an array, but the syntax of using a double and operator[ ] will look "array-like".

For the second option:

 #include <map>
 //...
 std::map<double, bool> array;

Then you can use syntax such as array[pow(k,2]] = false;. However be cautious in using [ ], since for a map, operator [ ] will create a new key / data entry if the value specified in [ ] doesn't exist. So you risk creating "holes" in your ersatz array.


But given all this, there is a fundamental flaw in using floating point values as array (or even std::map) indices (or keys w.r.t a map). The flaw is that floating point calculations are inexact -- a differing compiler, compiler setting, etc. could yield different results when you run your program. The index may be one-off if you, for example, compile with one set of options, and then rebuild with another set of options.

Also, if you say that "how can pow(k,2) be faulty if k is an integer?" Well this link will show that you cannot be sure.

Community
  • 1
  • 1
PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
  • Why does `std::vector` have issues? – Curious Feb 06 '16 at 07:51
  • `std::vector` specifically has issues in that it does not conform to a `std::vector`. – PaulMcKenzie Feb 06 '16 at 07:52
  • Yes it is specialized. Why should that be a problem? – Curious Feb 06 '16 at 07:54
  • And for someone coming from a Java background template specialization is not something that should be introduced as a beginning topic – Curious Feb 06 '16 at 07:54
  • Avoid using `vector`,using `deque` or bitset – icecity96 Feb 06 '16 at 07:55
  • There is nothing in the answer that says to specialize a template. – PaulMcKenzie Feb 06 '16 at 07:55
  • Sorry for being blunt about my opinion but this is completely incorrect. I do not subscribe to this chain of thought. `vector` can be used. These things are not something that should be introduced or warned against at an introductory level. – Curious Feb 06 '16 at 08:00
  • @Curious I agree that `vector` should be used in this case. The link is just a cautionary advisement if you use use `vector` assuming you're getting a dynamic array of contiguous `bool` data. – PaulMcKenzie Feb 06 '16 at 08:06
  • @PaulMcKenzie Now I agree with you on both points. It should be used and it does have some problems (not relevant here however). I will take off my downvote – Curious Feb 06 '16 at 08:08
  • Updated the answer to include the issue of floating point and using it for integral computations. – PaulMcKenzie Feb 06 '16 at 08:16
0

Welcome! You have entered a whole new world now that you are programming in C++. Let me introduce you to the C++ standard library (often called the STL) (http://www.cplusplus.com for reference). For most containers that you want to use in your everyday life you would probably want to consider one from the standard library.

In this particular instance, you cannot instantiate an array at runtime as you have done above. You cannot instantiate an array on the stack with a size that is determined at runtime. You will need to dynamically allocate memory on the heap or simply use a STL container (std::vector<> is advised). This is how I would have written your code

#include <iostream>
#include <cmath>
#include <vector>
using namespace std;

int main() {
    int a;
    cout << "Please enter the length of the array: " << endl;
    cin >> a;
    vector<bool> array(a);

    for (int n = 0; n < a; n++) {
        array[n] = true;

    }
    array[0] = false;
    array[1] = false;

    for (int k = 2; k < a; k++) {
        if (array[k] == true){

            for (int i = 0; pow(k,2)+ i*k < a; i++) {
                array[ static_cast<size_t>(pow(k,2) + i * k) ] = false;
             }
        }
    }

    for (int j = 0 ; j < a ; j++){
        if (array[j] == true){
            cout << j <<endl;
        }
    }


    return 0;
}

To explain more here. The following line

std::vector<bool> array(n)

initializes the vector (for the sake of simplicity) with n elements.

More information about the vector class can be found here (http://www.cplusplus.com/reference/vector/vector/?kw=vector)

Curious
  • 20,870
  • 8
  • 61
  • 146
  • Thank you ! i'll have a look into vectors. – m0mosenpai Feb 06 '16 at 07:55
  • No problem! You will enjoy C++ :) – Curious Feb 06 '16 at 07:56
  • If you want more information feel free to comment here and I will provide more information about the C++ standard library containers! – Curious Feb 06 '16 at 07:57
  • 1
    Thank you! you have been very helpful. :-) – m0mosenpai Feb 06 '16 at 07:58
  • Btw about my program...i tried your code. it works perfectly..however it is supposed to display all the prime number between 0 and no. entered by user.This method is based on Sieve of Eratosthenes.It works well enough but 25 is the only composite number being displayed. Rest all are prime. Any idea where i may have went wrong? – m0mosenpai Feb 06 '16 at 14:11
0

Can be done as follows.

for (int i = 0; (pow(k,2) + (i*k)) < a; i++) {
    int kk = (pow(k,2) + (i*k));
    array[kk] = false;

/* This is because pow() is returning double, double + int = double and we are considering double as index of array, which is not allowed in the standard.*/

subrat2014
  • 13
  • 2
  • A program like this may behave differently depending on compiler, compiler options, etc. Floating point calculations are not exact, and `kk` may have differing results. – PaulMcKenzie Feb 06 '16 at 08:08