Home > Enterprise >  Trying to set the size of a 2d array using input from user
Trying to set the size of a 2d array using input from user

Time:10-05

(Im programming in C) i have a program im trying to write and for the program i want to get input of 2 numbers from a user and use those numbers to set the dimensions of a 2d array for context im making a small drawing app and i want the user to set the size of the board tho i cant seem to find an awnser as to if this is possible and if it is how is it done.

#include<stdio.h>

int main() {
    int x, y;
    char sign[1];
    char board = 'O';
    int count2;
    int pos;
    // sets nuber of rows

    printf("enter the number of collums:\n ");
    scanf_s("%d", &x);
    // sets number of collums
    printf("enter the number of rows: \n");
    scanf_s("%d", &y);
    //sets the sign
    printf("enter the sign you want to draw with: \n");
    scanf_s("%s", &sign, 1);

// this is to visualize the board size for the user
    for (int count = 0; count != x; count  ) {
        printf("%c", board);
        for (int count2 = 0; count2 != y; count2  )
            printf("%c", board);
        printf("\n");
    }

    pos[x][y] = {
        {}
    };




}

i realize why this wouldnt work but 2d arrays are a new concept to me and i cant seem to get it to work. the error i seem to get are: expression must have pointer-to-object type but it has type int.

CodePudding user response:

Assuming that you are using integers, you should replace lines:

pos[x][y] = {
    {}
};

with:

int pos[x][y];

This declares the array to be of type integer with the size that you are looking for.

Since this is a variable-size array, it must be initialized after the declaration:

for(unsigned int idx1 = 0; x > idx1; idx1  )
{
    for(unsigned int idx2 = 0; y > idx2; idx2  )
    {
        pos[idx1][idx2] = 0;
    }
}

CodePudding user response:

Example use of VLA array and array pointers


void *allocate(size_t rows, size_t cols)
{
    int (*arr)[cols] = malloc(rows *sizeof(*arr));
    //or if you want to initialize the array to zeroes
//    int (*arr)[cols] = calloc(rows, sizeof(*arr));
    return arr;
}

void printarray(size_t rows, size_t cols, int (*arr)[cols])
{
    for(size_t row = 0; row < rows; row  )
    {
        for(size_t col = 0; col < cols; col  )
        {
            printf("M ", arr[row][col]);
        }
        printf("\n");
    }
}

void initarray(size_t rows, size_t cols, int (*arr)[cols])
{
    for(size_t row = 0; row < rows; row  )
    {
        for(size_t col = 0; col < cols; col  )
        {
            arr[row][col] = 100*row   col;
        }
    }    
}

int main(void)
{
    size_t rows,cols;

    if(scanf("%zu %zu", &rows, &cols) == 2)
    {
        int (*arr)[cols] = allocate(rows, cols);
        if(arr)
        {
            initarray(rows,cols,arr);
            printarray(rows, cols, arr);
        }
        else
        {
            /*handle allocation error*/
        }
    }
    else
    {

        /*handle scanf error*/
    }
}

https://godbolt.org/z/rnWafcd9c

CodePudding user response:

to set the size of a 2d array

Variable Length Array

Available in C99 and optionally afterwords.

// Validate array dimensions
// Some reasonable threshold
#define BIG 1000

if (x <= 0 || y <= 0 || x <= BIG/y) {
  Handle_Error();
}

int pos[x][y];
memset(pos, 0, sizeof pos);  // zero out if desired.

// Use pos

// No clean-up required

Allocate

Alternatively, allocate memory for an array pointers, each pointing to an allocated array of int.

// Validate dimensions (or consider using type `size_t`)
if (x < 0 || y < 0) {
  Handle_Error();
}

int **pos = calloc(x, sizeof *pos);
if (pow == NULL) {
  Handle_OutOfMemory();
}
for (int xi = 0; xi < x; xi  ) {
  pos[xi] = calloc(y, sizeof pos[0][0]);
  if (pos[xi] == NULL) {
    Handle_OutOfMemory();
  }
}

// Use pos

// Free when done
if (pos) {
  for (int xi = 0; xi < x; xi  ) {
    free(pos[xi]);
  }
  free(pos);
}

CodePudding user response:

In a standards compliant environment, you can define a variable-length array (VLA) by using non-constant expressions in the variable definition. This expression must evaluate to a value greater than zero.

VLAs cannot be initialized in their definitions, and must be initialized "by hand" after they are defined.

memset can be used to quickly fill a number of bytes with some constant byte. This can be useful for initializing all bytes to zero, which for integers is guaranteed to represent zero1.

