0

I'm trying to implement a train structure in c. I have a struct called bogie and another called linked bogie. I'm having problems with how to refer to all components of these structures in the code. My main problems are:

-I get a seg fault while entering the bogie type

-Why is size of bogie 28? (char(1) +array(20) +int(4)=25)

-I want to confirm if there is a struct inside a struct,I need to malloc for every inner struct when i make an instance of the outer struct? Anyway to make this automatic.

-Am I over complicating the code? Is there a cleaner way to write this?

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

typedef struct
{
    char name;
    char type[20];
    int capacity;
}BOGIE;

struct LINKED_BOGIE
{
    BOGIE* bogie_part_address;
    struct LINKED_BOGIE* link;
};

typedef struct LINKED_BOGIE LINKED_BOGIE;


void print_train(LINKED_BOGIE* engine_address);
void add_bogie(LINKED_BOGIE* engine_address);


void add_bogie(LINKED_BOGIE* engine_address)
{
    LINKED_BOGIE* traverse=engine_address;
    LINKED_BOGIE* new_bogie_address=(LINKED_BOGIE*)malloc(sizeof(LINKED_BOGIE));
    new_bogie_ad:dress->bogie_part_address=(BOGIE*) malloc(sizeof(BOGIE));

    printf("Enter bogie name,type,capacity\n");
    scanf("%c%s%d",&(new_bogie_address->bogie_part_address->name),(new_bogie_address->bogie_part_address)->type,&((new_bogie_address->bogie_part_address)->capacity));


    do traverse=traverse->link;
    while(traverse->link!=NULL);

    traverse->link=new_bogie_address;
    new_bogie_address->link=NULL;
    print_train(engine_address);

}



void print_train(LINKED_BOGIE* engine_address)
{

    LINKED_BOGIE* traverse=engine_address;
    int count=0;
    printf("This is the train\n");
    printf("----------------------------------------\n");


    do
    {
        printf("Bogie number:%d\n",count);
        printf("Bogie name:%c\n",traverse->bogie_part_address->name);
        printf("Bogie type:%s\n",traverse->bogie_part_address->type);
        printf("Bogie capacity:%d\n",traverse->bogie_part_address->capacity);
        printf("----------------------------------------\n");
    }
    while(traverse->link!=NULL);

}

int main()
{

    printf("linked bogie size:%lu\n",sizeof(LINKED_BOGIE));
    printf("bogie size:%lu\n",sizeof(BOGIE));

    LINKED_BOGIE* engine_address=(LINKED_BOGIE*)malloc(sizeof(LINKED_BOGIE));
    engine_address->bogie_part_address=(BOGIE*)malloc(sizeof(BOGIE));

    engine_address->bogie_part_address->name='E';
    strcpy(engine_address->bogie_part_address->type,"Engine");
    engine_address->bogie_part_address->capacity=1;
    engine_address->link=NULL;

    //  print_train(engine_address);


    int choice=0;
    do
    {
        printf("Pick what you want to do:\n\
1)View the train\n\
2)Add a bogie\n\
3)Insert a bogie\n\
4)Remove a bogie\n\
5)Sort train\n\
6)Swap bogies\n\
7)Exit\n");

        scanf("%d",&choice);

        switch (choice)
        {
            case 1:print_train(engine_address);break;
            case 2:add_bogie(engine_address);
        }

    }

    while(choice!=7);




return 0;

}
1
  • The size is 28 because of padding: the char will occupy 4 bytes even though only one is used. If you make the string 21 characters the size will probably jump up to 32. This is because the CPU you are compiling for has a 32 bit data bus, so the fastest access is when data items are aligned on (32 bit) word boundaries. There may be a 'pack' pragma or attribute language extension on your compiler, which can remove the unused bytes, but it will slow all accesses to that structure down. Commented Nov 7, 2016 at 16:54

1 Answer 1

1

Mike already explained that the size of the struct was caused by padding. In your system, an int uses 4 bytes and is aligned on a address multiple of 4.

Your mallocs are correct, but you will have to consistently free the inner and outer struct when later removing a boogie.

But you have small errors in your code:

  • scanf("%c%s%d", ...) will not do what you expect: the %c is likely to read the end of the previous line and not the first non blank character. You should use a %1s for that, without forgotting a place for the null:

    char name[2];
    ...
    scanf("%1s%19s%d",name,(new_bogie_address->bogie_part_address)->type,
        &((new_bogie_address->bogie_part_address)->capacity));
    new_bogie_address->bogie_part_address->name = name[0];
    
  • do traverse=traverse->link; while(traverse->link!=NULL); will not work either: when the train contains only one boogie, you set traverse to null before testing anything. You should do:

    while(traverse->link!=NULL) {
        traverse = traverse->link;
    }
    
  • in `print_traint, you forgot to move traverse. It should be:

    while(traverse != NULL)
    {
        ....
        traverse = traverse->link;
        count += 1;
    }
    

Remember:

  • %c is seldom used because it reads even non printable characters which are ignored by other formats
  • do {...} while(...); if less used than the simple while(...) {...} because it runs its body at least once.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.