0

Suppose you have 12 passengers on a ship. Each of them is different. These 12 passengers are divided into the categories of:

  • class
  • age
  • gender

Each of these categories can have 2 different options:

  • class is either "first" or "second"

  • age is either "adult" or "child"

  • gender is either "male" or "female"

I decided to create a new datatype of type struct called "Passenger". As you will see in the code below, it has three members: class, age, gender.

And then I create a variable (allPassengers) of this newly created datatype (Passenger).

But now, how do I fill out the array of type Passenger called "allPassengers" with the all 12 different combinations of info about Passengers?

E.g. I created manually the first three combinations:

#include < stdio.h > #include < string.h >

    typedef struct {
        char class[7];
        char age[6];
        char gender[7];
    }
Passenger;


/* This is where all the information about passengers will be stored, global variable,
there are 9 combinations of passengers (allocated array elements for the variable), last one is reserved for the null character \0 */
Passenger allPassengers[10];


int main() {

    // First combination
    strcpy(allPassengers[0].class, "first");
    strcpy(allPassengers[0].age, "adult");
    strcpy(allPassengers[0].gender, "male");


    // Second combination
    strcpy(allPassengers[1].class, "second");
    strcpy(allPassengers[1].age, "adult");
    strcpy(allPassengers[1].gender, "male");


    // Third combination
    strcpy(allPassengers[2].class, "first");
    strcpy(allPassengers[2].age, "child");
    strcpy(allPassengers[2].gender, "male");

    // ... etc

    return 0;
}

Here's the same code (copy-paste friendly).

I know it'd have been easy to fill out an array with just numbers (for loops). But I have no idea how to fill out, for example, the first two allPassengers[0], and allPassengers[1] with necessary information. I guess I'd write a complex "if statements" inside for loops e.g. check the class of the previous allPassengers e.g. if there are more than 2 matches, assign class "second".

Or switch case... dunno. What if I had to fill out a harder combination.

How do I only allow a limited strings for the variable to take? e.g. class can take either "first" or "second"?

Any clues?

Stefano Nardo
  • 1,567
  • 2
  • 13
  • 23
Jack
  • 121
  • 4
  • If you will always be limited to 2 options for each item, it might be easier to use a [boolean type](http://stackoverflow.com/questions/1921539/using-boolean-values-in-c) or a 0-1 based system, would likely make the logic much easier. IE `(isFirstClass {0,1}, isAdult {0,1}, isMale {0,1}) `or any combination. – Tim S. Mar 21 '16 at 17:49

4 Answers4

0

I suggest you create enum types if your data are strictly limited to the specific values you said.

Example :

enum ClassEnum{
FIRST,
SECOND
};

enum AgeEnum{
   ADULT,
   CHILD
};

enum GenderEnum{
   MALE,
   FEMALE
};

typedef struct {
        ClassEnum class;
        AgeEnum age;
        GenderEnum gender;
    }
Passenger; 

It will simplify what you are trying to do as you won't have to manipulate string anymore.

In order to fill an array with every combinations you don't have other choice that to write a function that will go through all of them.

Gluk36
  • 62
  • 5
0

I suggest you define a function that takes a pointer to a passenger structure and a set of attribute values which it uses to initialize the structure. For example:

void init_passenger(Passenger *passenger, const char *class,
    const char *age, const char *gender) {
    strcpy(passenger->class, class);
    /* ... */
}

I would also avoid magic numbers and define macros

#define CLASS_MAX_LEN 7
#define AGE_MAX_LEN 6
#define GENDER_MAX_LEN 7

so that the struct definition becomes

typedef struct {
    char class[MAX_CLASS_LEN];
    char age[MAX_AGE_LEN];
    char gender[MAX_GENDER_LEN];
} Passenger;

If space is not an issue you can have a single macro

#define MAX_LEN 7

To fill in the array of passengers, simply call the function init_passenger(allPassengers[i], "firstm "child", "male") for appropriate values of i (and appropriate attribute values).

You can loop through all possible values by nesting three loops, one for each array of possible attribute values (as suggested in a separate answer).

P.S. I imagine you're using the well-know Titanic dataset. Is that accurate?

blazs
  • 4,705
  • 24
  • 38
0

I would suggest null terminated arrays of strings, which in C are null terminated arrays of character.

char **classes = { "first", "second", NULL };
char **ages = { "child", "adult", NULL };
char **gender = { "female", "male", NULL };

for( char **class = classes; class; class++ ) {
    for( char **age = ages; age; age++ ) {
        for( char **gender = genders; gender; gender++ ) {

Note that the ++ operator is operating on char ** variables and NOT on char * variables, so you are incrementing through the strings in the list and NOT the characters in one particular string. Null terminating allows a very simple second term for the for loop of just the loop variable itself. This approach is generalizable, in that you could simply add new category values to the list of strings and the logic would be basically the same. (Although as you add more category values you would need to preallocate more space as the number of combinations grow)

Chip Grandits
  • 317
  • 1
  • 9
0

Each passenger has three attributes, and each attribute has two possible values, so there are
23 = 8 possibilities in all. To fill in the array, we can use the concept of a binary number.

In the code below, p is used as the index into the allPassengers array, and at the same time, the binary representation of p is used to choose the strings. The most significant bit of p determines the gender, the middle bit determines the age, and the least significant bit determines the class.

Passenger allPassengers[8];

int main( void )
{
    for ( int p = 0; p < 8; p++ )
    {
        char *gender = (p & 4) ? "female" : "male";
        char *age    = (p & 2) ? "child"  : "adult";
        char *class  = (p & 1) ? "second" : "first";

        strcpy( allPassengers[p].gender, gender );
        strcpy( allPassengers[p].age, age );
        strcpy( allPassengers[p].class, class );
    }

    for ( int p = 0; p < 8; p++ )
        printf( "%-6s %s %-6s\n", allPassengers[p].class, allPassengers[p].age, allPassengers[p].gender );
}
user3386109
  • 34,287
  • 7
  • 49
  • 68