C can't free memory after allocating it in function - c

I'm working on a programm that compares the runtime and steps of insertion- and countsort.
Everything works except one thing, for countsort I have to initialize an extra array with malloc.
My problem is that I can't figure out how or where to free the allocated memory for my count_array.
(I'm fairly new to the C language)
The malloc command is in line 47, in the "count_sort" function.
programm code:
#include <stdio.h>
#include <stdlib.h>
#include "introprog_complexity_steps_input.h"
const int MAX_VALUE = 5000000;
void count_sort_calculate_counts(int input_array[], int len, int count_array[], unsigned int* befehle) {
// Muss implementiert werden
int s = 0;
*befehle = *befehle + 1; //1 Befehl für Zuweisung von s
*befehle = *befehle + 1; //1 Befehl für Zuweisung von i
for(int i = 0; i < len; i++){
*befehle = *befehle + 1; //1 Befehl für die Überprüfung von (i < len) = true
*befehle = *befehle + 1; //1 Befehl für i++
s = input_array[i];
*befehle = *befehle + 1; //1 Befehl für Zuweisung von s = input_array[i]
count_array[s] = count_array[s] + 1;
*befehle = *befehle + 1; //1 Befehl für die Rechnung count_array[s] = count_array[s] + 1
}
*befehle = *befehle + 1; //1 Befehl für die Überprüfung von (i < len) = false
}
void count_sort_write_output_array(int output_array[], int len, int count_array[], unsigned int* befehle) {
// Muss implementiert werden
int k = 0;
*befehle = *befehle + 1; //1 Befehl für Zuweisung von k
*befehle = *befehle + 1; //1 Befehl für Zuweisung von j
*befehle = *befehle + 1; //1 Befehl für Zuweisung von i
for(int j = 0; j <= MAX_VALUE; j++){
*befehle = *befehle + 1; //1 Befehl für die Überprüfung von (j <= MAX_VALUE) = true
*befehle = *befehle + 1; //1 Befehl für j++
for(int i = 0; i < count_array[j]; i++){
*befehle = *befehle + 1; //1 Befehl für die Überprüfung von (i < count_array[j]) = true
*befehle = *befehle + 1; //1 Befehl für i++
output_array[k] = j;
*befehle = *befehle + 1; //1 Befehl für Zuweisung von output_array[k] = j
k = k + 1;
*befehle = *befehle + 1; //1 Befehl für die Rechnung k = k + 1
}
*befehle = *befehle + 1; //1 Befehl für die Überprüfung von (i < count_array[j]) = false
}
*befehle = *befehle + 1; //1 Befehl für die Überprüfung von (j <= MAX_VALUE) = false
}
void count_sort(int array[], int len, unsigned int* befehle) {
// Muss implementiert werden
int* count_array = malloc(sizeof(int) * MAX_VALUE);
count_sort_calculate_counts(array, len, count_array, befehle);
count_sort_write_output_array(array, len, count_array, befehle);
}
void insertion_sort(int array[], int len, unsigned int* befehle) {
// Muss implementiert werden
int key;
int i;
*befehle = *befehle + 1; //1 Befehl für Zuweisung von key
*befehle = *befehle + 1; //1 Befehl für Zuweisung von i
*befehle = *befehle + 1; //1 Befehl für Zuweisung von j
for (int j = 1; j <len; j++){
*befehle = *befehle + 1; //1 Befehl für die Überprüfung von (j <len) = true
*befehle = *befehle + 1; //1 Befehl für j++
i = j;
*befehle = *befehle + 1; //1 Befehl für die zuweisung i = j;
key = array[j];
*befehle = *befehle + 1; //1 Befehl für die zuweisung key = array[j]
i = j - 1;
*befehle = *befehle + 1; //1 Befehl für die Rechnung i = j - 1
while (i >= 0 && array[i] > key){
*befehle = *befehle + 2; //2 Befehle für die Bedingungen (i >= 0 = true) und (array[i] > key) = true
array[i + 1] = array[i];
*befehle = *befehle + 1; //1 Befehl für die zuweisung array[i + 1] = array[i]
i = i - 1;
*befehle = *befehle + 1; //1 Befehl für die Rechnung i = i - 1;
}
*befehle = *befehle + 2; //2 Befehle für die Bedingung (i >= 0 = false) und (array[i] > key) = false
array[i+1] = key;
*befehle = *befehle + 1; //1 Befehl für die zuweisung array[i+1] = key
}
*befehle = *befehle + 1; //1 Befehl für die Überprüfung von (j <len) = false
}
int main(int argc, char *argv[]) {
const int WERTE[] = {10000,20000,30000,40000,50000};
const int LEN_WERTE = 5;
const int LEN_ALGORITHMEN = 2;
int rc = 0;
unsigned int befehle_array[LEN_ALGORITHMEN][LEN_WERTE];
double laufzeit_array[LEN_ALGORITHMEN][LEN_WERTE];
for(int j = 0; j < LEN_WERTE; ++j) {
int n = WERTE[j];
// Reserviere Speicher für Arrays der Länge n
int* array_countsort = malloc(sizeof(int) * n);
int* array_insertionsort = malloc(sizeof(int) * n);
// Fülle array_countsort mit Zufallswerten ..
fill_array_randomly(array_countsort, n, MAX_VALUE);
// ... und kopiere die erzeugten Werte in das Array
// array_insertionsort
copy_array_elements(array_insertionsort, array_countsort, n);
// Teste ob beide Arrays auch wirklich die gleichen Werte
// enthalten
if(!check_equality_of_arrays(array_countsort, array_insertionsort, n)) {
printf("Die Eingaben für beide Algorithmen müssen für die Vergleichbarkeit gleich sein!\n");
return -1;
}
for(int i = 0; i < LEN_ALGORITHMEN; ++i) {
unsigned int anzahl_befehle = 0;
start_timer();
// Aufruf der entsprechenden Sortieralgorithmen
if(i==0) {
count_sort(array_countsort, n, &anzahl_befehle);
} else if(i==1) {
insertion_sort(array_insertionsort, n, &anzahl_befehle);
}
// Speichere die Laufzeit sowie die Anzahl benötigter
// Befehle
laufzeit_array[i][j] = end_timer();
befehle_array[i][j] = anzahl_befehle;
}
// Teste, ob die Ausgabe beider Algorithmen gleich sind
if(!check_equality_of_arrays(array_countsort, array_insertionsort, n)) {
printf("Die Arrays sind nicht gleich. Eines muss (falsch) sortiert worden sein!\n");
rc = -1;
}
// Gib den Speicherplatz wieder frei
free(array_countsort);
free(array_insertionsort);
}
// Ausgabe der Anzahl ausgeführter Befehle sowie der gemessenen
// Laufzeiten (in Millisekunden)
printf("Parameter MAX_VALUE hat den Wert %d\n", MAX_VALUE);
printf("\t %32s %32s \n", "Countsort","Insertionsort");
printf("%8s \t %16s %16s \t %16s %16s \n", "n","Befehle", "Laufzeit","Befehle","Laufzeit");
for(int j = 0; j < LEN_WERTE; ++j) {
printf("%8d \t ",WERTE[j]);
for(int i = 0; i < LEN_ALGORITHMEN; ++i) {
printf("%16u %16.4f \t ", befehle_array[i][j], laufzeit_array[i][j]);
}
printf("\n");
}
return rc;
}
I have tried to free the memory of the count array at several points of the programm. Compiling works but if I run the programm it spits out a segmentation fault.
Also I have tried to not use the malloc command and just use
int count_array[MAX_VALUE];
which also gives a segmentation fault.

As #AviBerger pointed out, it may be because you are accessing count_array[MAX_VALUE], whereas the last element legally accessable is MAX_VALUE-1.
Make sure that fill_array_randomly function only fills non-negative integers to the array, cause in the function count_sort_calculate_counts, in the statement count_array[s] = count_array[s] + 1;, you are accessing input_array[i]th element of count_array, and if input_array[i] is negative, then it may issue this error.

Related

Why triple nested for loop doesn't work the 2nd time in C?

Edid: Thanks for the suggestions, but none of them work for the FOR loop error.
Why the triple nested for loop(line 82 - 98) works only the first time(correctly) and then it just spits crazy random numbers? The first time it works so good and then it does everything wrong. Thanks for the help!
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
// 2 players, 5 zara, 3 puti(ako ne si gi haresa), moje da pazite:
//1 qift
// 2 qifta
// ful: 1*2 i 1*3
// 5 ednakvi: general
// 4 ednakvi
// 1*3
// 5 poredni
// shans
// izpulnqvase 8 puti i moje da se zapazva zara (samo pri 1 i 2 hvurlane)
int np, otg[5], otg10[5];
int check_pairs(int *otg10, int time){
int dicecopy[5];
memcpy(dicecopy, otg10, sizeof(int) * 5);
for(int k = 0; k < 5; k++){
printf("%d " , dicecopy[k]);
}
int pairs = 0, sum = 0;
for(int i = 0; i < 5; i++){
for(int j = 0; j < 5; j++){
if(dicecopy[i] == dicecopy[j])
pairs++;
}
}
// points
if(pairs == 1*2 || pairs == 2*2){
printf("GGGGGGG");
for(int k = 0; k < 5; k++){
sum += dicecopy[k];
}
} else {
return 0;
}
return sum;
}
int main(){
printf("How many players do you want: ");
scanf("%d" , &np);
int points[np];
for(int i = 0; i < np; i++){
points[i] = 0;
}
int dice[8][np][3][5];
srand(time(NULL));
for(int i = 0; i < 8; i++){
for(int j = 0; j < np; j++){
for(int c = 0; c < 3; c++){
for(int k = 0; k < 5; k++){
dice[i][j][c][k] = rand() % 6 + 1;
}
}
}
}
/* for(int i = 0; i < 8; i++){
for(int j = 0; j < np; j++){
for(int c = 0; c < 3; c++){
for(int k = 0; k < 5; k++){
printf("%d " , dice[i][j][c][k]);
}
putchar('\n');
}
putchar('\n');
}
putchar('\n\n');
}
*/
char anws = 'y';
for(int i = 0; i < 8; i++){
for(int j = 0; j < np; j++){
printf("\nPlayer: %d\nPoints: %d\n" , j + 1 , points[j]);
for(int k = 0; k < 3; k++){
for(int l = 0; l < 5; l++){
otg10[l] = dice[i][j][k][l];
printf("%d " , otg10[l]);
}
printf("\n\nDo you like it?\n");
scanf("%s" , &anws);
if(anws == 'y' || anws == 'Y'){
points[j] = check_pairs(otg10 , k);
break;
}
}
}
}
return 0;
}
The code is still not finished I have to do more work on the other check-ups. BTW this will represent the game called Generala, if you have any suggestions I'd like to hear them!

C: 2d char array issue

i've a problem with an exercise. The purpose is to print a specific picture after an int input (It is assumed that the input is > 3).
Example:
https://i.stack.imgur.com/KRl0R.png
This is my code:
#include <stdio.h>
int main(void){
int i, j, n, simbolo;
printf("Inserire un numero: ");
scanf("%d", &n);
char mat[n + 1][n + 2];
simbolo = n+2;
//initialization with blank space and setting 3 * diagonal
for(i = 0; i < n + 1; i ++){
for(j = 0; j < n + 2; j++){
mat[i][j] = ' ';
mat[n - 2][0] = '*';
mat[n - 1][1] = '*';
mat[n][2] = '*';
}
}
//Add * diagonal of n length
for(i = 0; i < n + 1; i++){
mat[i][simbolo] = '*';
for(int x = i, y = 0; y < n + 2; y++){ //Print current line
printf("%c", mat[x][y]);
}
printf("\n");
simbolo--;
}
return 0;
}
The output isn't correct, it's added an extra '*' in mat[1][0]:
https://i.stack.imgur.com/4Z5Fl.png
Thanks in advance for you help
According to image, you want your output to have n rows, not n+1. This works correctly:
#include <stdio.h>
int main(void){
int i, j, n, simbolo;
printf("Inserire un numero: ");
scanf("%d", &n);
char mat[n][n + 2];
simbolo = n+1;
//initialization with blank space and setting 3 * diagonal
for(i = 0; i < n; i ++){
for(j = 0; j < n + 2; j++){
mat[i][j] = ' ';
}
}
mat[n - 3][0] = '*';
mat[n - 2][1] = '*';
mat[n - 1][2] = '*';
//Add * diagonal of n length
for(i = 0; i < n; i++){
if(i<(n-1))
mat[i][simbolo] = '*';
printf("%.*s\n", n+2, mat[i]);
simbolo--;
}
return 0;
}
Some other people have already pointed out the issue, so I thought I would just post a cleaned up version for your reference:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("n: ");
int n = 0;
if (scanf("%d", &n) != 1) {
fprintf(stderr, "ERROR: couldn't read 'n'\n");
return EXIT_FAILURE;
}
char mat[n][n + 2];
// Initialize with spaces.
int i;
int j;
for (i = 0; i < n; i++)
for (j = 0; j < n + 2; j++)
mat[i][j] = ' ';
// Draw the first 2 * on the left.
mat[n - 3][0] = '*';
mat[n - 2][1] = '*';
// Draw the diagonal on the right.
j = n + 1;
for (i = 0; j >= 2; i++, j--)
mat[i][j] = '*';
// Print out the result.
for (i = 0; i < n; i++) {
for (j = 0; j < n + 2; j++)
printf("%c", mat[i][j]);
printf("\n");
}
return EXIT_SUCCESS;
}
I just changed
mat[i][simbolo] = '*';
for
mat[i+1][simbolo-1] = '*';
I also changed the spaces for '-' to make the output clearer.
The problem is the one mentioned in the comments: your indices were off.
Remember, in C, indexing is 0 based, so the last element of any array has index n-1.
Usually, in C when you go further the pointer just goes back to the beginning.
#include <stdio.h>
int main(void){
int i, j, n, simbolo;
printf("Inserire un numero: ");
scanf("%d", &n);
char mat[n + 1][n + 2];
simbolo = n+2;
//printf("Simbolo: %d",simbolo);
//initialization with blank space and setting 3 * diagonal
for(i = 0; i < n + 1; i ++){
for(j = 0; j < n + 2; j++){
mat[i][j] = '-';
mat[n - 2][0] = '*';
mat[n - 1][1] = '*';
mat[n][2] = '*';
}
}
//Add * diagonal of n length
for(i = 0; i < n+1 ; i++){
mat[i+1][simbolo-1] = '*';
for(int y = 0; y < n + 2; y++){ //Print current line
//printf(",x< %d, y: %d",i,y);
printf("%c", mat[i][y]);
}
printf("\n");
//printf("Simbolo: %d",simbolo);
simbolo--;
}
return 0;
}

