I was playing around with pointers when inputing a matrix with scanf and for some reason, when I run this code, only the first element of every row gets stored correctly.
#include "stdio.h"
void main()
{
int i, j, n, A[10][10];
scanf("%d", &n);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", A + j + i*10);
}
This is what I get after inputing 1,2,3,4,5,6,7,9 into a 3x3 matrix and printing it:
1 -858993460 -858993460
2 -858993460 -858993460
3 -858993460 -858993460
According to my understanding of how matrices are stored, this should work. Can anyone point out whats wrong with my code?
You declare A as
int A[10][10];
that is, an array of 10 arrays of 10 ints each. Thus, when A decays to a pointer to its first element, the type of that pointer is int (*)[10]. That's a pointer to an array of 10 ints, not a pointer to a single int. Among the differences is their interaction with pointer arithmetic. Because pointer arithmetic is defined in terms of the size of the pointed-to type, whenever i is nonzero, the expression A + j + i*10 produces a pointer (to array of 10 ints) outside the bounds of array A.
The most type-safe way of doing what you want would be to use array syntax to select array elements:
&A[i][j]
. Type-correct alternatives that use pointer arithmetic include
&(*(A + i))[j]
and
*(A + i) + j
These latter two both rely on the fact that the expression A + i is a pointer to an array of int; dereferencing that pointer produces an array, which can be the operand of the [] operator (and the address of the result then taken). Alternatively, the array designated by *(A + i) decays to a pointer to its first element (i.e. decays to an int *) when it appears as an operand of the + operator, and adding j to that yields a pointer to the jth element of array *(A + i) (which is the same array designated by A[i]).
Bad pointer math.
A + j + i * 10
When A is used in A + j + i*10, it becomes the pointer to its first element, which is an array of 10 int. Every 1 added to A offsets its address by 40 bytes.
Recommend to use &A[i][j] instead.
Code re-worked to show addresses used.
#include "stdio.h"
int main() {
int i, j, n, A[10][10];
n = 3;
char *base = (char*) A;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++) {
char *offset0 = (char*) (&A[i][j]);
char *offset1 = (char *) (A + j + i * 10);
printf("%d %d %3td %3td\n", i, j, offset0 - base, offset1 - base);
}
}
Output
0 0 0 0
0 1 4 40
0 2 8 80
1 0 40 400
1 1 44 440
1 2 48 480
2 0 80 800
2 1 84 840
2 2 88 880
Related
So my book is explaining me pointers to an array using ts example
#include <stdio.h>
int main()
{
int s[4][2] = {
{1234,56},{1212,33},{1434,80},{1312,78}
};
int(*p)[2];
int i, j, * pint;
for (i = 0; i <= 3; i++)
{
p = &s[i];
pint = (int*)p;
printf("\n");
for (j = 0; j<= 1; j++)
{
printf("%d ", *(pint + j));
}
}
return 0;
}
The output is Given as
1234 56
1212 33
1434 80
1312 78
No issue I am getting the same output.
My question is what was the need of using another pointer pint ?
Why can't we directly use P?
So When I tried to do it using P directly it didn't work
printf("%d ", *(p + j));
I got garbage values in output, Why is this happening?
I also tried printing p and pint they are the same.
Although p and pint have the same value, p + 1 and pint + 1 do not. p + 1 is the same as (char *)p + sizeof *p, and pint + 1 is the same as (char *)pint + sizeof *pint. Since the size of the object pointed to is different, the arithmetic gives different results.
The pointer p is declared like
int(*p)[2];
So dereferencing the pointer expression with the pointer in this call of printf
printf("%d ", *(p + j));
you will get the j-th "row" of the type int[2] of the two dimensional array that in turn will be implicitly converted to a pointer of the type int * that will point to the first element of the j-th "row".
So instead of outputting elements of each row you will output first elements of each row that moreover results in undefined behavior when i will be greater than 2.
int *A [10];
why A[2][3] is a valid lvalue. As I understand in A[2] we store a pointer to an integer(Single integer not an array). So how can [3] in A[2][3] access it?
Hopefully this code can demonstrate how int pointer arrays can be used.
The goal is to create a buffer big enough to hold 30 integers. Then assign an int pointer to every 3rd address division of the allocated buffer.
So if a[0] is set to address 0x562437eea260.
Then that means a[1] will be set to address 0x562437eea26c approximately (sizeof(int) * 3), 12, bytes away.
Then the values at the pointer's address can be set by calling a[i][j]; assuming i is the index that chooses the address from the int pointer array and j is either 1, 2, or 3 depending on what number you wish to access.
Expected Output:
a[0] = 0x562437eea260
a[0][0] = 2
a[0][1] = 3
a[0][2] = 5
a[1] = 0x562437eea26c
a[1][0] = 3
a[1][1] = 3
a[1][2] = 7
a[2] = 0x562437eea278
a[2][0] = 9
a[2][1] = 2
a[2][2] = 3
In my example, I set all integers to random values
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define UNUSED(x)((void)(x))
#define TOTAL_INT_POINTERS 10
#define INTS_PER_POINTER 3
int main(const int argc, const char** const argv, const char** const envp) {
UNUSED(argc); UNUSED(argv); UNUSED(envp);
// Seed random number generator
srand((unsigned int)time(0));
// Create and array that will hold 10 int pointers
int *a[TOTAL_INT_POINTERS] = {0};
// Allocate memory for integers
int *ptr = (int *)malloc((sizeof(int) * TOTAL_INT_POINTERS) * INTS_PER_POINTER);
if(ptr == NULL) {
fprintf(stderr, "Failed to allocate memory for integers!\n");
return (int)EXIT_FAILURE;
}
// Assign pointers and values to each allocated space
for(unsigned int i = 0; i < TOTAL_INT_POINTERS; i++) {
// Assign pointer array member
a[i] = ptr + (i * INTS_PER_POINTER);
// Print assigned address
printf("a[%d] = %p\n", i, a[i]);
// Give 3 integers their values and print out the result
for(unsigned int j = 0; j < INTS_PER_POINTER; j++) {
a[i][j] = rand() % 10;
printf("a[%d][%d] = %d\n", i, j, a[i][j]);
}
putchar('\n');
}
// Free up used memory
free(ptr);
return (int)EXIT_SUCCESS;
}
As already pointed out in the comments, the compiler manages only the pointer and is not aware of the actual structure of your data. You can access array elements by index using square brackets or by using pointer arithmetics:
A[i][j] is equivalent to *(A[i] + j) and also equivalent to *(*(A+i) + j).
Note that you must ensure that the memory you are accessing is actually within the array bounds.
Further reading:
Multidimensional Pointer Arithmetic in C/C++
How to access two dimensional array using pointers in C programming?
The fact that x points to an int does not mean there are not more int next to that int, either before or after it or both.
If I have an array int a[10], then &a[5] points to element 5 of the array, and &[5] - 1 and &a[5] + 1 point to elements 4 and 6. If I pass &a[5] to a subroutine as its parameter int *x, and that subroutine knows other elements exist, it may use x[1] to refer to element 6 of the array and x[-1] to refer to element 4.
Given int *A[10], I can allocate as much memory as I want and assign its address to A[0]. Then A[0][0] points to space for the first int in that memory, A[0][1] points to space for the next int, and so on.
This is my C code and and .txt file. I want to use 2d-array from .txt file as a function argument. However, when I run this code, program gives error at the call function lines such:
[Error] cannot convert 'int (*)[C]' to 'int (*)[3]' for argument '1' to 'int rec_ped(int (*)[3], int)'.
Other words, my function rec_ped cannot accept the 2d-array from .txt file.
Could you help me about this?
#include <stdio.h>
int rec_ped(int k[18][3], int idx) {
int sire, dam;
sire = k[idx - 1][1];
dam = k[idx - 1][2];
printf("%d ", sire);
if (sire != 0)
rec_ped(k, sire);
if (dam != 0)
rec_ped(k, dam);
}
int main() {
int R = 18;
int C = 3;
int A[R][C];
FILE *fp;
int i, j;
fp = fopen("t.txt", "r");
for (i = 0; i < R; i++) {
for (j = 0; j < C; j++) {
fscanf(fp, "%d", &A[i][j]);
}
}
for (i = 0; i < R; i++) {
for (j = 0; j < C; j++) {
A[i][j];
rec_ped(A, 18); // <--- there is error!!!
}
}
return 0;
}
my file is a.txt as below;
1 0 0
2 0 0
3 0 0
4 0 0
5 0 0
6 1 3
7 1 5
8 0 2
9 4 6
10 0 0
11 1 0
12 4 10
13 7 11
14 1 6
15 13 0
16 1 15
17 4 14
18 16 17
When an array decays to a pointer, it only applies to the outermost array dimension. It does not apply to inner dimensions. So int (*)[3] and int (*)[C] are not the same, even though C happens to be 3 at the time the function is called. A fixed size array and a variable length array can't be considered the same in this situation.
What you can do however is pass the dimensions of an array as parameters:
int rec_ped(int rows, int cols, int k[rows][cols], int idx) {
Then you can call it like this:
rec_ped(R, C, A, 18);
Make C a constant (#define C 3)!
Problem is: Without C being constant, but a variable, it could have been modified before declaring the array, so the latter actually is a VLA. The function, in contrast, expects a fixed size array, so types don't match.
Be aware you don't have to make R constant:
int rec_ped(int k[18][3], int idx);
is equivalent to
int rec_ped(int k[][3], int idx);
which is equivalent to
int rec_ped(int (*k)[3], int idx);
i. e. the function actually accepts a pointer to an array of length 3 just like void f(int*); accepts a pointer to int. In both cases, the pointer could reference the first element of an array (array of array or array of int respectively) or just a single element...
C allows passing arrays to functions using the array name directly. Since the array name is the starting address of the array (address of element [0]) - this is passing by reference - hence even local array can be passed this way - and the changes of either function will be visible to the other without any need of explicit return.
What I understand so far is -
The function call just needs to include the name of the array which provides the starting address - and the integer size of each dimension as separate int arguments - this way any function other than the function that contains array definition - has all the information of arrays location and size (array size as well as size of each dimension) and can operate on any element. Once again, since this is pass by reference, any such change will be visible to all such functions including and from the one containing array definition (it will need to pass the same information as arguments to each function - the array name for starting address and each dimension size) , without any return required specifically for these changes to be visible to all functions including the calling function.
The array argument in the function prototype and function definition specifies the array with a pair of square braces for each dimension + in the same argument - the largest ? value for each dimension except the most significant one (rows in a 2-D array) is also specified eg -
//Prototype
return_type function_name ( array_name[][MAX_COLS], int rows, int cols);
// Function call somewhere
function_name (array_name, num_rows, num_columns); /* array name refers
to starting address */
Also for the dimensions for which the largest ? value is specified in prototype and definition (MAX_COLS for our example), the actual value during call, specified as a separate argument (cols), may and will mostly be different.
I do not know why the size is required for other dimensions (MAX_COLS) and it will be very kind of someone to explain. Also please correct, confirm, improve everything as necessary.
Example Code with 1-D array of pointers to model a 2-D array -
#define MAX_ROWS 20
extern void modify( int rows, int cols, int *a[]);
extern void input_2d_array(int rows, int cols, int *a[]);
extern void output_2d_array(int rows, int cols, int *a[]);
int main()
{
int rows = 4, cols = 3;
int* a[MAX_ROWS], i;
for (i=0; i<rows; i++)
a[i] = (int*) malloc ( cols*sizeof(int) );
input_2d_array(rows, cols, a);
printf("Initially in main array = \n");
output_2d_array(rows, cols, a);
modify(rows, cols, a);
printf("Finally in main array = \n");
output_2d_array(rows, cols, a);
_getch();
return 0;
}
void input_2d_array(int rows, int cols, int *a[])
{
int i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
{
printf("Please enter the elements for row %d and column %d of a \n", i + 1, j + 1);
scanf_s(" %d", (a+(i*cols)+j) );
}
return;
}
void output_2d_array(int rows, int cols, int *a[])
{
int i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
printf(" %d", *(a + (i*cols) + j) );
}
printf("\n");
}
return;
}
void modify(int rows, int cols, int *a[])
{
int i, j;
printf("Initally in modify array = \n");
output_2d_array(rows, cols, a);
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
*(a + (i*cols) + j) = (*(a + (i*cols) + j)) + 2;
// *(*(a + i) + j) += 2; // Gives exception
// *(a[i]+j) += 10; // Gives exception
}
}
printf("Finally in modify array = \n");
output_2d_array(rows, cols, a);
return;
}
There are some misunderstandings. It is going to take time to explain them.
Fixed width arrays
Your example prototype is (more or less):
//Prototype
ReturnType function_name(ArrayType array_name[][MAX_COLS], int rows, int cols);
Somewhere, you have a constant definition for MAX_COLS; for sake of argument, it can be:
enum { MAX_COLS = 64 };
This function only accepts arrays that have MAX_COLS columns, though the arrays can have any number of rows. The int cols argument is immaterial to this array's definition. In the calling code, the array must be defined with MAX_COLS (or its equivalent) as the second dimension.
Inside the function, the compiler will interpret a reference array_name[i][j] (i and j being integer types) as:
*(array_name + (i * MAX_COLS + j))
It will never use cols in that calculation. An attempt to pass an array with a different row width to the function leads to — I'm going to call it 'undefined behaviour', though there might strictly be a different interpretation for which sort of undesirable and incompletely specified behaviour is applicable. The result is not going to be what you expect. If you pass a narrower array, you may well index out of bounds of the actual array; if you pass a wider array, you probably won't run out of bounds, but (as when accessing out of bounds), you won't be accessing the elements you expect to access because the computation will be based on MAX_COLS, not the function argument cols.
Variable length arrays
Using a variable length array (VLA), you could revise your function to:
ReturnType function_name(int rows, int cols, ArrayType array_name[rows][cols]);
Note that the size variables must be defined before they are used; the size parameters must precede their use in an array definition.
Now, inside the function, the compiler will interpret array_name[i][j] (as before) as:
*(array_name + (i * cols + j))
You can pass any shape of array as long as you get the rows and cols parameters correct.
There are a variety of other notations that could be used in the prototype for the function taking a VLA, including these:
ReturnType function_name(int rows, int cols, ArrayType array_name[*][*]);
ReturnType function_name(int rows, int cols, ArrayType array_name[][*]);
However, the function definition would need to have cols appear before the array definition:
ReturnType function_name(int rows, int cols, ArrayType array_name[rows][cols]) { … }
ReturnType function_name(int rows, int cols, ArrayType array_name[][cols]) { … }
And with the 'unsized' leading dimension, you could (if you were perverse enough) write:
ReturnType function_name(int cols, ArrayType array_name[][*], int rows);
ReturnType function_name(int cols, ArrayType array_name[][cols], int rows) { … }
My own view is that it is simpler to maintain the code if the function prototype declaration exactly matches the function definition line, so I'd not use the notations with * in the prototypes. I'd also use the explicit ArrayType array_name[rows][cols] notation, indicating which parameter specifies each size. This matters if you do a matrix multiplication function, for example:
void MatrixMultiply(int r1, int c1, int c2,
Data m1[r1][c1], Data m2[c1][c2], Data result[r1][c2]);
Whether the compiler will report problems with matrix size mismatches is open to debate, but the opportunity is there. If you prefer, you could have a redundant r2 parameter to specify the row size of the m2 matrix, but then you've got problems if r2 != c1, and it is harder for the compiler to help — you're reduced to assertions or other error reporting mechanisms to indicate that nothing useful was done to the result because the matrix sizes were not compatible for multiplication.
I'm not sure whether I've deconstructed all the misunderstandings in your question; I suspect not.
Arrays of pointers vs 2D arrays
From a comment:
If my function signature is void modify(int rows, int cols, int *a[]) then how do I access a[i][j] and &a[i][j] in the called function?
This requires an array of pointers to int, so you have to set up the array differently from before (in the calling code). However, inside the function,
you simply write:
int x = a[i][j];
int *y = &a[i][j];
int *z = a[i] + j;
The expressions for y and z are equivalent; I'd probably use the former.
Note that the 'behind the scenes' calculation for x is different here from the formula used for a[i][j] when passing an array:
int x = *(*(a + i) + j);
There are two memory references, the first to read the pointer a[i], and the second to read a[i][j] (with two explicit additions but no explicit multiplication, though the subscript additions have to be scaled by the size of int * and int), whereas with the array notation, there was only one memory reference (with two explicit additions and one explicit multiplication — and only one scaling operation by the size of int).
The same comment also says:
I tried a[i]+j and (a[i]+j) combination as well as *(a+(i*cols)+j) and (a+(i*cols)+j) and none is working.
There's a good chance I've not managed to add * symbols in the right places, especially in the 'as well as' portion of the sentence. Please provide the correct notation in a new extra (or replacement) comment, and I can dissect what you actually typed rather than what I'm guessing you typed.
The value of a[i] + j should give you a pointer to the jth integer in the ith row of the data. You'd have to wrap that as *(a[i] + j) to get the int value. The parenthesized version also gives you the pointer to element a[i][j]; you need a * in front to get the value.
The variations like *(a+(i*cols)+j) are wrong because in this context, you do not need to multiply by the number of columns. There's no requirement the consecutive rows pointed at by a[i] and a[i+1] are contiguous in memory; they could be located in multiple disjoint blocks of memory (and in fact there could be multiple pointers to a single block of memory, too). Within a row, the elements must be contiguous, of course.
It's roughly the difference between int a[][4]:
+---+---+---+---+
| 2 | 3 | 5 | 7 |
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
| 7 | 5 | 3 | 2 |
+---+---+---+---+
| 9 | 8 | 7 | 6 |
+---+---+---+---+
and int *a[]:
+------------+ +---+---+---+---+
| 0x010C0304 |------>| 2 | 3 | 5 | 7 |
+------------+ +---+---+---+---+
| 0x020D0408 |------>| 1 | 2 | 3 | 4 |
+------------+ +---+---+---+---+
| 0x030E050C |------>| 7 | 5 | 3 | 2 |
+------------+ +---+---+---+---+
| 0x040F0600 |------>| 9 | 8 | 7 | 6 |
+------------+ +---+---+---+---+
Note that more storage is required to hold the int *a[] data than int a[][4].
Also note that I've made the 4 arrays of numbers in the int *a[] non-contiguous. Also, the rows in the int *a[] example could be of different lengths, provided you know how to access the length (or the lengths are all at least 4 and you don't go beyond the fourth element).
Adapting the MCVE from the question
As I said in the previous section, when you are using an 'array of pointers' notation, using cols in the subscript calculation is wrong. Here's an adaptation of your code — I've had to remove the Windows-specific features such as _getch() and scanf_s() (using 'nothing' and scanf() instead). I've also shown some alternatives; the printing shows some of the alternatives.
#include <stdio.h>
#include <stdlib.h>
#define MAX_ROWS 20
extern void modify(int rows, int cols, int *a[]);
extern void input_2d_array(int rows, int cols, int *a[]);
extern void output_2d_array(int rows, int cols, int *a[]);
int main(void)
{
int rows = 4, cols = 3;
int *a[MAX_ROWS], i;
for (i = 0; i < rows; i++)
a[i] = (int *)malloc(cols * sizeof(int));
input_2d_array(rows, cols, a);
printf("Initially in main array =\n");
output_2d_array(rows, cols, a);
modify(rows, cols, a);
printf("Finally in main array =\n");
output_2d_array(rows, cols, a);
//_getch();
return 0;
}
void input_2d_array(int rows, int cols, int *a[])
{
int i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
printf("Please enter the elements for row %d and column %d of a\n", i + 1, j + 1);
//scanf_s(" %d", (a + (i * cols) + j));
//scanf(" %d", (a + (i * cols) + j));
scanf(" %d", &a[i][j]);
//scanf(" %d", a[i] + j);
//scanf(" %d", *(a + i) + j);
}
}
}
void output_2d_array(int rows, int cols, int *a[])
{
int i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
//printf(" %d", *(a + (i * cols) + j));
printf(" %d", a[i][j]);
printf(" (%d)", *(*(a + i) + j));
}
printf("\n");
}
}
void modify(int rows, int cols, int *a[])
{
int i, j;
printf("Initally in modify array =\n");
output_2d_array(rows, cols, a);
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
a[i][j] = a[i][j] + 2;
*(a[i] + j) = *(*(a + i) + j) + 2;
//*(a + (i * cols) + j) = (*(a + (i * cols) + j)) + 2;
// *(*(a + i) + j) += 2; // Gives exception
// *(a[i]+j) += 10; // Gives exception
}
}
printf("Finally in modify array =\n");
output_2d_array(rows, cols, a);
}
Example run (program mda17):
$ mda17
Please enter the elements for row 1 and column 1 of a
23
Please enter the elements for row 1 and column 2 of a
24
Please enter the elements for row 1 and column 3 of a
25
Please enter the elements for row 2 and column 1 of a
26
Please enter the elements for row 2 and column 2 of a
27
Please enter the elements for row 2 and column 3 of a
28
Please enter the elements for row 3 and column 1 of a
99
Please enter the elements for row 3 and column 2 of a
98
Please enter the elements for row 3 and column 3 of a
97
Please enter the elements for row 4 and column 1 of a
96
Please enter the elements for row 4 and column 2 of a
95
Please enter the elements for row 4 and column 3 of a
94
Initially in main array =
23 (23) 24 (24) 25 (25)
26 (26) 27 (27) 28 (28)
99 (99) 98 (98) 97 (97)
96 (96) 95 (95) 94 (94)
Initally in modify array =
23 (23) 24 (24) 25 (25)
26 (26) 27 (27) 28 (28)
99 (99) 98 (98) 97 (97)
96 (96) 95 (95) 94 (94)
Finally in modify array =
27 (27) 28 (28) 29 (29)
30 (30) 31 (31) 32 (32)
103 (103) 102 (102) 101 (101)
100 (100) 99 (99) 98 (98)
Finally in main array =
27 (27) 28 (28) 29 (29)
30 (30) 31 (31) 32 (32)
103 (103) 102 (102) 101 (101)
100 (100) 99 (99) 98 (98)
$
Check this and try to find if array is passed as an array or a pointer to some function:
char arr[]={'a','b','c'};
int sizeOfArr = sizeof(arr)/sizeof(arr[0]);
in both the function find size of array using above method where arr[] has been created and where it has been passed - the sizeOfArr will decipher things. This perhaps would clear why size/dimensions have been passed explicitly - this is all I can make out of your entire statement. Correct me if I am wrong.
To not use pointers - wrap the array into the struct. Then the entire struct (including the array) will be passed to the function.
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
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;
}
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.