Sending blocks of 2D array rows using MPI in C - c

I am trying to do a matrix multiplication using MPI in C. (c <= a*b)
I am running the following code on 4 nodes. All the matrices are 8*8 in size.
(num of rows in a matrix % num of nodes == 0)
matrix b[][] is broadcast so all the nodes get the same copy. For matrix a[][], instead of broadcasting, I want to send only the set of rows that is needed by each node.
But when I run the following code and print the matrix a[][] after MPI_Recv() worker nodes print 0s instead of the values assigned in the master node.
Can you point out what am I doing wrong here?
#include <stdio.h>
#include "mpi.h"
#include "matrix.c" // matrix definitions and matrix operation functions are here
int main(int argc, char *argv[])
{
MPI_Status status;
int num, rank, size, tag, high,low,i;
int offset, tmphigh,rows;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
rows=MAX/size; // MAX is the length(=height) of the matrices
tag = 201;
low=rank*rows;
high=low+rows;
if (rank == 0) {
fillMatrix(b,MAX);
fillMatrix(a,MAX);
}
MPI_Bcast(&b[0][0],MAX*MAX,MPI_INT,0,MPI_COMM_WORLD);
if(rank==0){
for(i=1;i<size;i++){
offset=i*rows;
MPI_Send(&a[offset][0],rows*MAX,MPI_INT,i,tag,MPI_COMM_WORLD);
}
}else{
MPI_Recv(&a[low][0],rows*MAX,MPI_INT,0,tag,MPI_COMM_WORLD,&status);
}
printMatrix(a,MAX);
MPI_Finalize();
return 0;
}
here is how matrices are created
int a[MAX][MAX], b[MAX][MAX], c[MAX][MAX];
int len; //(edited after Jeremy W. Sherman's comment )
//this was the reason that caused this problem. changing this to int len=MAX; solved the problem
void fillMatrix(int (*matrix)[len], int len){
int i=0,j=0;
for(i=0;i<len;i++){
for(j=0;j<len;j++){
matrix[i][j]=j;
}
}
//printMatrix(matrix,len);
}
Thank You.

