-1

This is a program to initialize a minesweeper with parameters entered by a user and then print it. I get Segmentation fault (core dumped) when I run it (after I enter the parameters). But it compiles with no errors or warnings. How do I find the error? I tried compiling and running it in Ubuntu terminal and in dev-C++ in Windows 10. No difference. Any ideas? Thank you in advance.

//File: 5.2mineboard_setup.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROWS 101            //Μέγιστο επιτρεπόμενο ύψος πίστας
#define COLUMNS 101         //Μέγιστο επιτρεπομενο μήκος πίστας

void welcome(void);
int getRows(void);
int getColumns(void);
int getBombs(int, int);
void initializeBoard(char board[ROWS][COLUMNS], int, int);
void putBombs(char board[ROWS][COLUMNS], int, int, int);
void putNums(char board[ROWS][COLUMNS], int, int);
void putBorder(char board[ROWS][COLUMNS], int, int);
void printBoard(char board[ROWS][COLUMNS], int, int);

int main(void)
{
//  system ("chcp 1253");                   //Uncomment to run in Windows. Comment to run on Unix
    int Rows, Columns, Bombs;
    char Board[ROWS][COLUMNS];
    welcome();                              //Μήνυμα υποδοχής
    Rows = getRows();                       //Πλήθος γραμμών
    Columns = getColumns();                 //Πλήθους στηλών
    Bombs = getBombs(Rows, Columns);        //Εισαγωγή πλήθους βομβών
    initializeBoard(Board, Rows, Columns);  //Αρχικοποίηση του πίνακα με χαρακτήρες κενού
    putBombs(Board, Rows, Columns, Bombs);  //Τυχαία τοποθέτηση βομβών (όχι στις ακραίες στήλες και σειρές)
    putNums(Board, Rows, Columns);          //Καταμέτρηση βομβών σε γειτονικά τετράγωνα
    putBorder(Board, Rows, Columns);        //Τοποθέτηση περιγράμματος πίστας
    printBoard(Board, Rows, Columns);       //Εκτύπωση πίστας
    return 0;
}

//Τίτλος προγράμματος
void welcome(void)
{
    printf("Δημιουργία πίστας ναρκαλιευτή\n");
    printf("=============================\n\n");
}   

//Εισαγωγή ύψους πίστας
int getRows(void)
{   
    int rows;
    printf("Εισάγετε ύψος πίστας από 1 ως %d: \n", (ROWS-2));
    scanf ("%d",&rows);
    while(rows>(ROWS-2))    //Έλεγχος αν το ύψος υπερβαίνει το μέγιστο επιτρεπόμενο
    {
        printf("Υπερβολικά μεγάλο ύψος. Εισάγετε νέο ύψος: \n");
        scanf("%d",&rows);          
    }
    return rows;
}   

//Εισαγωγή μήκους πίστας
int getColumns(void)
{
    int columns;
    printf("Εισάγετε μήκος πίστας από 1 ως %d: \n", (COLUMNS-2));
    scanf ("%d",&columns);
    while(columns>(COLUMNS-2))  //Έλεγχος αν το μήκος υπερβαίνει το μέγιστο επιτρεπόμενο
    {
        printf("Υπερβολικά μεγάλο μήκος. Εισάγετε νέο μήκος: \n");
        scanf("%d",&columns);           
    }
    return columns;
}   

//Εισαγωγή αριθμού βομβών
int getBombs(int r, int c)
{   
    int bombs;
    printf("Εισάγετε πλήθος βομβών από 1 ως %d: \n", (r*c));
    scanf ("%d",&bombs);
    while(bombs>(r*c))  //Έλεγχος αν χωράνε οι βόμβες
    {
        printf("Όπα, δε χωράνε τόσες βόμβες. Εισάγετε νέο πλήθος βομβών: \n");
        scanf("%d",&bombs);         
    }
    return bombs;
}

//Αρχικοποίησε πίνακα με χαρακτήρες κενού
void initializeBoard(char board[ROWS][COLUMNS], int rows, int columns)
{
    int i, j;
    for(i=0; i<(ROWS); i++)
        for(j=0; j<(COLUMNS); j++)
            board[i][j] = ' ';
}