Splitting files in visual studio

can You help me split these files on:
header.h (this was already made by me)
dane.cpp (this was already made by me)
solve.cpp (all solve patterns, inverse matrix, x1, x2, and f)
main.cpp
I did first two, but I cannot manage other ones.
header:
void dane(float(*q)[2], float *p);
data:
#include "Header.h"
void dane(float(*q)[2], float *p)
{
printf("Write 4 numbers to Matrix: A\n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j <2; j++)
{
scanf_s(" %f", &q[i][j]);
}
}
printf("\nWrite vector: B\n");
for (int i = 0; i < 2; i++)
scanf_s(" %f", &p[i]);
}
source:
#include "Header.h"
float A[2][2], B[2], X[2];
void main(void)
{
float AA[2][2];
float h, det, value;
data(A, B);
system("cls");
printf("Matrix A: \n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
printf("[%5.2f] ", A[i][j]);
printf("\n");
}
printf("\n\nVector: \n");
for (int i = 0; i < 2; i++)
printf("\n[%5.2f] ", B[i]);
_getch();
det = (A[0][0] * A[1][1]) - (A[0][1] * A[1][0]);
AA[0][0] = (1 / det) * A[1][1];
AA[0][1] = (1 / det) * (-1)*A[1][0];
AA[1][0] = (1 / det) * (-1)*A[0][1];
AA[1][1] = (1 / det) * A[0][0];
h = AA[1][0];
AA[1][0] = AA[0][1];
AA[0][1] = h;
if (det <= 0)
{
printf("\n\nDoesnt have extreme.");
_getch();
}
else
{
printf("\n\n\nInv matrix: \n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
printf("[%5.2f] ", AA[i][j]);
printf("\n");
}
_getch();
X[0] = 0.5 * AA[0][0] * (-1) * B[0] + 0.5 * AA[0][1] * (-1) * B[1];
X[1] = 0.5 * AA[1][0] * (-1) * B[0] + 0.5 * AA[1][1] * (-1) * B[1];
printf("\n x1 = %5.2f", X[0]);
printf("\n x2 = %5.2f", X[1]);
value = A[0][0] * X[0] * X[0] + A[1][0] * 2 * X[0] * X[1] +
A[1][1] * X[1] * X[1] + B[0] * X[0] + B[1] * X[1];
printf("\n\n f = %5.2f", value);
_getch();
}
}
Keep prototypes in header-files and surround them with #ifndef. Like the following,
Header.h
#ifndef HEADER_H
#define HEADER_H
void dane(float(*q)[2], float *p);
#endif

