0

This is were I got so far,but I don't know if it's right. This function receives the dimensions of the 2D array (nxn),and allocates it. flightInfo is the name of the struct. Will this work? thanks in advanced

after allocating the array(ignore the method ,since we are not allowed to use the method you proposed) I would like to initialize the struct (I built a function to do it but it didn't work),I tried to do it right after the allocation and kept getting the" Unhandled exception" warning, does it has to do with the syntax, am I forgetting a '*'?

void flightMatrix()
{
 FILE * fpf;
 int checkScan,Origin,Dest;
 float  time,cost;
 char flightName[3];
 flightInfo *** matrix;


 if(!(fpf=fopen("flights.txt","r")))exit(1);

  while((checkScan=fscanf(fpf,"%*10c%3d%3d%3c%5f%7f%*",&Origin,&Dest,flightName,&time,&cost))!=EOF)
{
    matrix=allocateMatrix(Dest);
   matrix[Origin-1][Dest-1]->o=Origin;

}

}

flightInfo*** allocateMatrix(int n)

{   int i,j;
    flightInfo***  matrix;

matrix=(flightInfo***)malloc(sizeof(flightInfo **)*n);
    for(i=0;i<n;i++)
matrix[i]=(flightInfo **)malloc(sizeof(flightInfo*)*n);

 for (int i = 0; i < n; ++i) 
 {  
    for (int j = 0; j < n; ++j) 
        matrix[i][j] = NULL;
 }

    return matrix;
}

[https://i.stack.imgur.com/MFC7V.png] this is what happens when I try to initialize

Tohar
  • 23
  • 4

1 Answers1

0

Technically speaking, this won't create 2D array. The result will be array of pointers, where each one points to different array of pointers to a struct.

The difference is that, memory will be fragmented, so every element will point to some memory location, instead of single continuous memory block.

The common approach for this is to create flatten 2D array:

flightInfo** allocateMatrix(int n)
{
    flightInfo** matrix = malloc(n*n * sizeof(*matrix));
    for (int i = 0; i < n; i++) 
        for (int j = 0; j < n; j++) 
            matrix[i*n + j] = NULL;
    return matrix;
}

If you are forced to use two indices, then you could place matrix as function argument:

void allocateMatrix(int n, flightInfo* (**matrix)[n])
{
    *matrix = malloc(n * sizeof(**matrix));
    for (int i = 0; i < n; ++i) 
        for (int j = 0; j < n; ++j) 
            (*matrix)[i][j] = NULL;
}

The second asterisk is required, because pointers are passed by value, otherwise you would end up with modified local copy of the pointer, that does nothing to matrix from main function.

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

typedef struct flightInfo {
    char airport[30];
    int  altitude;
} flightInfo;

void allocateMatrix(int n, flightInfo* (**matrix)[n])
{
    *matrix = malloc(n * sizeof(**matrix));
    for (int i = 0; i < n; ++i) 
        for (int j = 0; j < n; ++j) 
            (*matrix)[i][j] = NULL;
}

int main()
{
    int n = 10;
    flightInfo* (*matrix)[n];

    allocateMatrix(n, &matrix);

    matrix[0][0] = malloc(sizeof(flightInfo));
    strcpy(matrix[0][0]->airport, "Heathrow");
    matrix[0][0]->altitude = 10000;

    printf("%s, %d\n", matrix[0][0]->airport, matrix[0][0]->altitude);
}

The another way would be to encapsulate the array within a struct.

Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137
  • In modern C programming, you would rather do `flightInfo (*matrix)[y] = malloc(sizeof(flightInfo[x][y]))`. "Mangled arrays" is a thing of 1990s style C programming. – Lundin Sep 14 '16 at 10:42
  • @Lundin: Yes, but how to return such array from function? I tried with `flightInfo* (*allocateMatrix(int n))[n]` prototype, but this won't compile, as second `n` is unknown to the compiler. The declaration of array was `flightInfo *(*matrix)[n] = malloc(n * sizeof(*matrix));`. – Grzegorz Szpetkowski Sep 14 '16 at 10:43
  • Can you please explain why you used flightInfo** and not flightInfo*** ,because I need to have pointers at each [i][j] in matrix that will eventually lead my to structs,and I don't completely understand the way you allocated the 2D array – Tohar Sep 14 '16 at 10:53
  • @GrzegorzSzpetkowski Typically by using some other pointer type, just as your example uses pointer-to-pointer, where in fact the returned type is no such thing. Cleaner solutions use structs to wrap the array inside. – Lundin Sep 14 '16 at 10:55
  • @Tohar: This is because I dropped one level of indirection. The method is to replace "bogus 2D array" with 1D array, that imitates 2D array. Both methods have pros and cons. – Grzegorz Szpetkowski Sep 14 '16 at 10:55
  • I'm sorry,but we were taught that in order to allocate a 2D array you most use malloc 2 times;the first is for creating a 1D array of pointers and then "extend" each arr[i] to a full line containing whatever you need. How can I reach the same outcome using the method I was taught in class? – Tohar Sep 14 '16 at 11:02
  • 2
    @Tohar You were taught nonsense, what you mention is simply bad practice. Please read [this](http://stackoverflow.com/a/32050859/584518) and [this](http://stackoverflow.com/a/39363946/584518). Your source of learning is bad and needs to be replaced. Ask them if they even know a 2D array is, then ask them if they know what heap fragmentation is, then ask them if they know what data cache memory is. – Lundin Sep 14 '16 at 11:16
  • First ,thank you very much for the help. I would like to know how to initialize each filed after the allocation.I wrote : matrix[Origin-1][Dest-1].d=Dest; (d is defined in the struct, origin=1,Dest=2) but I keep getting the Unhandled exception warning. – Tohar Sep 14 '16 at 13:51
  • @Tohar: The problem is that you initialized 2D array of **pointers** to struct. There is a difference between pointer and actual struct object, which also needs to be allocated. See the last code snippet in my answer. I had to call `malloc` in `main` to make a room for struct object itself. – Grzegorz Szpetkowski Sep 14 '16 at 15:27
  • Thank you very much that works great! Now what should I do if I want to allocate the struct in other function and initialize the struct too there,should I call the function like this: fillArray(matrix) and initialize with -> since it is a pointer to struct or should I use '*' in the call and when I try to initialize? – Tohar Sep 14 '16 at 17:13
  • @Tohar: Both forms are equivalent, but the `->` form is more common, as it helps with code readability (it is obvious at first sight, that you are accessing by pointer). – Grzegorz Szpetkowski Sep 14 '16 at 18:06
  • I understand, but for some reason it is not working I call the function fillMtrix(matrix,Origin,Dest,time,cost); and in it ,after allocating the struct ,like you said,I try to initialize the struct using ->but nothing happenes – Tohar Sep 14 '16 at 18:18
  • @Tohar: It may largely help you to run the code under debugger. This way you can run the code step by step and investigate the variables' contents, and its changes. MS Visual Studio consists of such tool. On Linux, see `gdb`. Debugging is a required and essential skill in C development. – Grzegorz Szpetkowski Sep 14 '16 at 18:24
  • That is exactly what I did and nothing changes within the struct once I pass the matrix[Origin-1][Dest-1]->o=Origin; line in that function, however when I write the same thing at void flightMatrix() it works great – Tohar Sep 14 '16 at 18:36
  • @Tohar: The `malloc` function can return `NULL` if it fails to allocate (so you are out of memory for some reason). You could check when this happens with `if (matrix[Origin-1][Dest-1] == NULL)` after `malloc` call. – Grzegorz Szpetkowski Sep 14 '16 at 19:25