Search code examples
c++arraysstringcompiler-errorsdynamic-arrays

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;

}


Solution

  • 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.