2

In my code I am trying to read values from a .txt file so as to build my adjacency matrix but it keeps on returning a segmentation fault. I don't seem to be able to point out where I am going wrong. Please help.

#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <math.h>
#include <limits.h>
#include <iostream>


#define MAX_VERTICES 1024

int global_adj_matrix[MAX_VERTICES][MAX_VERTICES];


int **graph_tree;
int **node_data;
int global_weight;
int number_threads;
int max_nodes;
int random_node;
int max_weight;
int finish_flag;

void readAdjMatrix();


int main(int argc, char *argv[]){

    for(int i = 0 ; i < MAX_VERTICES ; i++){
        for(int j = 0 ; j < MAX_VERTICES ; j++){
            global_adj_matrix[i][j] = 0;
        }
    }

    number_threads = atoi(argv[1]);
    max_nodes = 0;

    readAdjMatrix();

}

void readAdjMatrix(){

    int source, destination, edge_weight;

    max_nodes = INT_MIN;
    max_weight = INT_MIN;

    FILE *file_pointer = fopen("graph.txt", "r");

    while(!feof(file_pointer)){
        fscanf(file_pointer, "%d", &source);
        fscanf(file_pointer, "%d", &destination);
        fscanf(file_pointer, "%d", &edge_weight);

        global_adj_matrix[source][destination] = edge_weight;
        global_adj_matrix[destination][source] = edge_weight;

        if(edge_weight > max_weight)
            max_weight = edge_weight;

        if(destination > max_nodes)
            max_nodes = destination;
    }

    printf("%d %d", max_weight, max_nodes);

    for(int i = 0 ; i <= max_nodes ; i++){
        for(int j = 0 ; j <= max_nodes ; j++){
            printf("%d\t", global_adj_matrix[i][j]);
        }
        printf("\n");
    }

    fclose(file_pointer);
}

This is my .txt file

0 1 281
0 2 242
0 3 344
0 4 340
0 5 372
0 6 161
0 7 49
0 8 278
0 10 190
0 11 213
0 12 55
0 13 239
0 14 321
0 15 162
1 0 281
1 2 249
1 3 58
1 4 331
1 5 189
1 6 84
1 7 259
1 9 256
1 11 188
1 12 149
1 13 330
1 14 17
1 15 370
2 0 242
2 1 249
2 3 125
2 4 179
2 5 355
2 6 11
2 7 232
2 8 199
2 9 67
2 10 390
2 12 312
2 13 3
2 14 237
2 15 96
3 0 344
3 1 58
3 2 125
3 4 105
3 5 192
3 6 180
3 7 335
3 8 280
3 9 185
3 10 66
3 11 65
3 13 274
3 14 72
3 15 282
4 0 340
4 1 331
4 2 179
4 3 105
4 5 149
4 6 286
4 7 265
4 8 359
4 9 341
4 10 211
4 11 367
4 12 340
4 13 14
4 14 69
4 15 128
5 0 372
5 1 189
5 2 355
5 3 192
5 4 149
5 6 167
5 7 268
5 8 20
5 9 270
5 10 210
5 11 369
5 12 131
5 13 133
5 15 167
6 0 161
6 1 84
6 2 11
6 3 180
6 4 286
6 5 167
6 7 208
6 8 335
6 9 353
6 10 12
6 11 307
6 12 199
6 13 273
6 14 118
7 0 49
7 1 259
7 2 232
7 3 335
7 4 265
7 5 268
7 6 208
7 8 182
7 9 327
7 10 272
7 11 198
7 12 103
7 13 132
7 15 161
8 0 278
8 2 199
8 3 280
8 4 359
8 5 20
8 6 335
8 7 182
8 9 108
8 10 112
8 11 344
8 12 192
8 13 264
8 14 207
8 15 231
9 1 256
9 2 67
9 3 185
9 4 341
9 5 270
9 6 353
9 7 327
9 8 108
9 10 395
9 11 205
9 12 365
9 13 8
9 14 57
9 15 132
10 0 190
10 2 390
10 3 66
10 4 211
10 5 210
10 6 12
10 7 272
10 8 112
10 9 395
10 11 11
10 12 7
10 13 288
10 14 143
10 15 226
11 0 213
11 1 188
11 3 65
11 4 367
11 5 369
11 6 307
11 7 198
11 8 344
11 9 205
11 10 11
11 12 203
11 13 136
11 14 252
11 15 168
12 0 55
12 1 149
12 2 312
12 4 340
12 5 131
12 6 199
12 7 103
12 8 192
12 9 365
12 10 7
12 11 203
12 13 90
12 14 344
12 15 11
13 0 239
13 1 330
13 2 3
13 3 274
13 4 14
13 5 133
13 6 273
13 7 132
13 8 264
13 9 8
13 10 288
13 11 136
13 12 90
13 14 39
13 15 39
14 0 321
14 1 17
14 2 237
14 3 72
14 4 69
14 6 118
14 8 207
14 9 57
14 10 143
14 11 252
14 12 344
14 13 39
14 15 154
15 0 162
15 1 370
15 2 96
15 3 282
15 4 128
15 5 167
15 7 161
15 8 231
15 9 132
15 10 226
15 11 168
15 12 11
15 13 39
15 14 154
17
  • 2
    This looks a lot more like C than C++ Commented Apr 24, 2017 at 4:23
  • Sorry about that. @InternetAussie Commented Apr 24, 2017 at 4:24
  • 2
    If it is actually C, remove the <iostream> include, because that is C++. You are not using any element of iostream, so you do not need it. Commented Apr 24, 2017 at 4:29
  • 1
    From core are you able to identify where it fails? Also you need to add check if fopen returns null Commented Apr 24, 2017 at 4:37
  • 5
    If you don't enter an arg then it should be obvious that atoi(argv[1]); will cause a problem because argv[1] will be NULL. Suggest you learn to use a debugger. Commented Apr 24, 2017 at 4:45