/*Τοποθέτησε x βόμβες σε τυχαίες θέσεις
(όχι στο περίγραμμα), προσεχοντας να μη συμπέσουν*/
void putBombs(char board[ROWS][COLUMNS], int rows, int columns, int bombs)
{
    int i, j, k;
    srand(time(NULL));
    for(k=0; k<bombs; k++)              //Επανάλαβε τόσες φορές όσες οι βόμβες
    {
        do
        {
            i = 1 + rand()/rows;        //Τυχαία επιλογή γραμμής
            j = 1 + rand()/columns;     //Τυχαία επιλογή στήλης
        }
        while(board[i][j] != ' ');      //Αν είναι βόμβα, κάνε νέα τυχαία επιλογή
        board[i][j] = '*';              //Βάλε βόμβα
    }
}   

/*Τοποθέτησε αριθμούς με το πλήθος των γειτονικών βομβών
στα κελιά που δεν έχουν βόμβες (όχι στο περίγραμμα)*/
void putNums(char board[ROWS][COLUMNS], int rows, int columns)
{
    int i, j, k, l;
    char n;                                     //Πλήθος γειτονικών βομβών σε μορφή char
    int m = 0;                                  //Αρχικοποίηση μετρητή βομβών
    for(i=1; i<(rows-1); i++)                   //Για κάθε εσωτερικό κελί
        {
        for(j=1; j<(columns-1); j++)
            if(board[i][j] != '*')              //Αν δεν είναι βόμβα
                for(k=(i-1); k<i+2; k++)        //Έλεγξε τα γειτονικά κελιά
                    for(l=(j-1); l<j+2; l++)    
                        if(board[k][l] = '*')   //Για καθένα που είναι βόμβα
                            m++;                //Αύξησε τον μετρητή βομβών κατά 1
        char n = (char)m;                       //casting από int σε char για το πλήθος γειτονικών βομβών
        board[i][j] = 'm';                      //Δώσε στο κελί την τιμή του μετρητή βομβών
        }
}

//Καταχώρισε περίγραμμα πίστας
void putBorder(char board[ROWS][COLUMNS], int rows, int columns)
{
    int i, j;
    if(i==0 || i==rows+1)
        board[i][j] = '-';
    if(j==0 || j==columns+1)
        board[i][j] = '|';
}

//Τύπωσε τελική πίστα
void printBoard(char board[ROWS][COLUMNS], int rows, int columns)
{
    int i,j;
    for(i=0; i<rows+1; i++)
    {
        printf("\n");
        for(j=0; j<columns+1; j++)
        {
            printf("%c", board[i][j]);
        }
    }
    printf("\n");
}
adonle
  • 1
  • Possible duplicate of [Determine the line of code that causes a segmentation fault?](https://stackoverflow.com/questions/2876357/determine-the-line-of-code-that-causes-a-segmentation-fault) –  Dec 31 '18 at 21:29
  • Please read [mcve] and take special note of the link (near the page bottom) about debugging small programs. – AdrianHHH Dec 31 '18 at 22:03
  • the posted code causes the compiler to output several warnings many of which MUST be corrected. Especially the warnings about using uninitialized variables. When compiling, always enable the warnings, then fix those warnings. ( for `gcc`, at a minimum use: `-Wall -Wextra -Wconversion -pedantic -std=gnu11` ) Note: other compilers use different options to produce the same thing – user3629249 Jan 01 '19 at 01:16

1 Answers1

1

No compiler warnings? Why not?

Function putBorder uses uninitialised variables i and j.

void putBorder(char board[ROWS][COLUMNS], int rows, int columns)
{
    int i, j;
    if(i==0 || i==rows+1)
        board[i][j] = '-';
    if(j==0 || j==columns+1)
        board[i][j] = '|';
}

The function seems to be missing some loops, as seen in function printBoard.

void putBorder(char board[ROWS][COLUMNS], int rows, int columns)
{
    int i, j;
    for(i=0; i<rows+1; i++)
    {
        for(j=0; j<columns+1; j++)
        {
            if(i==0 || i==rows+1)
                board[i][j] = '-';
            if(j==0 || j==columns+1)
                board[i][j] = '|';
        }
    }
}

However, having copied those loops, their upper limit seems off-by-1. So I suggest

i<rows+2
j<columns+2

etc, in both these functions, to allow for a border all round.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • 1
    Neither GCC nor Clang warn for it by default. @adonie So add `-Wall -Wextra` to your compiler invocation to be warned! (or the equivalent for your compiler). –  Dec 31 '18 at 21:52