Home > other >  How do I set a double pointer back to the first array element?
How do I set a double pointer back to the first array element?

Time:01-17

Edited to add the entire assignment and expected output.

You have been hired to assist firefighters locate wildfires in a large geographic area. The area is divided into smaller zones. Each zone is scanned via satellite for its average temperature. If a zone has an average temperature strictly greater than 1000°F, we assume there is a fire in that zone. If the temperature is between 100 degrees (included) and 1000 degrees (included), we have to further investigate, so it becomes a "zone to watch."

The large geographic area you are watching is a rectangle with a certain length and width, each given in terms of zones. For example, if the area to be scanned has a length of 6 and width of 9 then it will be divided into 6*9 zones:

Because your program will be used for a variety of geographic areas (each with its own length and width) your program needs to dynamically allocate the memory for the number of zones it is to handle (vertically and horizontally).

To do so, you must use the two following functions without changing the code in them:

int ** allocateIntStarArray(int num){
    int ** ptr = (int **) malloc(num * sizeof(int *));
    return ptr;
}

int * allocateIntArray(int num){
    int * ptr = (int *) malloc(num * sizeof(int));
    return ptr;
}

The function allocateIntArray() will be used to allocate the space required to store the average temperatures in one row of zones, that is, an array of integers. The function therefore returns a pointer to such an array of integers.

The function allocateIntStarArray() will be used to allocate an array of pointers, each of which will store a pointer to a row of integers (temperatures of zones). That is, the function returns a pointer to an array of pointers. Each cell of this array will point to an array of integers containing the temperature values for the zones.

The inputs of the program are first the length, then the width of an area, then the average temperatures of all zones, row by row.

Please remember to free the memory you have allocated.

The output should pinpoint the possible zones with fires with [X] and the watch zone with a [*], the other zone are displayed with [ ].


The code I'm working on is to create a matrix based off user input. I'm having an issue getting my variable **mat back to the first array element so that it will print the rectangle correctly. Could someone enlighten me on how to do this? What I have so far:

#include<stdio.h>
#include<stdlib.h>

int ** allocateIntStarArray(int num);
int * allocateIntArray(int num);
void readValues(int **mat, int cols, int rows);
void print(int **mat, int cols, int rows);
int** allocateMatrix(int nrows, int ncols);

int main(void) {
    int rows=0, cols=0;
    int i,j;
    int** mat = 0;
    int num = rows*cols;

    scanf("%d %d", &rows, &cols);

    mat = allocateMatrix(rows, cols);
    readValues(mat, cols, rows);
    print(mat, cols, rows);
    printf("\n");

    return 0;
}

int ** allocateIntStarArray(int num){
    int ** ptr = (int **) malloc(num * sizeof(int *));
    return ptr;
}

int * allocateIntArray(int num){
    int * ptr = (int *) malloc(num * sizeof(int));
    return ptr;
}

int** allocateMatrix(int nrows, int ncols) {
    int** mat = allocateIntStarArray(nrows);

    for (int row = 0; row != nrows;   row) {
        mat[row] = allocateIntArray(ncols);
    }

    return mat;
}

void readValues(int** mat, int ncols, int nrows){
    int num = nrows*ncols;

    for(int cols=0;cols!=ncols;cols  ){
        for(int rows=0;rows!=nrows;rows  ){
            scanf("%d", &**mat);
        }
    }
}

void print(int** mat, int ncols, int nrows){
    int num = ncols*nrows;

    **mat = **(mat-num);

    int m = **mat;

    for(int cols=0;cols<ncols;cols  ){
        for(int rows=0;rows<nrows;rows  ){
            if(m>1000){
                printf("[X]");
            }
            else if(m>100&&m<1000){
                printf("[*]");
            }
            else{
                printf("[ ]");
            }
            if(rows==nrows-1){
                printf("\n");
            }
        }
    }
}

CodePudding user response:

I would not use double pointers instead of 2D arrays.

void *allocateMatrix(size_t nrows, size_t ncols, int (**array)[ncols]) 
{
    int (*arrptr)[ncols]  = malloc(nrows * sizeof(*arrptr));
    if(array) *array = arrptr;
    return arrptr;
}