The problem might lie printMatrix() and fillMatrix(). clang refused to compile your definition of fillMatrix():
so_mpi.c:22:31: error: use of undeclared identifier 'len'
void fillMatrix(int (*matrix)[len], int len){
^
Dropping len from the prototype just creates another problem:
so_mpi.c:26:19: error: subscript of pointer to incomplete type 'int []'
matrix[i][j]=j;
~~~~~~^
What did work was this:
void fillMatrix(int *matrix, int len) {
int i, j;
for (i = 0; i < len; ++i) {
int *row = &matrix[i * len];
for(j = 0; j < len; ++j) {
row[j] = j;
}
}
}
fillMatrix((int *)a, MAX);
fillMatrix((int *)b, MAX);
With that change, everything seems to work fine. I used MAX = 5 and 5 nodes. I prefixed logging statements with the node's rank and added a few more logging statements. Here was the result:
$ mpirun -np 5 ./so_mpi
node 1 of 5
node 4 of 5
node 0 of 5
0: filling matrices
0: matrix B:
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0: matrix A:
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0: broadcast of B complete
0: sending 1 rows (5 elements) of A to node 1
0: sending 1 rows (5 elements) of A to node 2
0: sending 1 rows (5 elements) of A to node 3
0: sending 1 rows (5 elements) of A to node 4
0: matrix A:
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
1: broadcast of B complete
1: received portion of matrix
1: matrix A:
0 0 0 0 0
0 1 2 3 4
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
node 2 of 5
2: broadcast of B complete
2: received portion of matrix
2: matrix A:
0 0 0 0 0
0 0 0 0 0
0 1 2 3 4
0 0 0 0 0
0 0 0 0 0
node 3 of 5
3: broadcast of B complete
3: received portion of matrix
3: matrix A:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 1 2 3 4
0 0 0 0 0
4: broadcast of B complete
4: received portion of matrix
4: matrix A:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 1 2 3 4

Related

MPI Gatherv ordering data incorrectly when different 2-D array sizes

I'm trying to take a N*N 2-D array, have each process be responsible for a number of columns, carry out an action on the elements and gather them back together into a single 2-D array again.
I have managed to divide the columns among the processes, carry out the action and bring them back together using MPI subarrays and Gatherv. However, when I give the program a number of processes that doesn't equally divide into the number of columns, the returned data is misplaced.
With the master matrix being 12x12, I provide four processes and get the correct result back:
FINAL MATRIX
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
When the matrix is still 12x12 and I provide five processes, I get this output:
FINAL MATRIX
1 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 0 0 0 0 0 0
1 1 1 2 2 2 0 0 0 0 0 0
1 1 1 2 2 2 0 0 0 0 0 0
1 1 1 2 2 2 0 0 0 0 0 0
Can someone inform me as to what I've configured incorrectly for this to be the result? Ultimately, after resolving this, I wish to switch the Gatherv to Allgatherv so that each process has the entire 2-D array locally for further alterations.
Update (11/04/2021)
As suggested by Gilles I have attempted to use column vectors instead but could not find a way in which to recombine with Gatherv. I believe my issue with my current solution may be due to displacements as manually altering these causes changes in the output (populating some of the zero cells).
Full code:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void print_matrix (double ** X, int rows, int cols)
{
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j)
printf ("%.0f ", X[i][j]);
printf ("\n");
}
}
double **alloc_2d_array(int m, int n) {
double **x;
int i;
x = (double **)malloc(m*sizeof(double *));
x[0] = (double *)calloc(m*n,sizeof(double));
for ( i = 1; i < m; i++ )
x[i] = &x[0][i*n];
return x;
}
void main(int argc, char *argv[]) {
int n = 12;
int ndims = 2;
int rank, size;
int root_rank = 0;
MPI_Datatype sendsubarray, recvsubarray, resizedrecvsubarray;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Report active to console
printf("Rank: %d, reporting!\n", rank);
// Make master matrix
double ** master_matrix = alloc_2d_array(n, n);
// Set starting values in master matrix
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
master_matrix[i][j] = 0;
}
}
// Calculate sub matrices no. of columns and displacements
int interval, modulus, section_end, section_start, section_length;
int counts[size];
int displs[size];
interval = n/size;
modulus = n % size;
for (int i=0; i < size; i++) {
if (modulus != 0) {
counts[i] = interval+1;
modulus--;
} else {
counts[i] = interval;
}
displs[i] = (i == 0) ? 0 : displs[i-1]+counts[i-1];
}
// Calculate subarray info
int master_size[2] = {n, n};
int subsize[2] = {n, counts[rank]};
int startat[2] = {0, displs[rank]};
// Populate sub matrix in main matrix
for (int i = startat[0]; i < startat[0] + subsize[0]; i++)
for (int j = startat[1]; j < startat[1] + subsize[1]; j++)
master_matrix[i][j] = rank + 1;
// Print adjusted matrix
// printf("ADJUSTED MATRIX\n");
// print_matrix(master_matrix, n, n);
// Create the subarray type for use by each send node (incl. the root):
MPI_Type_create_subarray(ndims, master_size, subsize, startat, MPI_ORDER_C,
MPI_DOUBLE, &sendsubarray);
MPI_Type_commit(&sendsubarray);
// Create the subarray type for use by the receive node (the root):
if (rank == 0) {
MPI_Type_create_subarray(ndims, master_size, subsize, startat, MPI_ORDER_C,
MPI_DOUBLE, &recvsubarray);
MPI_Type_commit(&recvsubarray);
MPI_Type_create_resized(recvsubarray, 0, 1 * sizeof(double),
&resizedrecvsubarray);
MPI_Type_commit(&resizedrecvsubarray);
}
// Gather the send matrices into the receive matrix:
MPI_Gatherv(master_matrix[0], 1, sendsubarray,
master_matrix[0], counts, displs, resizedrecvsubarray,
0, MPI_COMM_WORLD);
if (rank == 0) {
printf("FINAL MATRIX\n");
print_matrix(master_matrix, n, n);
}
MPI_Finalize();
}

logical multiplication of matrices A and B by the operation "AND" and "OR" in C