Strassen matrix multiplication implementation

I have written the below code for Strassen matrix multiplication. I know it's big but you don't need to go through the whole thing. My problem is that during compile time, the Strassen function with parameters of a[][num],b[][num] and c[][num] doesn't have a fixed value of num. This is where i am going wrong. I need to take the input of num in the main and that is why it cannot be globally given a value. How can i fix this? My code:
#include <stdio.h>
int num;
void strassen(int a[][num], int b[][num], int c[][num], int size) {
int p1[size/2][size/2], p2[size/2][size/2], p3[size/2][size/2], p4[size/2][size/2], p5[size/2][size/2], p6[size/2][size/2], p7[size/2][size/2];
int temp1[size/2][size/2], temp2[size/2][size/2];
int q1, q2, q3, q4, q5, q6, q7, i, j;
if(size >= 2) { //give recursive calls
//p1
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp1[i][j] = a[i][j] + a[i + size / 2][j + size / 2];
}
}
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp2[i][j] = b[i][j] + b[i + size / 2][j + size / 2];
}
}
num = size / 2;
strassen(temp1, temp2, p1, size / 2);
//p2
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp1[i][j] = a[i + size / 2][j] + a[i + size / 2][j + size / 2];
}
}
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp2[i][j] = b[i][j];
}
}
num = size / 2;
strassen(temp1, temp2, p2, size / 2);
//p3
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp1[i][j] = a[i][j];
}
}
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp2[i][j] = b[i][j + size / 2] - b[i + size / 2][j + size / 2];
}
}
num = size / 2;
strassen(temp1, temp2, p3, size / 2);
//p4
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp1[i][j] = a[i + size / 2][j + size / 2];
}
}
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp2[i][j] = b[i + size / 2][j] - b[i][j];
}
}
num = size / 2;
strassen(temp1, temp2, p4, size / 2);
//p5
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp1[i][j] = a[i][j] + a[i][j + size / 2];
}
}
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp2[i][j] = b[i + size / 2][j + size / 2];
}
}
num = size / 2;
strassen(temp1, temp2, p5, size / 2);
//p6
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp1[i][j] = a[i + size / 2][j] - a[i][j];
}
}num = size / 2;
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp2[i][j] = b[i][j] + b[i][j + size / 2];
}
}
num = size / 2;
strassen(temp1, temp2, p6, size / 2);
//p7
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp1[i][j] = a[i][j + size / 2] - a[i + size / 2][j + size / 2];
}
}
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
temp2[i][j] = b[i + size / 2][j] + b[i + size / 2][j + size / 2];
}
}
num = size / 2;
strassen(temp1, temp2, p7, size / 2);
//c11
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
c[i][j] = p1[i][j] + p4[i][j] - p5[i][j] + p7[i][j];
}
}
//c12
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
c[i][j + size / 2] = p3[i][j] + p5[i][j];
}
}
//c21
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
c[i + size / 2][j] = p2[i][j] + p4[i][j];
}
}
//c22
for(i = 0; i < size / 2; i++) {
for(j = 0; j < size / 2; j++) {
c[i + size / 2][j + size / 2] = p1[i][j] + p3[i][j] - p2[i][j] + p6[i][j];
}
}
}
else if(size == 1) {
c[0][0] = a[0][0] * b[0][0];
}
}
int padding(int num) {
int original_num = num, lower_power = 0, i, actual_num = 1;
if(num == 1)
return 1;
while(num > 1) {
lower_power++;
num /= 2;
}
for(i = 0; i < lower_power; i++) {
actual_num *= 2;
}
if(actual_num == original_num)
return original_num;
else
return actual_num * 2;
}
int main() {
int i, j, temp;
printf("Enter the size of nxn matrix:\n");
scanf("%d", &num);
temp = num;
if(num <= 0)
return 0;
num = padding(num);
int a[num][num], b[num][num], c[num][num];
printf("Enter matrix a:\n"); //accept inputs for a and b from the user
for(i = 0; i < temp; i++) {
for(j = 0; j < temp; j++) {
scanf("%d", &a[i][j]);
}
for(j = temp; j < num; j++) {
a[i][j] = 0;
}
}
for(i = temp; i < num; i++)
for(j = 0; j < num; j++)
a[i][j] = 0;
printf("\nEnter matrix b:\n");
for(i = 0; i < temp; i++) {
for(j = 0; j < temp; j++) {
scanf("%d", &b[i][j]);
}
for(j = temp; j < num; j++) {
b[i][j] = 0;
}
}
for(i = temp; i < num; i++)
for(j = 0; j < num; j++)
b[i][j] = 0;
printf("Matrix a:\n"); //printing the actual matrices for strassen's multiplication
for(i = 0; i < num; i++) {
for(j = 0; j < num; j++) {
printf("%d ", a[i][j]);
}
printf("\n");
}
printf("\nMatrix b:\n");
for(i = 0; i < num; i++) {
for(j = 0; j < num; j++) {
printf("%d ", b[i][j]);
}
printf("\n");
}
strassen(a, b, c, num);
printf("\nMatrix c is:\n");
for(i = 0; i < temp; i++) {
for(j = 0; j < temp; j++) {
printf("%d ", c[i][j]);
}
printf("\n");
}
return 0;
}
You can (perhaps even should) use int ** instead, and pass num as an argument. As a simplified example, here is how you might compute the sum of a dynamically sized array:
int sum(int *in, int len) {
int out = 0;
for(int i = 0; i < len; i++)
out += in[i];
return out;
}

