Home > database >  Assigning an Array of Char Arrays in Constructor and can it be Flexible?
Assigning an Array of Char Arrays in Constructor and can it be Flexible?

Time:11-19

Ideally I would like to be able to pass an array of char arrays to my constructor and populate the private flexible array member in the constructor. I've made various passes at this but have been have not been successful. Various illegal assignment errors or no errors but not overwriting string literals.

class A{
public:

    A(char b[][20]);
    
private:
    //Some Members
    
    char _x[][20]; //One Flexible Member at end of class
}
A::A(char b[][20]) {
    for(int i = 0; i < sizeof(b)/sizeof(b[0]); i  ) {
        strcpy(_x[i], b[i]);
    }
}
char states[][20] = {"State1","State2","State3","State4"};    

A(states);

I have also tried this:

class A{
public:

    A(char* b[20]);
    
private:
    //Some Members
    
    char* _x[20]; //One Flexible Member at end of class
}
A::A(char* b[20]) {
    for(int i = 0; i < sizeof(b)/sizeof(b[0]); i  ) {
        strcpy(_x[i], b[i]);
    }
}
char states[][20] = {"State1","State2","State3","State4"};    

A(states);

And since I couldn't get either option to work with the flexible size I also hardcoded the size but was still unable to get this to work:

class A{
public:

    A(char b[4][20]);
    
private:
    //Some Members
    
    char _x[4][20] = {}; //Initialized to empty string literals
}
A::A(char b[4][20]) {
    for(int i = 0; i < 4; i  ) {
        strcpy(_x[i], b[i]);
    }
}
char states[4][20] = {"State1","State2","State3","State4"};    

A(states);

The first and third compile and run fine but do not actually rewrite the string literal in the classes 2D array. In the debugger I can see the b[i] showing the correct value but the strcpy does not end up changing the values of _x array.

I have also successfully done the following: (Might be missing a const, I'll double check and edit)

class A{
public:

    A(char* b[]);
    
private:
    //Some Members
    
    char* _x1; 
    char* _x2;
    char* _x3;
    char* _x4;
}
A::A(char* b[]) {
    _x1 = b[0];
    _x2 = b[1];
    _x3 = b[2];
    _x4 = b[3];
}
char* states[] = {"State1","State2","State3","State4"};    

A(states);

I feel like I am misunderstanding a concept here why would my approach be working with multiple char* variables but not work when I make it an array of those variables. Thanks for the help.

Also I am working on an embedded project that avoids STL containers so I am stuck with the C style arrays unfortunately.

CodePudding user response:

You are dealing with a more fundamental problem.

In C all arrays must have a constant, fixed size that's determined at compile time.

char _x[][20]; //One Flexible Member at end of class

Unfortunately there is no such thing as a "flexible member" that's an array, in C . You might be confused by similar "flexible"-like syntax in certain contents, like function parameters, but as far as actual objects go, all arrays must have a fixed, constant size. No exceptions.

In C , there is a std::vector that acts like an array, but whose size can be adjusted at runtime, so the above declaration can simply be:

std::vector<std::array<char, 20>> _x;

This construct makes it possible to use an array-like syntax, like _x[0][1], and get the expected results.

However the rest of your question makes it clear that you don't really want fixed 20-character blocks in your array, but rather manage a vector of strings, so this would be:

std::vector<std::string> _x;

Then, the vector can be managed, intelligently. It will be your responsibility to implement appropriate logic to resize the vector to the appropriate number of values, and to populate its string contents, using high-level std::string class methods, and overloaded operators, instead of rudimentary and error-prone C library functions like strcpy().

strcpy(), strcat(), and plain arrays are used when writing C code. Written C code uses containers, like std::vectors, and std::strings.

CodePudding user response:

No, a member array cannot have an unknown bound.

Your char _x[4][20] version works, but wastes storage.

Your char* _x1; version is ill-formed because the constant string literals don't implicitly convert to pointer to non-const. If you don't intend to modify the strings, then adding const is a trivial solution. Furthermore, your use of separate variables is unnecessary and you can use an array of pointers just like you could use array of arrays. The use of pointers is of course less safe since the pointed strings could have different lifetime from the class instance, but that's not an issue when you use string literals.

So long as it's an option, std::string would be preferable.

  • Related