This is the question:
A logical matrix is a matrix in which all its elements are either 0 or
1.
We define logical multiplication of matrices A and B by the operation
defined below, where "·" is the logical AND operation, and "+" is the
logical OR operation.
In this assignment, you will create two 5x5 logical matrices and find
the corresponding matrix which will be created from "multiply" these 2
matrices
Define global SIZE equals to 5 (Already defined in the template)
Write a function that gets a matrix reference and reads the input
to the matrix from the user. If the input is non-zero replace it by 1.
If the user did not enter enough values before the end of the line,
the remaining cells in the matrix will be populated with zeros. Also
make sure if the user inputs too many characters, you only take what's
needed and discard the remaining input. (Eg: 1509 is a 2x2 matrix with
values 1101, and ‘1 5 ‘ is also a 2x2 matrix with values 1111, the
highlighted whitespace is taken as a 1 as discussed above.)
Function signature: void read_mat(int mat[][SIZE])
Write a function that multiplies, as defined above, two matrices
and enters the results into a third matrix with suitable dimensions.
Function signature: void mult_mat(int mat1[][SIZE],int mat2[][SIZE], int result_mat[][SIZE])
Write a function that prints a matrix into the screen. Please use
“%3d” for printing format to make it look nice as shown below.
Function signature: void print_mat(int mat[][SIZE])
Write the main program which uses the functions above. The program
reads the matrices values from the user, multiplies them and prints
the result matrix on the screen.
The function definitions given are intentional with the return
statements as void. Do not change them. Arrays are transferred between
functions as references rather as primitives like variables. So the
function definitions are perfectly valid. Also, there is no limit on
the input from the user. You can read only the required digits, and
then stop reading, and discard the remaining input.
Here is my code:
#include <stdio.h>
#define SIZE 5
void read_mat(int mat[][SIZE],int size)
{
int i = 0, j = 0, k = 0;
char c;
c=getchar();
while(c!='\n' && k<size*size){
if(c!='0'){
mat[i][j]=1;
j++;
}
else{
mat[i][j]=0;
j++;
}
if (j >= size){
j = 0;
i++;
}
if (i >= size){
return;
}
c=getchar();
k++;
}
}
void mult_mat(int mat1[][SIZE], int mat2[][SIZE], int result_mat[][SIZE])
{
int i,j,k;
for (i = 0; i <SIZE; ++i){
for (j = 0; j <SIZE; ++j)
{
result_mat[i][j] = 0;
for (k = 0; k < SIZE; ++k)
result_mat[i][j] += mat1[i][k] * mat2[k][j];
if(result_mat[i][j]!=0){
result_mat[i][j]=1;
}
}
}
}
void print_mat(int mat[][SIZE],int size)
{
int i, j;
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++)
printf("%3d", mat[i][j]);
printf("\n");
}
//Please use the "%3d" format to print for uniformity.
}
int main()
{
int mat1[][SIZE]={ 0 }, mat2[][SIZE]={ 0 }, res_mat[][SIZE]={0};
printf("Please Enter Values For Matrix 1\n");
read_mat(mat1,SIZE);
printf("Please Enter Values For Matrix 2\n");
read_mat(mat2,SIZE);
mult_mat(mat1,mat2,res_mat);
printf("The First Matrix Is :- \n");
print_mat(mat1,SIZE);
printf("The Second Matrix Is :- \n");
print_mat(mat2,SIZE);
printf("The Resultant Matrix Is :- \n");
print_mat(res_mat,SIZE);
return 0;
}
The input and output should be like this:
Please Enter Values For Matrix 1
111000654987010
Please Enter Values For Matrix 2
11 53
The First Matrix Is :-
1 1 1 0 0
0 1 1 1 1
1 1 0 1 0
0 0 0 0 0
0 0 0 0 0
The Second Matrix Is :-
1 1 1 1 1
1 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
The Resultant Matrix Is :-
1 1 1 1 1
1 0 0 0 0
1 1 1 1 1
0 0 0 0 0
0 0 0 0 0
But when I run the program, this message appears:
exception thrown: Run-Time Check Failure #2 - Stack around the variable 'mat2' was corrupted.
and the output isn't right and I am getting some elements has a junk values:
Please Enter Values For Matrix 1
111000654987010
Please Enter Values For Matrix 2
11 53
The First Matrix Is :-
1 1 1 0 0
0 1 1 1 1
1 1 1 1 1
1 1-858993460-858993460-858993460
-858993460-858993460-858993460-858993460 1
The Second Matrix Is :-
1 1 1 1 1
-858993460-858993460-858993460-858993460-858993460
-858993460-858993460 1 1 1
1 1 1 1 1
1 1 1 1 1
The Resultant Matrix Is :-
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
Another question:
if I entered to the mat1 a big string it's calculated directly without letting me enter a string to mat2 how do I solve this problem ?
int mat1[][SIZE]={ 0 }
will declare a 1x5 matrix. Change it to
int mat1[SIZE][SIZE]={ 0 }

