realn00b
realn00b

Reputation: 53

string Vector push_back failing in class

I have a class with a method that should return a vector of strings. the getCommVector method has to push_back the elements of a string array into a string vector that can then be returned by the method. When trying to add a string element to the string vector i get:

libc++abi.dylib: terminate called throwing an exception
2Program ended with exit code: 0

I cannot understand why I can't push_back strings to the vector. Any ideas? Thanks in advance!

code segments of interest (edited after suggestions):

class Command {
public:
    //Command (std::string, bool, bool);
    void setOperators(std::string,bool, bool);
    void analyseCommand();
    Command();
    std::vector<std::string> getCommVector ();
private:
    int numOperators; //number of total commands
    int opCount; //current command number
    std::string input_string;
    bool field_command, byte_command;
    std::string commVector[3];
    std::vector<std::string> finalCommVector;
    void byte_analysis();
    void field_analysis();
    void decode_command();
    void syntax_error();
    void decode_error();
};


Command::Command() : numOperators(0), opCount(0),  field_command(false),byte_command(false)
{

}
std::vector<std::string> Command::getCommVector ()
{
    std::string s ="test";
    finalCommVector.push_back("s");
    return finalCommVector;
}

adding SSCE:

class Command {
    public:
        //Command (std::string, bool, bool);
        void setOperators(std::string,bool, bool);
        void analyseCommand();
        Command();
        std::vector<std::string> getCommVector ();
    private:
        int numOperators; //number of total commands
        int opCount; //current command number
        std::string input_string;
        bool field_command, byte_command;
        std::string commVector[3];
        std::vector<std::string> finalCommVector;
        void byte_analysis();
        void field_analysis();
        void decode_command();
        void syntax_error();
        void decode_error();

};


Command::Command() : numOperators(0), opCount(0), field_command(false),byte_command(false)
{

}

void Command::syntax_error()
{
    std::cout<<"Incorrect Syntax Error: Usage: linuxcut -b num -f num \n";
    exit(EXIT_FAILURE);
}

void Command::decode_error()
{
    std::cout<<"Decode Error: Usage: linuxcut -b num -f num \n";
    exit(EXIT_FAILURE);
}


void Command::analyseCommand()
{
    if (byte_command) {
        //start byte command analysys
        byte_analysis();
    }
    else if (field_command)
    {
        //start field command analysys
        field_analysis();
    }
}




void Command::setOperators(std::string input_argument, bool is_field, bool is_byte)
{
    input_string = input_argument;

    field_command = is_field;
    byte_command = is_byte;
}

std::vector<std::string> Command::getCommVector ()
{

    std::string s = "ssd";
    finalCommVector.push_back(s);
    /*
    for (int i = 0; i<sizeof(commVector); i++)
    {

        if (commVector[i] != "")
        {
            //debug

            std::cout<<"asdas";
        }


    }
     */
    return finalCommVector;
}


void Command::byte_analysis()
{
    int next_state = 0;
    int dashCount = 0;
    int commVectIndex = 0;




    //iterate through string and check if the argument is valid
    for (int i= 0; i<input_string.length(); i++) {



        switch (next_state) {
            case 0: //start
                //if character is a number:
                if (isdigit(input_string.at(i)))
                {
                    //first elemnt of command commVector is number
                    commVector[commVectIndex]+=input_string.at(i);

                    //DEBUG
                    std::cout<<commVector[commVectIndex];
                    next_state = 1;
                }
                //if character is a dash:
                else if (input_string[i] == '-')
                {
                    //increment dashCount
                    dashCount++;
                    //if next character in input_string is a number continue
                    if (isdigit(input_string[i+1])) {
                        commVector[commVectIndex]+=input_string.at(i);
                        commVectIndex++;
                        next_state = 1;
                    }
                    else //else error
                    {
                        syntax_error();
                    }
                }
                //if it's niether: error!
                else
                {

                    syntax_error();
                }
                break;

            case 1:
                //if next character is a number:
                if (isdigit(input_string[i]))
                {
                    commVector[commVectIndex]+=input_string.at(i);
                    next_state = 1;
                }
                //if next character is dash
                else if (input_string[i] == '-'&& dashCount <= 3)
                {
                    dashCount++;
                    //increment commandVectIndex
                    commVectIndex++;
                    next_state = 2;
                    commVector[commVectIndex]+=input_string.at(i);
                    //increment commandVectIndex to accomodate next operation
                    commVectIndex++;
                }

                //if it's niether: error!
                else
                {

                    syntax_error();
                }
                break;

            case 2://previous character was dash
                //if next character is number
                if (isdigit(input_string[i]))
                {
                    commVector[commVectIndex]+=input_string.at(i);
                    next_state = 1;
                }

                //if it's niether: error!
                else
                {

                    syntax_error();
                }
                break;

            default:
                syntax_error();
                break;
        }

    }

}



