-2

The program runs without any errors, it prompts the user to enter row and column numbers so that it can construct a 2D array. If you enter 2 for rows and 2 for columns, it proceeds to the next step but if you enter 3 and above, it terminates with an error

"there is a problem causing this program to stop working..."

Here is my code

#include <stdio.h>
#include <string.h>
#include <malloc.h>
//declaring structure called student
struct student {
    //members of the structure
    char last_name[30];
    char first_name[30];
};
//declaring structure called  classroom_seating
struct classroom_seating {
    struct student **seating ;

};
//Functions implementation for struct student.

void student_init_default(struct student *s) {
    //initializing the data members to string "???"
    strcpy(s->first_name, "???");
    strcpy(s->last_name, "???");
}

void student_init(struct student *s, char *info) {

  /* Use the strtok function to extract first name and
    last name from the variable student, then assign
    them to each instance variable of the student
    structure*/
  strcpy(s->first_name, strtok(info, "/"));
  strcpy(s->last_name, strtok(NULL, "/"));

}

void student_to_string(struct student *s) {
    //printing the initial character of the first name, a period, the initial character of the last name, and a
    //period
    printf("%c.%c.", s->first_name[0], s->last_name[0]);
}
//end of step1

//step2

//Functions implementation for struct classro classroom_seating_init(int rowNum, int columnNum, struct classroom_seating *a){
//It instantiates a two-dimensional array of the size "rowNum" by "columnNum" specified by the
//parameters inside the struct a. Then it initializes each student element of this array using the student_init_default function
void classroom_seating_init(int rowNum, int columnNum, struct classroom_seating *a){
  a->seating=malloc((sizeof(a->seating[rowNum][columnNum])));
   //initializing the counters
    int i = 0;
    int j = 0;
    for (i = 0; i < rowNum; i++) {
        for (j = 0; j < columnNum; j++) {
        student_init_default(&a->seating[i][j]);

        }
       printf("\n");
    }
}


int assign_student_at(int row, int col,struct classroom_seating *a,struct student *s) {
    char str1[30];
    strcpy(str1, a->seating[row][col].first_name);
    if (strcmp(str1, "???"))
    {
        strcpy(a->seating[row][col].first_name,s->first_name);
        strcpy(a->seating[row][col].last_name,s->last_name);
        return 1;
    }
    else {
        return 0;
    }
}

int check_boundaries(int row, int col, struct classroom_seating *a) {
    if (row < 0 || col < 0) {
        return 0;
    }
    else if (row > sizeof(a->seating) || col > sizeof(a->seating[0])) {
        return 0;
    }
    else {
        return 1;
    }
}

void classroom_seating_to_string(struct classroom_seating *a) {
    printf("The Current Seating\n");
    printf("-------------------\n");
    int i = 0;
    int j = 0;
    for (i = 0; i < sizeof(a->seating); i++) {
        for (j = 0; j < sizeof(a->seating[0]); j++) {
            student_to_string(&a->seating[i][j]);
        }
        printf("\n");
    }

}
//end of functions implementation.

//main function
int main(){
    //variable declaration
  struct student s;
  struct classroom_seating a;
  char info[30];
  int rowNum,colNum,row,col;


//taking the inputs from the user,,,enter number of rows and columns that the array will have
  printf("Please enter a number of rows for an classroom seating.");
  scanf("%d",&rowNum);
  printf("Please enter a number of columns for an classroom seating.");
  scanf("%d",&colNum);
  //
  classroom_seating_init(rowNum,colNum,&a);//calling method to create a 2D array for class arrangement.

  printf("Please enter a student information or enter \"Q\" to quit.");
  scanf("%s",&info);
  student_init(&s, info);
  while (1) {
        printf("\nA student information is read.\n");

        // printing student information.
        student_to_string(&s);
         printf("\n");
        // Ask a user to decide where to seat a student by asking for row and column of a seat
        printf("Please enter a row number where the student wants to sit.");
        scanf("%d",&row);
        printf("Please enter a column number where the student wants to sit.");
        scanf("%d", &col);
        // Checking if the row number and column number are valid

        if (check_boundaries(row, col, &a) == 0) {
            printf("\nrow or column number is not valid.");
            printf("A student %s %s is not assigned a seat.\n",s.first_name, s.last_name);
        }
        else {
            // Assigning a seat for a student
            if (assign_student_at(row, col, &a, &s)== 1) {
                printf("\nThe seat at row %d and column %d is assigned to the student\n", row, col);
                student_to_string(&s);
                classroom_seating_to_string(&a);
            }
            else {
                printf("\nThe seat at row %d and column %d is taken.\n", row, col);
            }
        }
        // Read the next studentInfo
        printf("Please enter a student information or enter \"Q\" to quit.");
        // reading a student's information
        scanf("%s", info);

    }

return 0;
}
user3386109
  • 34,287
  • 7
  • 49
  • 68