int main(void)
{
    size_t cols = 30, rows = 40;
    int (*matrix)[cols] = allocateMatrix(rows, cols, NULL);

    if(matrix)
    {
        matrix[5][4] = 97;
        matrix[4][2] = matrix[5][4] * 4;
        printf("%d %d\n", matrix[5][4], matrix[4][2]);
    }
    free(matrix);
}

Easier, only one allocation / free, usage same as arrays and more efficient as you remove one level of indirection.

Also use the correct type for sizes and indexes: size_t

CodePudding user response:

In scanf("%d", &**mat);, the first * will be balanced by its & counterpart, as the two operators have the opposite effect.

The result will be *mat, a value of type int *. While is is the correct type for the %d format specifier, *mat is the address of the first subarray in the matrix. Repeatedly reading values to this address will continue to overwrite the first value of the first subarray (mat[0][0]).

Since you never move any pointers, the rest of the matrix will remain uninitialized.

That said, there is no need to manually manage your pointers, since you are already calculating indexes. Simply use array subscript notation with your indexes, and take the address of each value's location.

scanf("%d", &mat[rows][cols]);

(See Member access operators)

In the print function,mat - num is going to resolve to some address you should not attempt to access, as it is outside the bounds of the mat object. This is a classic example of Undefined Behavior.

You then attempt to set m to be some value located through this address, but only once.

Again, you are calculating your indexes already, so use them to your advantage. Set m in the inner loop to the value found at mat[rows][cols], so that you update its value for each iteration.


Here's a functional program, with an example of freeing the memory you allocate.

(Note: as previously stated, size_t is the correct type to use for memory sizes and indexes. I have stuck with int here, to match your instructor's flawed implementations.)

#include <stdio.h>
#include <stdlib.h>

int **allocateIntStarArray(int);
int *allocateIntArray(int);
int **allocateMatrix(int, int);

void readValues(int **, int, int);
void print(int **, int, int);

int main(void) {
    int rows, cols;

    if (2 != scanf("%d %d", &rows, &cols)) {
        fprintf(stderr, "Could not read matrix size information.\n");
        return EXIT_FAILURE;
    }

    int **mat = allocateMatrix(rows, cols);

    readValues(mat, cols, rows);
    print(mat, cols, rows);

    /* free your memory */
    for (int i = 0; i < rows; i  )
        free(mat[i]);
    free(mat);
}

void readValues(int **mat, int ncols, int nrows) {
    for (int i = 0; i < nrows; i  ) {
        for (int j = 0; j < ncols; j  ) {
            if (1 != scanf("%d", &mat[i][j])) {
                fprintf(stderr, "Invalid value read.\n");
                exit(EXIT_FAILURE);
            }
        }
    }
}

void print(int **mat, int ncols, int nrows) {
    for (int i = 0; i < nrows; i  ) {
        for (int j = 0; j < ncols; j  ) {
            int value = mat[i][j];

            if (value > 1000)
                printf("[X]");
            else if (value > 100)
                printf("[*]");
            else
                printf("[ ]");
        }

        /* print a newline after every row */
        putchar('\n');
    }
}

int **allocateMatrix(int nrows, int ncols) {
    int **mat = allocateIntStarArray(nrows);

    for (int row = 0; row < nrows;   row) {
        mat[row] = allocateIntArray(ncols);
    }

    return mat;
}

/* Provided functions, do not edit */
int **allocateIntStarArray(int num) {
    int **ptr = (int **) malloc(num * sizeof(int *));
    return ptr;
}

int *allocateIntArray(int num) {
    int *ptr = (int *) malloc(num * sizeof(int));
    return ptr;
}

Here is the program I used to quickly generate data for testing:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void) {
    srand((unsigned) time(NULL));

    int rows = (rand() % 20)   1;
    int cols = (rand() % 20)   1;

    printf("%d %d\n", rows, cols);

    for (int i = 0, n = rows * cols; i < n; i  )
        printf("%d ", rand() % 2000);
}
  •  Tags:  
  • Related