/*
 * Program to demonstrate 2D array using malloc, two ways.
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

void fill_VLA(int rows, int cols, int nums[rows][cols]);
void printarray_VLA(int rows, int cols, int nums[rows][cols]);
void fill(int rows, int cols, int **nums);
void printarray(int rows, int cols, int **nums);

int main(void) {

	printf("enter rows, cols\n");
	int rows, cols;
	if (scanf("%d %d", &rows, &cols) != 2) {
		printf("error\n");
		return 1;
	}

	/*
	 * one way to make a 2D array:
	 * use VLA (not good for really large arrays)
	 */
	int vla_array[rows][cols];

	/* fill and print array */
	printf("with VLA:\n");
	fill_VLA(rows, cols, vla_array);
	printarray_VLA(rows, cols, vla_array);

	/* 
	 * another way to make a 2D array:
	 * use malloc() and allocate each row separately
	 */

	/* array of pointers to rows */
	int **row_ptrs1 = malloc(sizeof(row_ptrs1[0]) * rows);
	if (row_ptrs1 == NULL) {
		printf("count not get space\n");
		return 1;
	}

	/* fill array of pointers to rows */
	for (int r = 0; r < rows; ++r) {
		row_ptrs1[r] = malloc(sizeof(row_ptrs1[0][0]) * cols);
		if (row_ptrs1[r] == NULL) {
			printf("could not get space\n");
			return 1;
		}
	}

	/* fill and print array */
	printf("with malloc() method 1:\n");
	fill(rows, cols, row_ptrs1);
	printarray(rows, cols, row_ptrs1);

	/* free allocated space */
	for (int r = 0; r < rows; ++r) {
		free(row_ptrs1[r]);
	}
	free(row_ptrs1);

	/* 
	 * another way to make a 2D array:
	 * use malloc(), allocate one big block of space, and build 
	 * pointers into it
	 */

	/* array of pointers to rows */
	int **row_ptrs2 = malloc(sizeof(row_ptrs2[0]) * rows);
	if (row_ptrs2 == NULL) {
		printf("could not get space\n");
		return 1;
	}


	/* space for all rows */
	int *nums = malloc(sizeof(nums[0]) * rows * cols);
	if (nums == NULL) {
		printf("could not get space\n");
		return 1;
	}

	/* fill array of pointers to rows */
	for (int r = 0; r < rows; ++r) {
		row_ptrs2[r] = &nums[r*cols];
	}

	/* fill and print array */
	printf("with  malloc() method 2:\n");
	fill(rows, cols, row_ptrs2);
	printarray(rows, cols, row_ptrs2);

	/* free allocated space */
	free(nums);
	free(row_ptrs2);

	return 0;
}

void fill_VLA(int rows, int cols, int nums[rows][cols]) {
	for (int r = 0; r < rows; ++r) {
		for (int c = 0; c < cols; ++c) {
			nums[r][c] = 1000 * r + c;
		}
	}
}

void printarray_VLA(int rows, int cols, int nums[rows][cols]) {
	for (int r = 0; r < rows; ++r) {
		for (int c = 0; c < cols; ++c) {
			printf("%10d ", nums[r][c]);
		}
		putchar('\n');
	}
}

void fill(int rows, int cols, int **nums) {
	for (int r = 0; r < rows; ++r) {
		for (int c = 0; c < cols; ++c) {
			nums[r][c] = 1000 * r + c;
		}
	}
}

void printarray(int rows, int cols, int **nums) {
	for (int r = 0; r < rows; ++r) {
		for (int c = 0; c < cols; ++c) {
			printf("%10d ", nums[r][c]);
		}
		putchar('\n');
	}
}