1
#include<stdio.h>

int main()
{
    int size,i;
    printf("Enter size of square: ");
    scanf("%d",&size);
    int square[size][size];

    int cord_x = 1;
    int cord_y = 0;

    for(i=1;i<=(size*size);i++)
    {
        if(cord_x>(size-1))
        {
            cord_x -= size+1;
        }
        if(cord_y>(size-1))
                {
                        cord_y -= size+1;
                }

        if(square[cord_y][cord_x] == NULL)
        {
            square[cord_y][cord_x] = i;
            cord_y += 1;
            cord_x += 1;
        }
        else
        {
            continue;
        }

        show(square,size);
    }
    return 0;
}

show(array,s)
int s,array[s][s];
{
    int i,j;
    for(i=0;i<s;i++)
    {
        for(j=0;j<s;j++)
        {
            printf("%d ",array[j][i]);
        }
    }
    printf("\n");
}

Trying to make a program for magic square(sum of numbers in each row for n x n matrix equal). I am new to C and don't know why it's not working.

I used the following algorithm:

  • Place initial number at middle of top row (e.g. k)
  • Move up one row and right one column and place k+1
  • If move takes you above top row, go to bottom row(same for columns)
  • If move takes you to prefilled square or you move out of right corner square, place k+1 immediately below k

Edit:Put square[size][size] after scanf

Expected Output :
8 1 6
3 5 7
4 9 2