Timothy Mach
  • 131
  • 1
  • 9
  • 2
    What is `a->seating[rowNum][columnNum]` supposed to be in `malloc(sizeof(a->seating[rowNum][columnNum])`? You seem to be trying to refer to something that you haven't yet allocated. – John Coleman Jan 31 '18 at 02:22
  • how I am supposed to write it?,I have no idea,how malloc function works John Coleman – Timothy Mach Jan 31 '18 at 02:41
  • for ease of readability and understanding: 1) follow the axiom: *only one statement per line and (at most) one variable declaration per statement.* 2) separate code blocks ( `for` `if` `else` `while` `do...while` `switch` `case` `default` ) via a single blank line. 3) separate functions by 2 or 3 blank lines (be consistent),. – user3629249 Jan 31 '18 at 03:31
  • the 'scope' of variables should be as limited as reasonable possible. in function: `classroom_seating_to_string()` the variables `i` and `j` have a 'scope' of the whole function. However, they only need a 'scope' of the associated `for()` statements. And variable types should be compared with the same types. I.E. remove the function scope variable declarations and replace `for (i = 0; i < sizeof(a->seating); i++)` with: `for ( size_t i = 0; i < sizeof(a->seating); i++)` and `for (j = 0; j < sizeof(a->seating[0]); j++)` with: `for ( size_t j = 0; j < sizeof(a->seating[0]); j++)` – user3629249 Jan 31 '18 at 03:37
  • in general, variable and parameter names should indicate `content` or `usage` (or better, both). names like `a`, `s` are meaningless, even in the current context. – user3629249 Jan 31 '18 at 03:43
  • when calling: `strtok()`, always check (!=NULL) the returned value to assure the operation was successful. – user3629249 Jan 31 '18 at 03:44
  • when calling any of the `scanf()` family of functions, 1) always check the returned value (not the parameter values) to assure the operation was successful. 2) When using the input format specifiers '%s' and/or '%[...]', always include a MAX CHARACTERS modifier that is one less than the length of the input buffer. Otherwise the input can overflow the input buffer, which is undefined behavior and can lead to a seg fault event. – user3629249 Jan 31 '18 at 03:52
  • regarding: `printf("Please enter a student information or enter \"Q\" to quit."); scanf("%s",&info);` The posted code expects a 'firstname/lastname' format, However, the prompt fails to mention that critical detail and the code is not checking for a 'Q' – user3629249 Jan 31 '18 at 03:59
  • regarding: `printf("\n");` the function: `printf()` is very expensive in CPU cycles. a much less expensive alternative would be: `puts("");` – user3629249 Jan 31 '18 at 04:06
  • regarding the function: `classroom_seating_init()`. Statements like: `student_init_default(&a->seating[i][j]);` are accessing memory that the function does not own. This is undefined behavior and can lead to a seg fault event. This is because the instance 'seating' is only a double offset pointer and it is not set to point to anything in particular. – user3629249 Jan 31 '18 at 04:15
  • regarding: `else if (row > sizeof(a->seating) || col > sizeof(a->seating[0]))` the `sizeof()` is (in almost all instances) evaluated at compile time. So will return the size of a **pointer and not the actual size the code is expecting. This is a serious problem with the posted code. – user3629249 Jan 31 '18 at 04:18
  • regarding: `for ( size_t i = 0; i < sizeof(a->seating); i++) { for ( size_t j = 0; j < sizeof(a->seating[0]); j++)` the `sizeof()` is a compile time operators so will return the size of a pointer (depending on the underlying architecture, 2, 4, or 8. I.E. it will not return the number of bytes where the `seating` pointer points. This is a serious problem with the posted code. – user3629249 Jan 31 '18 at 04:23

1 Answers1

2

Given

struct student {
    //members of the structure
    char last_name[30];
    char first_name[30];
};
//declaring structure called  classroom_seating
struct classroom_seating {
    struct student **seating ;

};

Then

a->seating=malloc((sizeof(a->seating[rowNum][columnNum])));

is not what you want. The immediate problem is that your structure definitions cannot model the real-world problem of seating. First you need to fill the total seating capacity.

You may change the definition to

#define ROW_MAX 45
// Say you have 45 rows
#define COL_MAX 50
// Say you have 30 cols

//declaring structure called  classroom_seating
struct classroom_seating {
    struct student seating[ROW_MAX][COLUMN_MAX] ; //maximum seating

};

Then classroom_seating_init can be

void classroom_seating_init(void classroom_seating_init(int rowNum, int columnNum, struct classroom_seating *a){
// You should check the boundaries before reaching this point
// Do something with a->seating[rowNum][columnNum]
// Say add First name scanf("%s",(a->seating[rowNum][columnNum]).first_name)

}

You can optionally add a filled field in struct student

struct student {
        //members of the structure
        unsigned char isfilled;
        // set it to say 'f' when filling a particular spot is filled

        char last_name[30];
        char first_name[30];
    };
sjsam
  • 21,411
  • 5
  • 55
  • 102
  • pliz, implement for this metho Then classroom_seating_init can be void classroom_seating_init( void classroom_seating_init( int rowNum, int columnNum, struct classroom_seating *a){ // You should check the boundaries before reaching this point // Do something with a->seating[rowNum][columnNum] // Say add First name scanf("%s",(a->seating[rowNum][columnNum]).first_name) } d – Timothy Mach Jan 31 '18 at 03:21
  • @TimothyMach You have gotten a fairly detailed answer to your question (one that warrants being accepted) -- try to understand it and use what you learn in the rest of your code. This seems to be homework. Don't deprive yourself of the learning experience of working it out by yourself. – John Coleman Jan 31 '18 at 12:09
  • 1
    @John Coleman Yes sir. Thank you Stackoverflow. I manged to solve it by going through it line by line using the suggestions above. – Timothy Mach Feb 01 '18 at 05:27
  • @TimothyMach Glad that you've sorted that out. Thank you for accepting the answer – sjsam Feb 01 '18 at 06:31