How to solve error process returned -1073741819 in C

This is going to be a Minesweeper but is not finished yet. For now, the program should ask you for the size of the array and the number of mines. Then, it shows the hidden board (the one with numbers and 'X' as mines). That's all.
The problem is that the program stop working with this error
process returned -1073741819 <0xC0000005>
I think it's a memory problem, but I don't know where the problem is.
Sorry, because the comments are in Spanish. I'll try to add some in capital letters to make it understandable. The code:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "Tablero/tablero.h"
#include <stdbool.h>
int main()
{
int fils, cols, nMinas; //ROWS, COLUMNS, NUMBER OF MINES
printf("Introduzca el número de filas: ");
scanf("%d", &fils);
printf("Introduzca el número de columna: ");
scanf("%d", &cols);
printf("Introduzca el número de minas: ");
scanf("%d", &nMinas);
Tablero tab = crearTablero(fils, cols, nMinas);//CREATE BOARD
mostrarTablero(tab.tabOculto, tab.x, tab.y);//SHOW HIDDEN BOARD
liberarTablero(tab);//FREE THE MEMORY
return 0;
}
tablero.h
#ifndef TABLERO_H_INCLUDED
#define TABLERO_H_INCLUDED
typedef struct{
int x;//ROWS
int y;//COLUMNS
int numMinas;//NUMBER OF MINES
char **tabOculto;//HIDDEN BOARD
char **tabVisible;//VISIBLE BOARD
} Tablero;
Tablero crearTablero(int x, int y, int numMinas);//CREATE BOARD
void mostrarTablero(char **tab, int x, int y);//SHOW BOARD
void liberarTablero(Tablero tab);//FREE BOARD
#endif // TABLERO_H_INCLUDED
tablero.c
#include "tablero.h"
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
//CREATE BOARD
Tablero crearTablero(int x, int y, int numMinas){
Tablero tab;
tab.x = x;//ROWS
tab.y = y;//COLUMNS
tab.numMinas = numMinas;//NUMBER OF MINES
int i, j, k, l;
//Iniciamos y establecemos el contenido del tablero que se va a ver por consola
//INITIATE AND ESTABLISH THE CONTENT OF THE VISIBLE BOARD
tab.tabVisible = (char**) malloc (x * sizeof(char*));
for(i = 0; i < x; i++)
tab.tabVisible[i] = (char*) malloc (y * sizeof(char));
//Rellenamos con asteriscos para marcar la casilla normal
for(i = 0; i < x; i++)
for(j = 0; j < y; j++)
tab.tabVisible[i][j] = '*';
//Iniciamos y establecemos el contenido del tablero oculto, que se irá identificando
//INITIATE AND ESTABLISH THE CONTENT OF THE HIDDEN BOARD
tab.tabOculto = (char**) malloc (x * sizeof(char*));
for(i = 0; i < x; i++)
tab.tabOculto[i] = (char*) malloc (y * sizeof(char));
//Rellenamos con ceros antes de distribuir minas
//FIRST, FILL EVERYTHING WITH '0'
for(i = 0; i < x; i++)
for(j = 0; j < y; j++)
tab.tabOculto[i][j] = '0';
//Introducimos las minas aleatoriamente
//ESTABLISH RANDOM MINE POSITION
srand(time(NULL));
for(i = 0; i < tab.numMinas; i++)
tab.tabOculto[(int)rand() % x][(int)rand() % y] = 'X';
//Ponemos los números según las minas que tengan alrededor
//PUT THE NUMBERS DEPENDING ON THE QUANTITY OF MINES AROUND AND THE POSITION
for(i = 0; i < x; i++)
for(j = 0; j < y; j++)
if(tab.tabOculto[i][j] == 'X'){
//Esquina superior izquierda: de posx, posy a posx+1, posy+1
if(i == 0 && j == 0){
for(k = i; k <= i+1; k++)
for(l = j; l <= j+1; l++)
if(tab.tabOculto[k][l] != 'X')
tab.tabOculto[k][l]++;
}
//Esquina superior derecha: de posx, posy-1 a posx+1, posy
else if(i == 0 && j == y){
for(k = i; k <= i+1; k++)
for(l = j-1; l <= j; l++)
if(tab.tabOculto[k][l] != 'X')
tab.tabOculto[k][l]++;
}
//Esquina inferior izquierda: de posx-1, posy a posx, posy+1
else if(i == x && j == 0){
for(k = i-1; k <= i; k++)
for(l = j; l <= j+1; l++)
if(tab.tabOculto[k][l] != 'X')
tab.tabOculto[k][l]++;
}
//Esquina inferior derecha: de posx-1, posy-1 a posx, posy
else if(i == x && j == y){
for(k = i-1; k <= i; k++)
for(l = j-1; l <= j; l++)
if(tab.tabOculto[k][l] != 'X')
tab.tabOculto[k][l]++;
}
//Borde superior: de posx, posy-1 a posx+1, posy+1
else if(i == 0){
for(k = i; k <= i+1; k++)
for(l = j-1; l <= j+1; l++)
if(tab.tabOculto[k][l] != 'X')
tab.tabOculto[k][l]++;
}
//Borde inferior: de posx-1, posy-1 a posx, posy+1
else if(i == x){
for(k = i-1; k <= i; k++)
for(l = j-1; l <= j+1; l++)
if(tab.tabOculto[k][l] != 'X')
tab.tabOculto[k][l]++;
}
//Borde izquierdo: de posx-1, posy a posx+1, posy+1
else if(j == 0){
for(k = i-1; k <= i+1; k++)
for(l = j; l <= j+1; l++)
if(tab.tabOculto[k][l] != 'X')
tab.tabOculto[k][l]++;
}
//Borde derecho: de posx-1, posy-1 a posx+1, posy
else if(j == y){
for(k = i-1; k <= i+1; k++)
for(l = j-1; l <= j; l++)
if(tab.tabOculto[k][l] != 'X')
tab.tabOculto[k][l]++;
}
//Sin borde: de posx-1, posy-1 a posx+1, posy+1
else{
for(k = i-1; k <= i+1; k++)
for(l = j-1; l <= j+1; l++)
if(tab.tabOculto[k][l] != 'X')
tab.tabOculto[k][l]++;
}
}
return tab;
}
//SHOW BOARD
void mostrarTablero(char **tab, int x, int y){
int i, j;
for(i = 0; i < x; i++){
for(j = 0; j < y; j++)
printf(" %c ", tab[i][j]);
printf("\n");
}
}
//FREE BOARD
void liberarTablero(Tablero tab){
//liberamos la memoria reservada a los arrays
int i;
for(i = 0; i < tab.x; i++){
free(tab.tabOculto[i]);
free(tab.tabVisible[i]);
}
free(tab.tabOculto);
free(tab.tabVisible);
}
You are one off when you determine when you are at the right or bottom borders:
if (j == y)
This can't be true, because it occurs in a loop whose condition is j < y. The right and bottom border cases are never entered and you end up accessing fields at j + 1 and i + 1, which is one entry beyond the array.
You don't need to distinguish between the cases at all. The case determines the bounds of your neighbouring area to scan, but you could do that with a simple calculation and then adjust the range when you are on a border:
int jmin = j - 1;
int jmax = j + 1;
if (j == 0) jmin = 0;
if (jmax == y) jmax = y - 1;
And likewise for i. This will get rid of a lot of repetitive code.

Resources