2 Answers 2

3

Your segmentation fault is because you're trying to read a nonexistent index in the argument vector of main. If you want to avoid that, you should rewrite it to match something like this:

int main (int argc, const char *argv[]) {

    if (argc > 1 && (number_threads = atoi(argv[1]))) {
        max_nodes = 0;
        readAdjMatrix();
    }

    return 0;
}

This ensures that you have an argument to convert to begin with, and also that it is a nonzero number. I believe atoi has undefined behavior if it isn't a valid string though, so you should harden against that. You also do some other unnecessary things. For one, this block here:

   for(int i = 0 ; i < MAX_VERTICES ; i++){
        for(int j = 0 ; j < MAX_VERTICES ; j++){
            global_adj_matrix[i][j] = 0;
        }
    }

is pointless because if you initialize a 2D array as an external/global variable then it is automatically zeroed upon initialization. Only local/automatic variables will be filled with garbage data. Therefore, you can omit it.

Finally, I would also change your while loop to look more or less like this (Credit: Chux for better loop guard).

while(fscanf(file_pointer, "%d %d %d", &source, &destination, &edge_weight) == 3) {

    global_adj_matrix[source][destination] = global_adj_matrix[destination][source] = edge_weight;

    if(edge_weight > max_weight)
        max_weight = edge_weight;

    if(destination > max_nodes)
        max_nodes = destination;
}

This ensures you correctly scanned the amount of variables necessary per line. And the extended assignment just saves a bit of room.

Hope this fixed the problem you were having.

Sign up to request clarification or add additional context in comments.

1 Comment

Will put your version in instead. Thank you!
0

I am posting my answer by neglecting the bigger code which you have not mentioned in your question. I have trimmed down the unnecessary code. The code is given below.

 #include <stdio.h>
 #include <unistd.h>
 #include <ctype.h>
 #include <string.h>
 #include <stdlib.h>
 #include <math.h>
 #include <limits.h>

 #define MAX_VERTICES 1024

 int global_adj_matrix[MAX_VERTICES][MAX_VERTICES];
 int global_weight,max_nodes,random_node,max_weight;

 void readAdjMatrix();


 int main()
 {
  int i,j;

   max_nodes = 0;
   readAdjMatrix();
   return 0;
 }


 void readAdjMatrix()
 {
  int source, destination, edge_weight,i,j;
  max_nodes = INT_MIN;
  max_weight = INT_MIN;

  FILE *file_pointer = fopen("graph.txt", "r");

  while(!feof(file_pointer))
  {
    fscanf(file_pointer, "%d", &source);
    fscanf(file_pointer, "%d", &destination);
    fscanf(file_pointer, "%d", &edge_weight);

    global_adj_matrix[source][destination] = global_adj_matrix[destination][source] =edge_weight;


    if(destination > max_nodes)
        max_nodes = destination;
   }

   printf( "%d\n", max_nodes);

   for( i = 0 ; i <= max_nodes ; i++){
    for( j = 0 ; j <= max_nodes ; j++){
        printf("%d\t", global_adj_matrix[i][j]);
    }
    printf("\n");
   }

   fclose(file_pointer);
  }

PS : Simply execute this code with ./a.out with no command line argument. In case you are using the command line argument (as given in your question), please use the following syntax to execute your code :

./a.out "your desired number which works with the bigger code"

8 Comments

while(!feof(file_pointer)) test is too late: code will write outside global_adj_matrix[][]. Better to test the result of fscanf()s.
How come ? The two indexes of the global_adj_matrix[][] array are being taken from the file (column 1 --> first index, column 2 --> second index and column 3 --> value to be stored at that location). None of the values in the file are exceeding the number 1024. How will the data be written outside the matrix ?
After the last valid line is read with fscanf(file_pointer, "%d", &edge_weight);, the while(!feof(file_pointer)) does not prevent the next iteration as end-of-file has not happened yet. The 3 fscanf() read fail to read. In this case, likely the values of source, destination remain unchanged. Yet code is brittle. Should int source, destination get moved to inside the while(!feof(file_pointer)) { loop, their value would be undefined. Best to check the return of fscanf() & ditch feof(). See stackoverflow.com/questions/5431941/…
On that last fscanf(file_pointer, "%d", &source);, fscanf() did not return 1 - the scan failed. Try fscanf(file_pointer, "%d", &source); --> printf("retval:%d\n", fscanf(file_pointer, "%d", &source));. Since it do not return 1, the value of source will be 1) unassigned or 2) potentially corrupted. If corrupted or never assigned, global_adj_matrix[source][destination] = ... is undefined behavior - access outside the array may be attempted. Robust code checks the return values of *scanf().
Rather than while(!feof(file_pointer)) { fscanf(file_pointer, "%d", &source); fscanf(file_pointer, "%d", &destination); fscanf(file_pointer, "%d", &edge_weight); use while(fscanf(file_pointer, "%d%d%d", &source, &destination, &edge_weight) == 3) {
|

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.