Segfault while allotting 2D array using double dimensional pointer

I'm currently working on a codechef practice problem http://www.codechef.com/problems/STEPUP#
I'm trying to set up a 2D array using pointers to accept the data and enter in into the 2D array as i receive it using scanf.
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv)
{
int m,n,i,k,j;
int ex;
scanf("%d",&ex);
for(i=0;i<ex;i++)
{
int **edgegraph=NULL,temp1,temp2;
scanf("%d %d",&n,&m);
edgegraph=malloc(m*sizeof(int));
for(k=0;k<m;k++)
{
*(edgegraph+k)=malloc(m*sizeof(int));
if(!*(edgegraph+k))
exit(0);
}
for(k=0;k<m;k++)
{
scanf("%d %d",&temp1,&temp2);
*(*(edgegraph+m*temp1)+temp2)=1;
}
for(i=0;i<m;i++)
{
for(j=0;j<m;j++)
printf("%d ",*(*(edgegraph+m*i)+j));
printf("\n");
}
}
}
The error i get is
(gdb) run
Starting program: /home/vishwa/codechef/valid
2
2 2
1 2
Program received signal SIGSEGV, Segmentation fault.
0x000000000040079d in main (argc=1, argv=0x7fffffffded8) at validedge.c:24
24 *(*(edgegraph+m*temp1)+temp2)=1;
(gdb) quit
What I intend to do is create an m*m matrix, set all valid edges to 1 and then sort in ascending order of number of edges. I'm unsure if this will solve the problem, but would like to know where I'm messing up.
You malloc the wrong number of bytes: edgegraph=malloc(m*sizeof(int)); should have malloc(m * sizeof(int *)); . To avoid this sort of error you can use the following pattern:
ptr = malloc( N * sizeof *ptr );
which always allocates N of whatever ptr is a pointer to.
Next, the syntax x[y] is much simpler to read than *(x+y) especially when the expressions get complicated. Using that syntax would have avoided the mistake dconman points outs. You seem to have put an extra m * into your calculation where it is not required.
Also you mix up m and n later in your code. To avoid this sort of error, use more descriptive variable names.
So a fixed version of your allocation code could look like:
if ( 2 != scanf("%d %d",&num_edges, &num_vertices) )
exit(EXIT_FAILURE);
edgegraph = malloc( num_vertices * sizeof *edgegraph );
for (int vertex = 0; vertex < num_vertices; ++vertex)
{
edgegraph[vertex] = malloc( num_vertices * sizeof **edgegraph );
if ( edgegraph[vertex] == NULL )
exit(EXIT_FAILURE);
}
Note that it is possible to replace that malloc series with a single allocation:
int (*edgegraph)[num_vertices] = malloc( num_vertices * sizeof *edgegraph );
Moving onto your code to read edges. You wrote for(k=0;k<m;k++) however I think you meant n there. Using more descriptive variable names and the x[y] syntax:
for(int edge = 0; edge < num_edges; ++edge)
{
if ( 2 != scanf("%d %d",&temp1,&temp2) )
exit(EXIT_FAILURE);
if ( temp1 < 0 || temp1 >= num_vertices || temp2 < 0 || temp2 >= num_vertices )
exit(EXIT_FAILURE); // maybe display an error message
edgegraph[temp1][temp2] = 1;
edgegraph[temp2][temp1] = 1; // add this if undirected graph!
}
Now the final loop, for(i=0;i<m;i++). You have used the same variable i as control variable for this loop and for your outer loop. To avoid this sort of error, use scoped control variables:
for (int i = 0; i < num_edges; ++i)
Finally you will need to free the memory you malloc'd at the end of each time around the outer loop.
You are so close: lose the m* in your expressions to access an array element. Remember, you set up your 2d array as an array of rows, each with its own pointer (you allocated each independently).
*(*(edgegraph+m*temp1)+temp2)=1;
should be
*(*(edgegraph+temp1)+temp2)=1;
And the same change where you do that later in your code.
Is there a reason you are not using array indices?
EDIT
here is my input
2
10
10
4 3
4 9
7 3
3 7
4 3
4 5
7 4
3 5
9 0
5 2
And I got this output
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 1 0 0
0 0 0 1 0 1 0 0 0 1
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0

