Row-major ordering in C as Command Line Argument

169 views Asked by At

I need to pass in a 2D area (a matrix) from the command line through a txt file that looks like this:

0 0 0 0 0
0 1 1 0 0 
0 0 1 0 0 
0 0 1 0 0
0 0 0 0 0

I'm using C and need to have it in row-major order, so I'm trying to do this:

int matrix[][] = argv[2]; // it is the second command line argument passed

This isn't working, is it because it needs to be a 1-dimensional array? Am I only allowed to use a regular 1D array for row-major ordering? The error I'm getting is "array type has incomplete element type 'int[]' "

2

There are 2 answers

8
bruno On BEST ANSWER

I'm trying to do this:

int matrix[][] = argv[2]

This isn't working,

because this is invalid, out of the missing ';' :

  • at least the second dimension must be given, this is why you have the error array type has incomplete element type 'int[]'
  • matrix is a (wrongly defined) 2D array of int but in the best case argv[2] is an array of char :
    • if the program is called without argument argv[2] is undefined
    • if the program is called with one argument argv[2] is NULL
    • if the program is called with at least 2 argument argv[2] is the string containing the second arg

Considering argv[2] is the pathname of the file containing the 5x5 matrix the declaration of the matrix can be :

int matrix[5][5];

and you need to read the values in the file to set the matrix's content, you cannot directly map the txt file to matrix

Example :

#include <stdio.h>

int main(int argc, char ** argv)
{
  FILE * fp;

  if (argc < 3) {
    fprintf(stderr, "usage: %s ?? <file>\n", *argv);
    return -1;
  }
  else if ((fp = fopen(argv[2], "r")) == NULL) {
    perror("cannot open file");
    return -1;
  }
  else {
    int matrix[5][5];
    int i, j;

    for (i = 0; i != 5; ++i) {
      for (j = 0; j != 5; ++j) {
        if (fscanf(fp, "%d", &matrix[i][j]) != 1) {
          fprintf(stderr, "invalid file for [%d][%d]\n", i, j);
          return -1;
        }
      }
    }

    fclose(fp);

    /* debug */
    for (i = 0; i != 5; ++i) {
      for (j = 0; j != 5; ++j)
        printf("%d ", matrix[i][j]);
      putchar('\n');
    }

    putchar('\n');

    /* you can also use it as a 1D array */
    for (i = 0; i != 25; ++i) {
      printf("%d ", ((int *) matrix)[i]);
      if (i%5 == 4)
        putchar('\n');
    }

    return 0;
  }
}

Compilation and execution:

pi@raspberrypi:/tmp $ gcc -Wall a.c
pi@raspberrypi:/tmp $ cat f
0 0 0 0 0
0 1 1 0 0 
0 0 1 0 0 
0 0 1 0 0
0 0 0 0 0
pi@raspberrypi:/tmp $ ./a.out whatever f
0 0 0 0 0 
0 1 1 0 0 
0 0 1 0 0 
0 0 1 0 0 
0 0 0 0 0 

0 0 0 0 0 
0 1 1 0 0 
0 0 1 0 0 
0 0 1 0 0 
0 0 0 0 0 
pi@raspberrypi:/tmp $ 
0
Hitokiri On

As the answer of @bruno, you were wrong when declare the 2D array. I just propose one solution to get info from input file with double pointer (use it if you do not know the size of array before (number of lines, number of cols).

You can use fgets to get line by line in the text file. Then using the strtok function to separate the line by space. To get the integer value from string, you can use atoi function.

The complete code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    char line[256];
    int ** matrix = malloc(sizeof(int *));
    if(!matrix)
        return -1;
    if (argc < 2) {
        return -1;
    // argv[1] is the name of input file, for example input.txt
    FILE * fp = fopen(argv[1], "r");
    int row = 0, col;
    while(fgets(line, sizeof(line), fp)) {
        col = 0;
        matrix[row] = malloc(sizeof(int));
        if(!matrix[row])
            return -1;
        char * token = strtok(line, " ");

        while(token != NULL) {
             matrix[row][col] = atoi(token);
             token = strtok(NULL, " ");
             col++;
             // increase the size of each line after each loop
             matrix[row] = realloc(matrix[row], (col+1) * sizeof(int));
             if(!matrix[row])
                return -1;
        }
        row++;
        // increase size of matrix after each loop
        matrix = realloc(matrix, (row+1)*sizeof(int *));
        if(!matrix)
            return -1;
    }

    for(int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            printf("%d ", matrix[i][j]);
        }

        printf("\n");
    }
    return 0;
}

The test:

#cat input.txt
0 0 0 0 0 
0 1 1 0 0 
0 0 1 0 0 
0 0 1 0 0 
0 0 0 0 0

./test input.txt
0 0 0 0 0 
0 1 1 0 0 
0 0 1 0 0 
0 0 1 0 0 
0 0 0 0 0