Compiler Output:
0 0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 2 0

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
Saphereye
  • 121
  • 3
  • 1
    Welcome to SO. How many elements can your array hold? `int square[size][size];` Does your compiler complain in this line? If not, you should enable more warnings. For GCC you can use `-Wall -Wextra` options. – Gerhardh Aug 30 '21 at 08:49
  • 1
    What is the value of `size` when you define your array? You don't set `size` until *after* you have create the array `square`. – Some programmer dude Aug 30 '21 at 08:49
  • 2
    General advice for segfaults: Run your program in a debugger and see where the segfault happens. Then check all involved variables in or before that line. – Gerhardh Aug 30 '21 at 08:50
  • I also am not sure if `cord_x` and `cord_y` might be correct. – Some programmer dude Aug 30 '21 at 08:51
  • You need to put `scanf("%d",&size);` before `int square[size][size];` to avoid working with uninitialized variables – George Aug 30 '21 at 08:52
  • 3
    Lastly, whatever source you're using to learn C, throw it away and get a new modern one! The one you use teaches old, ***very*** old ways that aren't relevant now. I can see that with the definition of the `show` function. – Some programmer dude Aug 30 '21 at 08:52
  • `scanf("%d",&size);` before `int square[size][size];` removed the error, still the output is incorrect. Might be some logical error. – Saphereye Aug 30 '21 at 09:05
  • 2
    `if(square[cord_y][cord_x] == NULL)` compares an uninitialized entry of the array with a pointer. What do you expect with this line? Are you confused by the difference of `0` and `NULL`? – mch Aug 30 '21 at 09:13
  • @mch I want to check if the cell is empty or not before inserting value, does an empty array contain 0 for non-inserted values? – Saphereye Aug 30 '21 at 09:15
  • 1
    You never initialize the `square` array. Local variables are not set to 0 by default, they contain un undeterminate value. – Jabberwocky Aug 30 '21 at 09:19
  • @Saphereye Non-static empty arrays will contain random values that are not necessarily 0. See [What happens to a declared, uninitialized variable in C? Does it have a value?](https://stackoverflow.com/a/1597426/12307084) – George Aug 30 '21 at 09:35
  • Please don't edit out the programming errors - the comments won't make any sense to readers, and you introduced more mistakes: rolled back. This isn't a "live editing" site. – Weather Vane Aug 30 '21 at 10:02
  • C doesn't have the concept of "empty" or "null" values. Everything have a value. If it's not initialize it will have an *indeterminate* value, which you can't use. And the symbol `NULL` is for null *pointers*. I stand by my previous question: Please get a (new and modern, created at least the last 10-20 years) beginners C book to read – Some programmer dude Aug 30 '21 at 10:18

2 Answers2

2

You are breaking the bounds of the array index, with

if(cord_x>(size-1))
{
    cord_x -= size+1;
}
if(cord_y>(size-1))
{
    cord_y -= size+1;
}

You see, when cord_x == size the new value will be -1.

It is better to wrap the array index at the point of increment, so replace

cord_y += 1;
cord_x += 1;

with

cord_y = (cord_y + 1) % size;
cord_x = (cord_x + 1) % size;

and remove the faulty range tests.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
1

I used the following algorithm:

  • Place initial number at middle of top row (e.g. k). False: you start in the second column and the first row (always, independent of the variable size ---which should be odd, but you don't say this) This is important to make the two diagonals to add up to the same value of the rows/columns
  • Move up one row and right one column and place k+1. False: you move down one row and right one column. You need to decrement the row (to move up) and increment the column (to move right).
  • If move takes you above top row or left column, go to bottom row(or left column). You try to implement this in a very complex way. When you get to the bottom (col == size, after incrementing) you have to move to the top (col = 0, or col -= size, as you have incremented it you need to move up size rows, not size + 1)
  • If move takes you to prefilled square or you move out of right corner square, place k+1 immediately below k. This is one row increment.

Well this is the known formula for a magic square (one that fills a square matrix with the numbers 1 to size*size in a way that all rows add to the same number, all columns the same and the two grand diagonals too.)

The thing (after solving all the things you don't do well) should go in a way similar to this:

/* ms.c -- magic square.
 * Author: Luis Colorado.
 * Date: Fri 03 Sep 2021 02:08:34 PM EEST
 * Copyright: (C) 2021 Luis Colorado.  All rights reserved.
 * License: BSD.
 */

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

#define MAX 1023
#define DFLT 11

int square[MAX][MAX];
int sum_main_diag,
    sum_anti_diag,
    sum_cols[MAX],
    sum_rows[MAX];
char DOUBLE_LINE[] = "========================";
char SINGLE_LINE[] = "------------------------";

int main(int argc, char **argv)
{
    int opt; /* option */
    int size = DFLT;

    while ((opt = getopt(argc, argv, "n:")) >= 0) {
        switch (opt) {
        case 'n': size = atoi(optarg);
            if (size < 1 /* size must be >= 1 */
                || size > MAX /* and <= MAX */
                /* || !(size & 1) */) /* ...and odd, commented (see below) */
            {
                fprintf(stderr,
                        "N defaulting to %d, as provided "
                        "value (%s) was invalid\n",
                        DFLT, optarg);
                size = DFLT;
            }
            break;
        } /* switch */
    }

    int row = 0, /* top row */
        col = size/2, /* middle cell */
        total = size * size, /* total number of cells */
        i; /* number to put in the cell */

    for (i = 1; i <= total; i++) {
        square[row][col] = i; /* fill the square */
        if (row == col) { /* add to anti_diag */
            sum_anti_diag += i;
        }
        if (row + col + 1 == size) { /* add to main diag */
            sum_main_diag += i;
        }
        sum_cols[col] += i; /* add to col */
        sum_rows[row] += i; /* add to row */

        int nxtrow = row,  /* next row to go */
            nxtcol = col; /* next col to go */
        nxtrow--;
        if (nxtrow < 0) { /* top row */
            nxtrow = size - 1; /* rules 2 & 3 */
        }
        nxtcol++;
        if (nxtcol >= size) { /* right column */
            nxtcol = 0; /* rules 2 & 3 */
        }
        if (square[nxtrow][nxtcol]) { /* rule four */
            /* next cell is the located below the initial */
            nxtrow = row + 1;
            if (nxtrow >= size) { /* check boundary, not needed */
                nxtrow = 0;
            }
            nxtcol = col;
        }
        col = nxtcol; /* ... update */
        row = nxtrow;
    }

    /* print them all */
    int digs = snprintf(NULL, 0, "%d", total);
    int digs_sums = snprintf(NULL, 0, "%d", total*(total+1)/2/size);

    for (row = 0; row < size; row++) {
        printf("%*s +", digs_sums, "");
        for (col = 0; col < size; col++)
            printf("%.*s+", digs_sums, SINGLE_LINE);
        printf("\n%*d |", digs_sums, row);
        for (col = 0; col < size; col++) {
            printf("%*d|", digs_sums, square[row][col]);
            int val = square[row][col];
        }
        printf(" ==> %*d\n", digs, sum_rows[row]);
    }
    printf("%*s +", digs_sums, "");
    for (col = 0; col < size; col++)
        printf("%.*s+", digs_sums, DOUBLE_LINE);
    printf("\n%*d/|", digs, sum_anti_diag);
    for (col = 0; col < size; col++)
        printf("%*d|", digs, sum_cols[col]);
    printf("\\    %d\n", sum_main_diag);

    return 0; /* OK exit code */
}

that will print something like:

$ ms -n 3
   +--+--+--+
 0 | 8| 1| 6| ==> 15
   +--+--+--+
 1 | 3| 5| 7| ==> 15
   +--+--+--+
 2 | 4| 9| 2| ==> 15
   +==+==+==+
15/|15|15|15|\    15
$ ms -n 5
   +--+--+--+--+--+
 0 |17|24| 1| 8|15| ==> 65
   +--+--+--+--+--+
 1 |23| 5| 7|14|16| ==> 65
   +--+--+--+--+--+
 2 | 4| 6|13|20|22| ==> 65
   +--+--+--+--+--+
 3 |10|12|19|21| 3| ==> 65
   +--+--+--+--+--+
 4 |11|18|25| 2| 9| ==> 65
   +==+==+==+==+==+
65/|65|65|65|65|65|\    65
$ ms -n 6 # I've commented the odd test to see that the magic square is invalid.
    +---+---+---+---+---+---+
  0 | 19| 27| 35|  1|  9| 17| ==> 108
    +---+---+---+---+---+---+
  1 | 26| 34|  6|  8| 16| 24| ==> 114
    +---+---+---+---+---+---+
  2 | 33|  5|  7| 15| 23| 25| ==> 108
    +---+---+---+---+---+---+
  3 |  4| 12| 14| 22| 30| 32| ==> 114
    +---+---+---+---+---+---+
  4 | 11| 13| 21| 29| 31|  3| ==> 108
    +---+---+---+---+---+---+
  5 | 18| 20| 28| 36|  2| 10| ==> 114
    +===+===+===+===+===+===+
123/|111|111|111|111|111|111|\    93
$ ms
    +---+---+---+---+---+---+---+---+---+---+---+
  0 | 68| 81| 94|107|120|  1| 14| 27| 40| 53| 66| ==> 671
    +---+---+---+---+---+---+---+---+---+---+---+
  1 | 80| 93|106|119| 11| 13| 26| 39| 52| 65| 67| ==> 671
    +---+---+---+---+---+---+---+---+---+---+---+
  2 | 92|105|118| 10| 12| 25| 38| 51| 64| 77| 79| ==> 671
    +---+---+---+---+---+---+---+---+---+---+---+
  3 |104|117|  9| 22| 24| 37| 50| 63| 76| 78| 91| ==> 671
    +---+---+---+---+---+---+---+---+---+---+---+
  4 |116|  8| 21| 23| 36| 49| 62| 75| 88| 90|103| ==> 671
    +---+---+---+---+---+---+---+---+---+---+---+
  5 |  7| 20| 33| 35| 48| 61| 74| 87| 89|102|115| ==> 671
    +---+---+---+---+---+---+---+---+---+---+---+
  6 | 19| 32| 34| 47| 60| 73| 86| 99|101|114|  6| ==> 671
    +---+---+---+---+---+---+---+---+---+---+---+
  7 | 31| 44| 46| 59| 72| 85| 98|100|113|  5| 18| ==> 671
    +---+---+---+---+---+---+---+---+---+---+---+
  8 | 43| 45| 58| 71| 84| 97|110|112|  4| 17| 30| ==> 671
    +---+---+---+---+---+---+---+---+---+---+---+
  9 | 55| 57| 70| 83| 96|109|111|  3| 16| 29| 42| ==> 671
    +---+---+---+---+---+---+---+---+---+---+---+
 10 | 56| 69| 82| 95|108|121|  2| 15| 28| 41| 54| ==> 671
    +===+===+===+===+===+===+===+===+===+===+===+
671/|671|671|671|671|671|671|671|671|671|671|671|\    671
$ _

(parameter -n allows any odd number between 1 and 1023, and defaults ---e.g. option is not used--- to 11)

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31