cclloyd
cclloyd

Reputation: 9205

Subscripted value not array nor pointer

I have a program that reads a 2d array from a file, and makes it a jagged array (where each row is sized perfectly to fit all non-zero elements). Then it prints the array out.

But I have a couple issues I can't figure out.

Specifically

26: I get a warning (assignment makes integer from pointer without cast

44: error: subscripted value is neither array not pointer

What can I do to fix it?

int main() {

FILE *inputFile1 = fopen("denseMatrix1.txt", "r");

char inputBuffer[SIZE];
int dim1, dim2, input, i, j;
int *mtrx1;

fgets(inputBuffer, SIZE, inputFile1);
sscanf(inputBuffer, "%d%d", &dim1, &dim2);

mtrx1 = malloc(sizeof(int *) * dim1);

for (i=0; i<dim1; i++) {
    int cols=0;
    int *row = malloc(sizeof(int) * cols);
    fgets(inputBuffer, SIZE, inputFile1);
    for (j=0; j<dim2; j++) {
        sscanf(inputBuffer, "%d", input);
        printf("i=%d   j=%d    input=%d\n", i, j, input); // ADDED LINE (NOT PRINTING)
        if (input) {
            cols++;
            row = realloc(row, sizeof(int) * cols);
            row[cols-1] = input;
        }
    }
    mtrx1[i] = row;
    cols=0;
}

int mtrx3[DIM1][DIM2] = {0};

// Prints first 2 matrices
printf("First matrix: \n");
printMatrix(mtrx1, dim1);/*

return 0;


// Prints a 2d array matrix
void printMatrix(int *mtrx, int dim1) {
int i, j;
for (i=0; i<dim1; i++) {
    for (j=0; j<(sizeof(mtrx[i]) / sizeof(int)); j++) {
        printf("%d ", mtrx[i][j]);
    }
    printf("\n");
}
printf("\n\n");

Contents of file denseMatrix1.txt:

7 8
0 0 0 5 1 0 0 5
0 0 0 0 0 0 0 0
0 0 0 0 1 2 0 0
1 0 0 0 0 0 0 0
3 0 0 5 0 0 3 0
1 0 0 0 0 3 0 0
0 0 0 0 0 0 0 1

Upvotes: 0

Views: 106

Answers (2)

gntskn
gntskn

Reputation: 424

Line 26 Warning

Here is the line in question:

mtrx1[i] = row;

And here are the declarations for these variables:

int *mtrx1;
int ..., i, ...;
int *row = ...;

As your warning message says, you are trying to take a pointer value, row, and assign it to an array of ints. Assuming that what you want is mtrx1 to be an array of individual row sub-arrays, you should change its type accordingly – from int *, which is an array of ints, to int **, which would be an array of arrays of ints.

Line 44 Error

Relevant code:

void printMatrix(int *mtrx, int dim1) {
    int i, j;
    ...
    printf("%d ", mtrx[i][j]); // line 44
    ...
}

The error on this line is the result of a problem similar to the one above – mtrx is declared as a one-dimensional array of int, but in line 44 you have two subscripts as if it is a two-dimension array. This is also fixed by changing the type of mtrx to int **.

For Loop

The for loop is failing to iterate over all values because your sscanf line is ambiguous – there's no space between your %d values, and so sscanf can't tell which number should be which, and it reads them through as one value. This means dim2 is never properly set.

For this sort of bug, using breakpoints is the usually the easiest way to get an idea of what's going on in the program, particularly for loops. If you haven't looked into them yet, you should.

Additional Info

Line 26 gives you a warning while line 44 gives you an error because of the way pointers are defined in relation to ints in C. C allows for "pointer arithmetic," which means pointers can be treated as plain numbers in addition to referring to objects or arrays.

When you subscript an array in C, the type of the expression effectively just drops a *; for example, subscripting a int * array has a type of int. So when you try to assign a pointer to int *mtrx1, it treats it like trying to assign a pointer to an int variable, and so the pointer gets converted to its raw numeric value. This is perfectly legal C, but is considered by most programmers to be fairly bad practice (for various reasons), and so the compiler gives you a warning for it.

Line 44 is sort of the opposite case – your mtrx[i][j] expression is equivalent to (mtrx[i])[j]. Since mtrx is defined as just a int *, this means you effectively end up trying to subscript an int, which is flat out illegal in C. No warning, just an error.

Upvotes: 0

R Sahu
R Sahu

Reputation: 206577

In stead of

int *mtrx1;

use

int **mtrx1;

With the former declaration, mtrx[i] evaluates to int. You need it to evaluate to int* to be able to use:

mtrx1[i] = row;

Update

Your strategy of using fgets to get a line of text and using the line of text with sscanf is not going to work in a for loop.

Let's take the first line of the matrix:

0 0 0 5 1 0 0 5

and the for loop:

for (j=0; j<dim2; j++) {
    sscanf(inputBuffer, "%d", input);
    printf("i=%d   j=%d    input=%d\n", i, j, input); // ADDED LINE (NOT PRINTING)
    if (input) {
        cols++;
        row = realloc(row, sizeof(int) * cols);
        row[cols-1] = input;
    }
}

In the for loop, you will end up 0 being assigned to input every time for the first line. sscanf does not store what you read the first time and continue from what's left.

You'll need to come up with a different strategy. For example:

for (i=0; i<dim1; i++) {
   int cols=0;
   int *row = malloc(sizeof(int) * cols);
   fgets(inputBuffer, SIZE, inputFile1);
   char* token = strtok(inputBuffer, " \n");
   for (j=0; j<dim2; j++) {
      input = atoi(token);
      printf("i=%d   j=%d    input=%d\n", i, j, input);
      if (input) {
         cols++;
         row = realloc(row, sizeof(int) * cols);
         row[cols-1] = input;
      }
      token = strtok(NULL, " \n");
   }
   mtrx1[i] = row;
   cols=0;
}

Upvotes: 1

Related Questions