void Command::field_analysis()
{

}
/*****************FUNCTIONS DEFINITIONS***************/

void print_usage() {
    std::cout<<"Incorrect Syntax Error: Usage: linuxcut -b num -f num \n";
}



/*****************END OF FUNCTIONS DEFINITIONS***************/


/***************** MAIN ***************/

int main(int argc, char *argv[]) {
    int opt= 0;
    std::string byte = "-1-2,2",field = "";
    std::string sub_arg_delimiter = ","; //delimiter for comma serparated arguments
    static bool complement = false;
    int diffOpt = 0; //stores the difference between optind  and argc to read filenames in command
    std::string fileName;
    //Specifying the expected options
    //The two options l and b expect numbers as argument
    static struct option long_options[] = {
        {"byte",      required_argument,       0,  'b' },
        {"field", required_argument,       0,  'f' },
        {"complement",    no_argument, 0,  0 },
        {0,           0,                 0,  0   }
    };

    Command testCommand;
    testCommand.setOperators("-2-", false, true);

    std::vector<std::string> trial = testCommand.getCommVector();


    std::cout<<"filename:"<<fileName<<std::endl;
    std::cout<<"Selected flags:\n"<< "b: "<< byte<<"\nf: "<<field<<"\ncomplement: "<<complement<<std::endl;


    return 0;
}

Upvotes: 2

Views: 767

Answers (3)

Zdeslav Vojkovic
Zdeslav Vojkovic

Reputation: 14591

i<sizeof(commVector);

should be

i<countof(commVector);

if countof/_countof is defined for your compiler. If not, you can do it yourself, it is typically defined as:

#define countof(a) (sizeof(a)/sizeof(a[0]))

and I won't go into discussion about using macros in C++ :)

Of course, you could also use a constant are your array has fixed number of elements, but I guess it's just an example.

sizeof returns the size of the object (in this case the string array) itself, not the count of elements inside the vector.

Because of this, it is equal to number of the array elements multiplied by size of a single string instance, so you try to access non-existing items with operator[].

This is also broken:

finalCommVector.push_back("s"); 

and probably you meant:

finalCommVector.push_back(s);

Upvotes: 2

Henno
Henno

Reputation: 397

If all you need is the array of std::string commVector as a std::vector<String>, you can use std::vecor::assign:
finalCommVector.assign(commVector, commVector+3)
The '3' is the length of you array.

Upvotes: 0

You're iterating way beyond the array size. sizeof(commVector) returns the size of the array in bytes.

If you have C++11 available, you can do this:

for (const auto &s : commVector) {
  if (s != "") {
    // as before
  }
}

Or at least this (if you only have partial C++11 support):

for (auto it = std::begin(commVector); it != std::end(commVector); ++it) {
  std::string s = *it;
  // the rest as before
}

Without C++11, you can at least do this:

for (int i = 0; i < sizeof(commVector) / sizeof(commVector[0]); ++i) {
  // the rest as before
}

Or provide your own function for obtaining the correct array size:

template <class T, size_t N>
size_t arraySize(const T (&)[N]) { return N; }

// Use:

for (size_t i = 0; i < arraySize(commVector); ++i) {
  // the rest as before
}

Upvotes: 5

Related Questions