Using C, While initializing an array of structs, it seems like the first column, and the last column are overlooping

When main runs, I've been getting this output. The first columns being somehow confused with the last one, even though it's specifically initialized.
0 0 0 0 0 0 4 3 13 3 3 0 0 0 0 0 0
0 0 0 0 0 4 0 0 5 0 0 2 0 0 0 0 0
0 0 0 0 4 0 0 0 5 0 0 0 2 0 0 0 0
0 0 0 18 0 0 0 0 5 0 0 0 0 17 0 0 0
0 0 4 0 2 0 7 12 19 12 3 0 8 0 2 0 0
0 4 0 0 0 0 0 0 5 0 0 0 0 0 0 2 0
0 0 0 0 5 0 0 0 5 0 0 0 5 0 0 0 2
2 0 0 0 11 0 0 0 5 0 0 0 11 0 0 0 1
1 7 7 7 20 7 7 7 14 7 7 7 20 7 7 7 1
1 0 0 0 11 0 0 0 5 0 0 0 11 0 0 0 1
1 0 0 0 1 0 0 0 5 0 0 0 1 0 0 0 0
0 6 0 0 0 0 0 0 5 0 0 0 0 0 0 8 0
0 0 6 0 4 0 7 12 19 12 3 0 6 0 8 0 0
0 0 0 15 0 0 0 0 5 0 0 0 0 16 0 0 0
0 0 0 0 6 0 0 0 5 0 0 0 8 0 0 0 0
0 0 0 0 0 6 0 0 5 0 0 8 0 0 0 0 0
0 0 0 0 0 0 7 7 7 7 8 0 0 0 0 0 0
motion.h
struct square{
int directions;
int isRobotHere;
int isMultipleDirections;
int printable;
};
typedef struct square Square;
struct robot{
int robotx;
int roboty;
int robotz;
int destinationx;
int destinationy;
int destinationz;
};
typedef struct robot Robot;
enum direction{North, NorthWest, West, SouthWest, South, SouthEast, East, NorthEast};
Square firstfloor[16][16];
Square secondfloor[16][16];
void printbothfloors();
void initializeArrays();
initializeArrays.c
#include <stdio.h>
#include "motion.h"
void initializeArrays(){
firstfloor[6][0].directions=5;
firstfloor[7][0].directions=5;
firstfloor[8][0].directions=14;
firstfloor[9][0].directions=5;
firstfloor[10][0].directions=6;
firstfloor[11][1].directions=6;
firstfloor[12][2].directions=6;
firstfloor[13][3].directions=15;
firstfloor[14][4].directions=6;
firstfloor[15][5].directions=6;
firstfloor[16][6].directions=7;
firstfloor[16][7].directions=7;
firstfloor[16][8].directions=7;
firstfloor[16][9].directions=7;
firstfloor[16][10].directions=8;
firstfloor[15][11].directions=8;
firstfloor[14][12].directions=8;
firstfloor[13][13].directions=16;
firstfloor[12][14].directions=8;
firstfloor[11][15].directions=8;
firstfloor[10][16].directions=1;
firstfloor[9][16].directions=1;
firstfloor[8][16].directions=1;
firstfloor[7][16].directions=1;
firstfloor[6][16].directions=2;
firstfloor[5][15].directions=2;
firstfloor[4][14].directions=2;
firstfloor[3][13].directions=17;
firstfloor[2][12].directions=2;
firstfloor[1][11].directions=2;
firstfloor[0][10].directions=3;
firstfloor[0][9].directions=3;
firstfloor[0][8].directions=13;
firstfloor[0][7].directions=3;
firstfloor[0][6].directions=4;
firstfloor[1][5].directions=4;
firstfloor[2][4].directions=4;
firstfloor[3][3].directions=18;
firstfloor[4][2].directions=4;
firstfloor[5][1].directions=4;
firstfloor[1][8].directions=5;
firstfloor[2][8].directions=5;
firstfloor[3][8].directions=5;
firstfloor[4][8].directions=19;
firstfloor[5][8].directions=5;
firstfloor[6][8].directions=5;
firstfloor[7][8].directions=5;
firstfloor[8][8].directions=14;
firstfloor[9][8].directions=5;
firstfloor[10][8].directions=5;
firstfloor[11][8].directions=5;
firstfloor[12][8].directions=19;
firstfloor[13][8].directions=5;
firstfloor[14][8].directions=5;
firstfloor[15][8].directions=5;
firstfloor[8][1].directions=7;
firstfloor[8][2].directions=7;
firstfloor[8][3].directions=7;
firstfloor[8][4].directions=20;
firstfloor[8][5].directions=7;
firstfloor[8][6].directions=7;
firstfloor[8][7].directions=7;
firstfloor[8][9].directions=7;
firstfloor[8][10].directions=7;
firstfloor[8][11].directions=7;
firstfloor[8][12].directions=20;
firstfloor[8][13].directions=7;
firstfloor[8][14].directions=7;
firstfloor[8][15].directions=7;
firstfloor[7][4].directions=11;
firstfloor[9][4].directions=11;
firstfloor[4][7].directions=12;
firstfloor[4][9].directions=12;
firstfloor[12][7].directions=12;
firstfloor[12][9].directions=12;
firstfloor[7][12].directions=11;
firstfloor[9][12].directions=11;
firstfloor[4][4].directions=2;
firstfloor[4][6].directions=7;
firstfloor[4][10].directions=3;
firstfloor[4][12].directions=8;
firstfloor[6][4].directions=5;
firstfloor[6][12].directions=5;
firstfloor[10][4].directions=1;
firstfloor[10][12].directions=1;
firstfloor[12][4].directions=4;
firstfloor[12][6].directions=7;
firstfloor[12][10].directions=3;
firstfloor[12][12].directions=6;
firstfloor[11][0].directions=0;
firstfloor[5][16].directions=0;
}
printbothfloors.c
#include <stdio.h>
#include <stdlib.h>
#include "motion.h"
void printbothfloors(){
// printf("printfloor is running");
int upper, lower, i, j;
printf("%4d %4d %4d %4d %4d", firstfloor[6][0].directions, firstfloor[7][0].directions, firstfloor[8][0].directions, firstfloor[9][0].directions, firstfloor[10][0].directions);
printf("%4d %4d %4d %4d %4d", firstfloor[6][16].directions, firstfloor[7][16].directions, firstfloor[8][16].directions, firstfloor[9][16].directions, firstfloor[10][16].directions);
printf("FIRST FLOOR");
printf("\n-");
/* The next for loop prints out the upper edge */
for (upper = 0; upper < 18; upper++){
printf("----");
}
printf("\n");
/*The next for loop prints out the floor, every element is 4 digits wide */
for (i = 0; i <= 16; i++){
printf("|");
for(j = 0; j <= 16; j++){
printf("%4d", firstfloor[i][j].directions);
}
printf(" |\n");
}
/* The next for loop prints out the lower edge */
for (lower = 0; lower < 18; lower++){
printf("----");
}
printf("-\n");
/*
printf("SECOND FLOOR");
// printf("printfloor is running");
printf("\n-----");
// The next for loop prints out the upper edge
for (upper = 0; upper < 17; upper++){
printf("----");
}
printf("\n");
//The next for loop prints out the floor, every element is 4 digits wide
for (i = 0; i <= 16; i++){
printf("|");
for(j = 0; j <= 16; j++){
printf("%4d", secondfloor[i][j].directions);
}
printf(" |\n");
}
// The next for loop prints out the lower edge
for (lower = 0; lower < 17; lower++){
printf("----");
}
printf("-----\n");
*/
}
prog2.c
#include <stdio.h>
#include <stdlib.h>
#include "motion.h"
//#include "printbothfloors.h"
int main(){
int row = 0;
int column = 0;
initializeArrays();
// printbothfloors();
/*
for (row=0; row < 17; row++){
for (column=0; column < 17; column++){
// firstfloor[row][column].directions=0;
// secondfloor[row][column].directions=5;
//firstfloor[i][j].isRobotHere=0;
//secondfloor[i][j].isRobotHere=0;
//firstfloor[i][j].isMultipleDirections=0;
//secondfloor[i][j].isMultipleDirections=0;
}
}
firstfloor[6][0].directions=5;
firstfloor[7][0].directions=5;
firstfloor[8][0].directions=14;
firstfloor[9][0].directions=5;
firstfloor[10][0].directions=6;
firstfloor[11][1].directions=6;
firstfloor[12][2].directions=6;
firstfloor[13][3].directions=15;
firstfloor[14][4].directions=6;
firstfloor[15][5].directions=6;
firstfloor[16][6].directions=7;
firstfloor[16][7].directions=7;
firstfloor[16][8].directions=7;
firstfloor[16][9].directions=7;
firstfloor[16][10].directions=8;
firstfloor[15][11].directions=8;
firstfloor[14][12].directions=8;
firstfloor[13][13].directions=16;
firstfloor[12][14].directions=8;
firstfloor[11][15].directions=8;
firstfloor[10][16].directions=1;
firstfloor[9][16].directions=1;
firstfloor[8][16].directions=1;
firstfloor[7][16].directions=1;
firstfloor[6][16].directions=2;
firstfloor[5][15].directions=2;
firstfloor[4][14].directions=2;
firstfloor[3][13].directions=17;
firstfloor[2][12].directions=2;
firstfloor[1][11].directions=2;
firstfloor[0][10].directions=3;
firstfloor[0][9].directions=3;
firstfloor[0][8].directions=13;
firstfloor[0][7].directions=3;
firstfloor[0][6].directions=4;
firstfloor[1][5].directions=4;
firstfloor[2][4].directions=4;
firstfloor[3][3].directions=18;
firstfloor[4][2].directions=4;
firstfloor[5][1].directions=4;
firstfloor[1][8].directions=5;
firstfloor[2][8].directions=5;
firstfloor[3][8].directions=5;
firstfloor[4][8].directions=19;
firstfloor[5][8].directions=5;
firstfloor[6][8].directions=5;
firstfloor[7][8].directions=5;
firstfloor[8][8].directions=14;
firstfloor[9][8].directions=5;
firstfloor[10][8].directions=5;
firstfloor[11][8].directions=5;
firstfloor[12][8].directions=19;
firstfloor[13][8].directions=5;
firstfloor[14][8].directions=5;
firstfloor[15][8].directions=5;
firstfloor[8][1].directions=7;
firstfloor[8][2].directions=7;
firstfloor[8][3].directions=7;
firstfloor[8][4].directions=20;
firstfloor[8][5].directions=7;
firstfloor[8][6].directions=7;
firstfloor[8][7].directions=7;
firstfloor[8][9].directions=7;
firstfloor[8][10].directions=7;
firstfloor[8][11].directions=7;
firstfloor[8][12].directions=20;
firstfloor[8][13].directions=7;
firstfloor[8][14].directions=7;
firstfloor[8][15].directions=7;
firstfloor[7][4].directions=11;
firstfloor[9][4].directions=11;
firstfloor[4][7].directions=12;
firstfloor[4][9].directions=12;
firstfloor[12][7].directions=12;
firstfloor[12][9].directions=12;
firstfloor[7][12].directions=11;
firstfloor[9][12].directions=11;
firstfloor[4][4].directions=2;
firstfloor[4][6].directions=7;
firstfloor[4][10].directions=3;
firstfloor[4][12].directions=8;
firstfloor[6][4].directions=5;
firstfloor[6][12].directions=5;
firstfloor[10][4].directions=1;
firstfloor[10][12].directions=1;
firstfloor[12][4].directions=4;
firstfloor[12][6].directions=7;
firstfloor[12][10].directions=3;
firstfloor[12][12].directions=6;
firstfloor[11][0].directions=0;
firstfloor[5][16].directions=0;
*/
// for (i = 0; i < 17; i++){
// firstfloor
// printbothfloors();
// pbf_entrypoints();
/*
row = 0;
column = 0;
while (i < 17){
firstfloor[i][8] = 1;
secondfloor[i][8] = 1;
firstfloor[8][i] = 1;
secondfloor[8][i] = 1;
i++;
}
*/
printf("Function got here");
printbothfloors();
return 0;
}
Valid indices for Type arr[N] are between 0 and N-1.
This goes for any Type and for any number of dimensions.
Indexes in C start at 0, so if you declare an array to have 16 elements, valid indexes start from 0 and end at 15.
16 boxes, numbered 0 to 15:
---------------------------------------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---------------------------------------------------------------------------------
Accessing an element outside of this range (e.g. by using the index -1 or 16) invokes undefined behaviour.
Both the first answers are correct, I'll add some examples from your code.
firstfloor[6][16].directions
firstfloor[x][y], has been initialized as firstfloor[16][16] meaning the values x and y can can from 0 to 15. The numbering system is 0 based, a hang-over from Java's C language ancestry. 0-15 covers 16 elements.
/*The next for loop prints out the floor, every element is 4 digits wide */
for (i = 0; i <= 16; i++){
printf("|");
for(j = 0; j <= 16; j++){
printf("%4d", firstfloor[i][j].directions);
}
printf(" |\n");
}
The two for loops, start correctly at i = 0 and should only continue while i < 16 or if you prefer i <= 15.
At the moment I'm personally jumping between Java, C and Python, so someone might correct me in this, but calling firstfloor[6][16] if it does not generate an array out-of-bounds error, will give you the same result as firstfloor[7][0]. This might explain why you are observing the first columns being confused with the last.
Good luck :-)