Otherwise, use basic loops to initialize.

Because VLAs exist on the stack, care must be taken to ensure they do no exceed the maximum stack size on your platform.

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

void die(const char *msg) {
    fprintf(stderr, "%s\n", msg);
    exit(EXIT_FAILURE);
}

int valid(size_t n) {
    /* arbitrary upper bounds, platform dependent */
    return n > 0 && n < 512;
}

int main(void) {
    size_t x, y;

    printf("Enter X dimension: ");
    if (1 != scanf("%zu", &x))
        die("Could not read X dimension.");
    printf("Enter Y dimension: ");
    if (1 != scanf("%zu", &y))
        die("Could not read Y dimension");

    if (!valid(x) || !valid(y))
        die("Invalid dimensions.");

    int data[x][y];
    printf("[data] size in bytes is: %zu\n", sizeof data);

    /* All bytes zero */
    memset(data, 0, sizeof data);

    /* Or, a particular value */
    for (size_t i = 0; i < x; i  )
        for (size_t j = 0; j < y; j  )
            data[i][j] = 42;
}

Some additional notes:

  • Formally, the proper type for dealing with memory sizes is size_t. Its format specifier is "%zu".

  • The return value of scanf should always be checked to ensure the expected number of conversions took place.

  • The format string " %c" (note the leading space) can be used to read a single character while ignoring leading white space. This is useful because previous calls to scanf may leave characters such as the newline (\n) in the input buffer.


From various comments we can see one of your issues is that you are using the MSVC C compiler. This is an ancient, non-standards compliant compiler that has very poor support for C99 features, including VLAs.

In this case, you may want to use dynamic memory allocation to create your array. You'll need similar validation, but generally speaking heap memory is more vast.

Every call to malloc needs a mirrored called to free when you are done using the memory, and care must be taken in cleaning up memory in the event of a partial failure.

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

void die(const char *msg) {
    fprintf(stderr, "%s\n", msg);
    exit(EXIT_FAILURE);
}

int valid(size_t n) {
    return n > 0 && n < 2048;
}

int main(void) {
    size_t x, y;

    printf("Enter X dimension: ");
    if (1 != scanf("%zu", &x))
        die("Could not read X dimension.");
    printf("Enter Y dimension: ");
    if (1 != scanf("%zu", &y))
        die("Could not read Y dimension");

    if (!valid(x) || !valid(y))
        die("Invalid dimensions.");

    int **data = malloc(sizeof *data * x);

    if (data == NULL)
        die("Could not allocate memory.");

    for (size_t i = 0; i < x; i  ) {
        if (!(data[i] = malloc(sizeof *data[i] * y))) {
            for (size_t j = 0; j < i; j  )
                free(data[j]);

            free(data);
            die("Failed to allocate memory.");
        }
    }

    printf("[data] size in bytes is: %zu\n", sizeof (int) * x * y);

    for (size_t i = 0; i < x; i  )
        free(data[i]);

    free(data);
}

1 All bits zero is not a guaranteed representation of zero for all types, e.g., floating point numbers.

CodePudding user response:

If you consider using dynamic memory allocation with malloc:

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

void delete2DimArr(int** pos, int x) {
    for (int i = 0; i < x; i  ) {
        free(pos[i]);
    }
    free(pos);
}

int** create2DimArr(int x, int y) {
    int** pos = malloc(x * sizeof(int*));
    int fail_idx = -1;
    if (pos) {
        for (int i = 0; i < x; i  ) {
            pos[i] = malloc(y * sizeof(int));
            // if you need to initial the value
            if (pos[i]) {
                memset(pos[i], 0, y * sizeof(int));
            } else {
                fail_idx = i;
                break;
            }
        }
    }

    if (fail_idx != -1) {
        delete2DimArr(pos, fail_idx   1);
        pos = NULL;
    }
    if (!pos) {
        printf("create2DimArr malloc failed!");
    }

    return pos;
}

int main() {
    // test dimensions
    int x = 5, y = 7;

    // code continue here
    // this is to visualize the board size for the user
    for (int count = 0; count < x; count  ) {
        for (int count2 = 0; count2 < y; count2  ) {
            printf("%c", '0');
        }
        printf("\n");
    }

    int** pos = create2DimArr(x, y);
    printf("Show pos:\n");
    if (pos) {
        for (int count = 0; count < x; count  ) {
            for (int count2 = 0; count2 < y; count2  ) {
                printf("%d", pos[count][count2]);
            }
            printf("\n");
        }
    }

    delete2DimArr(pos, x);
}

With an online validation.

  •  Tags:  
  • c
  • Related