Nikky Xiong
Nikky Xiong

Reputation: 37

error: variable length array of non-POD element type 'string' (aka 'basic_string<char>')

I know eventually I need to change trigram, whose one space contains 3 characters from the former string, into a dynamic array to solve this problem, but I tried to set my array's capacity large enough at first. However, when I compile my code, the error appears.

#error: variable length array of non-POD element type 'string' (aka 'basic_string<char>'#

Code:

//global variable
int CAPACITY = 1000;

int main()
{
    //a string that reads in the language of the text
string language = "";
    //a string that reads in the file name of the text
string filename = "text.txt";
    //a string that reads in the original text characters
string original = "";
    //a string that reads in the modified original array
string rid_of_spaces = "";
    //an array with capacity that stores the trigrams
string trigrams[CAPACITY];
ifstream finput;
char c;
    //the length of an array
int sLength = 0;
    //the tracker for trigrams
int counter = 0;

cin >> language >> filename;
finput.open(filename.c_str());

while (finput.get(c)){
            //to test if the character is alpha
    if (isalpha(c)){
                    //change the alphabet to lowercase
        c = tolower(c);
                    //store the modified letter in the array
        original += c;
    }
            //change any other characters into a space
    else original += ' ';
}
sLength = original.length();

    //loop through the original array and change mutiple spaces into one 
for (int i = 0; i < sLength; i++){
    if (isalpha(original[i]))
        rid_of_spaces += original[i];
    else {
        while (original[i] == ' ')
            i++;
        rid_of_spaces += ' ';
        rid_of_spaces += original[i];
    }
}
sLength = rid_of_spaces.length();

for (int i = 0; i < CAPACITY; i++)
    trigrams[i] = 0;//initialize each element to 0

for (int i = 0; i < sLength - 2; i++){
    trigrams[counter] += rid_of_spaces[i] 
            + rid_of_spaces[i + 1]
            + rid_of_spaces[i + 2];
        counter++;
}

cout << filename << endl;

cout << original << endl;
cout << rid_of_spaces << endl;

for (int i = 0; i < counter; i++)
    cout << trigrams[i] << endl;

finput.close();
return 0;

}

Upvotes: 2

Views: 2668

Answers (3)

decltype_auto
decltype_auto

Reputation: 1736

The variable

int CAPACITY = 1000;

should be a constant

const int CAPACITY = 1000; // or with c++11 constexpr int CAPACITY = 1000;  

for

string trigrams[CAPACITY];

because "ISO C++ forbids variable length array 'trigrams'" (g++ message)

And this

for (int i = 0; i < CAPACITY; i++)
    trigrams[i] = 0;//initialize each element to 0

should be

for (int i = 0; i < CAPACITY; ++i)
    trigrams[i] = "";//initialize each element to 0

You don't "initialize [strings] to 0" but with a zero length C-string. A zero length C-string is not an invalid 0-pointer, but a (valid) pointer to a char with value 0;

Generally, it's better not to use C-arrays if there are STL-means to avoid them; with c++11, std::array<std::string, CAPACITY> would be preferable here if you want to stay with the "capacity large enough" approach.

live at Coliru's

I took the liberty to change all i++ to ++i in the for-loops' heads while at it; see eg. What is the difference between ++i and i++ for the rationale behind that.

For a dynamic (without pre-defined bounds) array use std::vector<std::string> trigrams;,

push_back or emplace_back your strings into that vector, and for i- iterate

for (std::size_t i = 0; i < trigrams.size(); ++i) {/* ... */}

Or use the iterator-interface of std::vector, e.g.

std::for_each(trigrams.begin(), trigrams.end(), 
              some_function_or_functor_that_does_the_job); 

(see std::foreach here ),

or with c++11 just

for (auto& s : trigrams) {/* ... */}

unless you need to customize the iteration like you do it inside your second loop.

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409364

The variable CAPACITY is not a compile-time constant variable, and variable-length arrays are not in C++ (though some have it as an extension, but apparently not for all types).

There are two solutions to your problem:

  1. Turn the variable into a compile-time constant, either by making it constexpr alternatively const (for older compilers), or by defining it as a preprocessor macro.

  2. Use std::vector, like std::vector<std::string> trigram(CAPACITY);

My suggestion is that you use both solutions above, at least if you later need to resize the vector. If the size will be fixed at compile-time and never change, then use the first solution and use std::array instead of a C-style array:

constexpr std::size_t CAPACITY = 1000;

...

std::array<std::string, CAPACITY> trigram;

Upvotes: 1

vsoftco
vsoftco

Reputation: 56567

The size of a C++ array must be a constant expression. You declare it as int CAPACITY = 1000;, which is not a constant expression. Adding a const qualifier solves the issue: int const CAPACITY = 1000;.

However, you should avoid plain arrays. Try using std::array if you know the size at compile time, or std::vector if not.

Upvotes: 0

Related Questions