Reputation: 9205
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
Reputation: 424
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 int
s. 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 int
s, to int **
, which would be an array of arrays of int
s.
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 **
.
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.
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
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