1

I am trying to create an adjacency matrix from a graph file.

I need to read in a text file containing the number of vertices, then lists the graph format

Ex:

5
0 3 2
1 0 2
1 2 2
1 4 1

The first column of numbers is for the id of source vertex, the second column is for the id of target vertex, and the third column is the weight of edge

So this should return the matrix

0 2 0 2 0
2 0 2 0 1
0 2 0 0 0
2 0 0 0 0
0 1 0 0 0

So far I have read the text file and gotten the number of vertices but I'm not sure on what to do from here.

My current code:

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

int main (){

    printf("Enter the file contianing the graph\n");

    char filename[20];
    FILE *myFile;
    scanf("%s",filename);
    myFile = fopen (filename,"r");

    int number_of_nodes, number_of_edges;
    int source_id[100], target_id[100], weight[100];
    int matrix[100][100];
    int i;      
    if (myFile == NULL){
        printf("File not found! Exiting...\n");
        return -1;
    }
    else{
        fscanf(myFile, "%d", &number_of_nodes);
        printf("There are %d vertices.\n", number_of_nodes);
        for(i = 0; i < (sizeof (source_id) / sizeof ( source_id[0] )); i++)
        {
 if( fscanf(myFile, "%d %d %d", &source_id[i], &target_id[i], &weight[i]) != 3)
           break;

        }
        number_of_edges = i;  

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

        for (i = 0;  i < number_of_edges; i++){
          int x = source_id[i];
          int y = target_id[i];
          matrix[x][y] = weight[i];
          matrix[y][x] = weight[i];
          }

          for (int y = 0; y < (number_of_nodes-1); y++){
            for (int x = 0; x < (number_of_nodes -1); x++){
              printf(matrix[x][y]);
              printf(" \n");
            } 
         } 

    }


    fclose(myFile);

    return 0;
}
mike
  • 13
  • 3
  • does the first line of file contain the number of nodes or the largest node ID? if first one then why is it 4, not 5? and why element [4,4] has been set to 1? – mangusta Dec 03 '18 at 03:28
  • sorry you're right it should be 5 I put 4 by mistake – mike Dec 03 '18 at 03:29
  • For sure it's better to check the return code for the statement fscanf(myFile,"%d,",&numberArray[i]); This IO operation may fail sometimes... – Krassi Em Dec 03 '18 at 03:32
  • @KrassiEm what do you mean by this/how can i improve it? – mike Dec 03 '18 at 03:36

1 Answers1

0

Since you only posted the code for reading the file, I'll just comment on and improve that part.

First, you can define your variables in a better way. In the below code I removed your numberArray and instead, defined a number_of_nodes and three separate arrays for sources, targets and weights. This makes it easier to refer to these data later.

Second, since you don't have the number of items (edges) in the file, you must check if a read is successful by looking at the return value of fscanf(). It returns the number of elements that are successfully read. In your case, you're reading 3 numbers at a time, so you can just compare the return value with 3. You would also like to store the value of i after exiting the loop, so you'll know later how many edges are actually read.

Third, using scanf("%s") is as bad as using gets() (Why is it bad?). You should probably look into limiting the input length, for example using scanf("%19s"). I didn't fix it in the below code as it's not a direct issue, but should be taken into account in your later development.

And finally, +1 for your file open check. It's a good practice to ensure that previous actions completed successfully before proceeding.

Here's my fixed code:

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

int main() {
    printf("Enter the file contianing the graph\n");

    char filename[20];
    FILE *myFile;
    scanf("%s", filename);
    myFile = fopen(filename, "r");

    int number_of_nodes, number_of_edges;
    int source_id[100], target_id[100], weight[100];

    int i;
    if (myFile == NULL) {
        printf("File not found! Exiting...\n");
        return -1;
    }
    else {
        fscanf(myFile, "%d", &number_of_nodes);
        printf("There are %d vertices.\n", number_of_nodes);
        for (i = 0; i < (sizeof(source_id) / sizeof(source_id[0])); i++) {
            if (fscanf(myFile, " %d %d %d", &source_id[i], &target_id[i], &weight[i]) != 3)
                break;
        }
        number_of_edges = i;
    }

    fclose(myFile);

    return 0;
}

For what to do next, I'll give you some tips instead of writing the full code directly. It's relatively easy if you get the point.

You would like to create a "matrix", or in the words of C, an array of arrays. To be simple, it should look like this

int matrix[100][100];

You can then initialize the matrix and reset it to zero:

// This is pseudo-code
for i = 0 to 99
  for j = 0 to 99
    matrix[i][j] = 0

And then based on what you have read from the file, you can assign the values to the zeroed-out matrix. Remember to assign two values (x to y and y to x)

for edge in edges
  x = edge.source
  y = edge.target
  matrix[x][y] = edge.weight
  matrix[y][x] = edge.weight

To print out the matrix, just go through it by row. Don't forget to print a newline after each row.

for y = 0 to (number_of_nodes - 1)
  for x = 0 to (same as above)
    print matrix[x][y] and a space
  print a newline

If you can understand all the above ideas, then you're good to go.

iBug
  • 35,554
  • 7
  • 89
  • 134
  • thank you for your help on fixing my problems, also would you be able to give me any idea as to how to create the matrix / read the vertices into separate arrays? I am not too sure on how to go about looking at this problem – mike Dec 03 '18 at 05:36
  • @mike Reading the edges into separate arrays is already implemented in that big block of C code. Creating the matrix in C is also in the first single-line code. The rest are provided in pseudo-code for you to comprehend (not copy). Hope you have a good time. – iBug Dec 03 '18 at 05:40
  • edge.source how am I supposed to code this, I was thinking number_of_edges.source_id[ ] but it is giving me error – mike Dec 03 '18 at 09:02
  • @mike `source_id[i]` where `i` is a number. – iBug Dec 03 '18 at 09:43
  • so I tried following the pseudo code to the best of my ability and I updated my code in the OP, however, I am getting a segmentation fault after printing out the number of vertices, I get a segmentation error, I am unsure what is causing this – mike Dec 03 '18 at 18:34