Take the 2-minute tour ×

I'm writing code that asks for two positive integers entered from the keyboard. The first integer N is odd in the range 3-15, and the second will have an initial value I. N will be the size of the array. Beginning in the center of the NxN array with the integer I. If I is prime then print the number I in that position of the square. Otherwise print three asterisks in that position. Move to the right one square, and test the integer I+1 for primality. Print I+1 if it is prime and three asterisks if it is not. Continue going counter clockwise through the square until the square is full of numbers and three asterisks, then print the array.

That's the problem; I have done most of it and am confused as to how to make the array and if any one could take a look at my code to let me know if I have my for loop set up correctly. Thank you kindly for your help.

#include <stdio.h>

    int N, I;

    printf("Enter an odd integer n between 3 and 15: ");
    scanf("%d", &N);

    printf("Enter an initial value i: ");
    scanf("%d", &I);

    int arr[N][N];
    int k = 1;
    int i = N / 2 + 1;
    int j = N / 2 + 1;

    while(k < N) {
            int s;

            for(s = 0; s < k; s++, i++, I++)
                    arr[i][j] = IsPrime(I) ? I : -1;
            for(s = 0; s < k; s++, j--, k++)
                    arr[i][j] = IsPrime(I) ? : -1;
            for(s = 0; s < k; s++, i--, I++)
            for(s = 0; s < k; s++, j++, I++)

            if(IsPrime(i) == 1) {
                return i;
            } else {
            return 0;

int IsPrime(int n) {
    int i, count = 0;

            if((n % i) == 0) count++;
share|improve this question
Why IsPrime does not return anything? –  aoeu Dec 3 '11 at 20:58
Well, it's not wrong. Have you learned about malloc yet? –  Greg Hewgill Dec 3 '11 at 21:04
@Michael: wrong. typecast is not needed for malloc in C. Only C++ needs it, see C tag. –  user411313 Dec 3 '11 at 21:25
I believe in "C", you cannot declare variables after code. You must declare all variables at top of scope. What you are doing will not work. –  Jim Rhodes Dec 3 '11 at 21:34
Variable length arrays are a C99 feature. Microsoft's C compiler doesn't support C99, so if you're using that, you have to malloc. –  Daniel Fischer Dec 3 '11 at 21:51
show 9 more comments

1 Answer

up vote 10 down vote accepted

OK, so there's a lot wrong here, and plenty to explain. Let's start with the really obvious stuff that prevents this even running, and move on afterwards. I'm going to use C89, so I'll do declare all my local variables at the start of each method. I'll be using gcc 4.6.1, and compiling with -W -Wall -ansi -pedantic -g -lm. We will need the -lm shortly - it links to the math library.


So, your IsPrime(int n) appears to be missing some pieces at the bottom. As such, I can't even say whether it will work or not.

Let's forward declare it by putting int IsPrime(int n); at the top of the file just below #include stdio.h. While we're at it, let's add some more includes, too:

#include <stdlib>
#include <math.h> /* For sqrt() */

Now, let's replace the body of the method with something that should work (well, you don't have to, but I will because I can't see the rest of your method):

int IsPrime (int n) {
  int i, sqrtN;

  if (n < 2) { return 0; } /* 1, 0, and negatives are nonprime */
  if (n == 2) { return 2; }
  if ((n % 2) == 0) { return 0; } /* Check for even numbers */
  sqrtN = sqrt(n) + 1; /* We don't need to search all the way up to n */
  for (i = 3; i < sqrtN; i += 2) {
    if (n % i == 0) { return 0; } /* Stop, because we found a factor! */
  return n;

main() and scanf()

You aren't using arguments to main() so let's change it to int main(void) {. When you call scanf(), you should check the result - it will return the number of things matched successfully, or EOF. You should also check the values it stored, since you require N to have a specific range and I to be positive.

So, let's try using this at the start of main():

int N, I;
int s;
int i, j, k;
int **arr; /* More on this later*/

s = scanf("%d", &N);
if (s != 1) {
  printf("No proper input provided; program will now exit");
  return 0; /* Or we could use EXIT_SUCCESS, which is defined by stdlib */
} else if (N < 3 || N > 15) {
  /* I have assumed the range of 3 to 15 to be inclusive here */
  printf("I must be positive; program will now exit");
  return 0;

printf("Enter an initial value I: ");
s = scanf("%d", &I);
if (s != 1) {
  return 0;
} else if (I <= 0) {
  return 0;


From the comments on your question, you appear to understand that malloc allocates memory but not necessarily the correct syntax to get it to do so in this instance. That's where the int **arr; comes in. To allocate your two dimensional array of integers, now that we have a legal value for N, we can do arr = malloc(N * sizeof arr[0]); Now, malloc can fail, so we need to check that arr != NULL after that call. And we aren't done yet! That's only one dimension of your array - we've just allocated enough memory for N pointers to one dimensional arrays, pointed to by arr. So we have to loop through and allocate space for those pointers to point to.

So then we do this:

for (s = 0; s < N; ++s) {
  arr[s] = malloc(N * sizeof arr[0][0]); /* Enough space for N integers */
  if (NULL == arr[s]) {
    /* We'll just quit instead of handling this gracefully... */
    /* ...because this is only an example */
    printf("Uh oh! Memory allocation failed! Let's run away!\n");
    return 0;


Now, because you have allocated memory, you will also need to free it when you are done with it. At the end of your main method, you will need a loop to free each of the one dimensional arrays you allocated space for, and then you will need to free arr itself. Like so:

  /* I am paranoid about setting pointers to NULL */
  arr[s] = NULL;

arr = NULL;
/* It can matter if you are going on to do other things instead of exiting. */

return 0;


So, now for the loop that's actually meant to do the moving around the array. You are returning i from main instead of printing out. I'm pretty sure you intended to print it out instead, right? If you need to print out the whole grid, as a grid, you need to do it in a separate pass after testing all the values with IsPrime(). If you just need to print out whether or not the number is prime (well, the number or *) in a spiralling order starting from the centre, then you don't actually need arr at all.

Now, your loop to calculate the numbers is also incorrect (for starters, it runs out of the bounds of the array), but I'm reluctant to solve that for you, because that piece of logic is the point of your homework assignment, so try sorting out everything I've mentioned here first, and then comment if you're still stuck with the logic after that, I guess.

Just by the way, I've avoided changing your variable names, but you might want to consider not mixing I and i and in general naming things more descriptively.

Spiral logic

Disclaimer: There may be better approaches, this is just what came to mind. It does work, though.

The way I think about this is that there is an edge between the middle square and the one to the right of it, and another edge between that square and the one above it, and so on. This forms a spiral pattern. If you draw it, you'll also notice that after every second corner, the number of edges before the next corner increases by one (1,1,2,2,3,3). If we keep track of how long the current side is, when it needs to change, what direction we're going, and when to stop (we know there are N*N total squares, so just count the squares you've filled in so far), then this is relatively straightforward:

totalSquares = N * N;
currentSquare = 0;
currentSideLength = 1; /* Number of edges/transitions per side before we turn */
currentPositionOnSide = 0; /* How far down a side we are*/
increaseSideLength = 0; /* This keeps track of when to increase currentSideLength */
i = j = N / 2; /* The middle */
direction = 0; /* Which way we're going - using an enum here would be better for clarity */

while (currentSquare < totalSquares) {

arr[i][j] = IsPrime(I);
switch (direction) {
  case 0: /* Right */
  case 1: /* Up */
  case 2: /* Left */
  case 3: /* Down */
  default: /* So we can see if something silly goes wrong with the direction! */

  ++currentSquare, ++I, ++currentPositionOnSide;

  if (currentPositionOnSide == currentSideLength) { /* We're at a corner! */
    ++increaseSideLength; /* Keep track of the number of turns */
    currentPositionOnSide = 0;
    direction = (direction + 1) % 4; /* Wrap around */
    if ((increaseSideLength % 2) == 0) { /* Increase every second corner */
      increaseSideLength = 0;

/* Ultra crude formatting - you may want to do better than this */
      if (arr[i][j] == 0) {
        printf(" *** |");
      } else {
        printf("%4d |", arr[i][j]);

Now, I've checked that this works, but I haven't tested the #@! out of it - that's your responsibility. Also, you'll obviously need to add those variables or reuse some of the ones you already have (I'd really recommend using well named ones, though.)

Also, that code abuses IsPrime() by getting it to return n or 0 (0 is not a prime and you said I must be positive, so there's no need to use -1), thus avoiding all your if IsPrime(I) ? I : -1; checks.

share|improve this answer
Wow your awesome! This is the best help I have ever gotten on this website! Thank you SOO Much!!. I thought about the "logic" part and I get what its suppose to do, but getting it to do it im not sure how to implement the for loop for the different movements of the square. –  Cka91405 Dec 4 '11 at 18:32
OK, so I've update my answer with a couple of minor bug fixes (one of the scanf checks, and IsPrime()), a revised IsPrime that returns 0 or n instead of 0 or 1, for convenience and the logic you need to get your grid, with what I hope is an adequate explanation of how it works. –  Iskar Jarak Dec 4 '11 at 21:44
Yes very well said ! i wish my teacher could explain as good as this lol. thank you again for your time to help me with this! –  Cka91405 Dec 5 '11 at 0:03
@Cka91405 All good - if that's sufficient then you should probably accept the answer. –  Iskar Jarak Dec 5 '11 at 0:39
+1 epic answer. –  Greg Hewgill Dec 7 '11 at 7:59
show 6 more comments

Your Answer


