Reputation: 53
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
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
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
Reputation: 171167
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