Extra edge in my list?

I'm writing code to create a matrix out of a list of edges.
However, when I run said code, I get a "phantom edge" that is not in the input data, which goes on to screw up the rest of my program. The edge is 9,2 in the matrix, or 8,1 in elemental code form.
All elements in the matrix are initialized to 0 before hand.
Here is the input data to do with the matrix:
1 2
1 8
2 8
3 5
3 1
4 5
4 6
5 2
5 9
6 4
6 8
7 4
7 10
8 4
8 6
9 4
9 5
10 7
10 3
Here are the functions that handle the input:
void displayMatrix(int **matrix, int numberVertices){ //function displays the matrix
int i, j;
for(i=0; i<numberVertices; i++) //go through eveyr element
{
for(j=0; j<numberVertices; j++)
{
printf("%d ", matrix[i][j]); //print element
}
printf("\n");
}
printf("\n\n");
}
void inputMatrix(FILE *fp, int ** matrix) //file places value 1 into matrix if edge exists for the adjacency matrix
{
int e1, e2;
while(!feof(fp)) //continue to the end of the file
{
fscanf(fp, "%d %d", &e1, &e2); //get pairs
e1 = e1 - 1; //adjust the edges for array use
e2 = e2 - 1;
matrix[e1][e2] = 1; //place value 1 into appropriate location in adjacency matrix
}
fclose(fp); //close the file connection
}
0 1 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1 0 0
1 0 0 0 1 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 1 0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 1 0 0
0 0 0 1 0 0 0 0 0 1
0 0 0 1 0 1 0 0 0 0
0 *1 0 1 1 0 0 0 0 0
0 0 1 0 0 0 1 0 0 0
*the entry that should not exist, not in the input data
The problem is that you're looping one more additional time than necessary, causing fscanf to fail before the first conversion and thus leaving e1 and e2 as they were from the prior read. As it turns out, the last entry has e1 set to 10 and e2 to 3, so e1 becomes 9 and e2 becomes 2, thus causing your phantom edge.
The cause of this additional loop is because your loop condition doesn't do what you think it does. feof checks if the end-of-file flag has been set, and this can only be set when attempting to read at the end of the file. Since you're checking for end-of-file before your read, you're not actually picking up on this until the next iteration, thus you loop an additional time. The proper correction is very simple; just continue until fscanf results in EOF.
while (fscanf(fp, "%d %d", &e1, &e2) != EOF)
{
matrix[e1 - 1][e2 - 1] = 1;
}
As pointed out in the comments, you're not testing for errors in fscanf.
In particular, you have not yet reached the end of file after reading 10 3, presumably because a newline was encountered.
However, in the next time around fscanf will return zero. Then you subtract 1 from those values (which were not read) to get 9 2.
You can make sure that two integers were read by doing this:
if( 2 != fscanf(fp, "%d %d", &e1, &e2) ) break;
You can try this:
fscanf(fp, "%d %d\n", &e1, &e2);
When you finish the last two digit, there is one more \n,the loop have to continue,this will make trouble

Resources