Use the function your wrote to write a program that prompts the user for a positive integer less than 45 (otherwise it will overflow our long long variable) and prints out the factorial of that number.
Add error checking, so that if the user does not enter an integer the program prints "Invalid input" and exits. You should also print "Invalid input" and exit if the user enters a negative number or a number of 45 or more.
factorialFunction.c
#include <stdio.h> #include <stdlib.h> #define MAX 45 //Note this will overflow for large n over 44 long long factorial(int n); int main(void) { int num; printf("Welcome to Factorial Calculator\n"); printf("Enter a positive integer less than %d: ", MAX); if(scanf("%d",&num) == 1 && num >= 0 && num < MAX){ printf("%d! is %lld\n",num,factorial(num)); return EXIT_SUCCESS; } else { printf("Invalid input\n"); return EXIT_FAILURE; } } //Note this will overflow for large n over 44 long long factorial(int n){ long long fact = 1; int i; i = 1; while (i <=n ){ fact = fact * i; i = i + 1; } return fact; }
// This program allows a user to enter a number // and prints out its reciprocal (ie. 1 divided by the number) void reciprocal(double x); int main(void){ double x; printf("Enter a number "); scanf("%lf",&x); reciprocal(x); printf("The reciprocal is %lf\n",x); return EXIT_SUCCESS; } void reciprocal(double x){ if ( x != 0 ){ x = 1.0/x; } }
However the function did not seem to work as intended and gave incorrect output as shown below
Enter a number 3 The reciprocal is 3.000000What is wrong with the code? How can we modify the code to make our function work as intended and in this case get
Enter a number 3 The reciprocal is 0.333333
We can modify the function to return the value it calculates to the main function.
// This program allows a user to enter a number // and prints out its reciprocal (ie. 1 divided by the number) double reciprocal(double x); int main(void){ double x; printf("Enter a number "); scanf("%lf",&x); x = reciprocal(x); printf("Reciprocal is %lf\n",x); return EXIT_SUCCESS; } double reciprocal(double x){ double result; if ( x != 0 ){ result = 1.0/x; } return result; }
numbers
?
numbers[2]
since C uses zero based indexing.
int numbers[20];
and your program assigns a value to each element in the array, what is the problem with the statement x = numbers[20];
?
Behaviour of a program that does this is undefined and it is possible, for example, that it will cause the program to terminate. Sometimes it will retrieve the value of another variable.
int squares[15];
Write a C code fragment to store, in each element of this array, the square of the index of that element, e.g., squares[5] would contain the value 25.
#include <stdio.h> #define ELEMENTS 15 int main(void) { int squares[ELEMENTS]; int i; // Fill the array with values // equal to the square of each index i = 0; while (i < ELEMENTS) { squares[i] = i * i; i = i + 1; } // Let's print the array to check i = 0; while (i < ELEMENTS) { printf("squares[%d] has the value %d\n", i, squares[i]); i = i + 1; } return 0; }
int x; int a[6]; x = 10; a[3 * 2] = 2 * 3 * 7; printf("%d\n", x);mysteriously printed
42
. How could this happen when x
is clearly
assigned only the value 10
?
How can you easily detect such errors before they have mysterious effects?
42
to a[6]
an array element that does not exist.
The result of this is undefined.
In this case the value 42
has apparently been assigned to the variable x
.
Silently changing another variable is a common consequence of use of an an illegal array index.
Subtler and more confusing behaviour are also quite possible.
If you are using a CSE machine you can compile the program with dcc
. It will give you a warning in this example and will
produce a program which will stop immediately with a clear error message if an invalid array index is used. For example:
dcc arrayExample.c arrayExample.c:8:5: warning: array index 6 is past the end of the array (which contains 6 elements) [-Warray-bounds] a[3 * 2] = 2 * 3 * 7; ^ ~~~~~ arrayExample.c:5:5: note: array 'a' declared here EXPLANATION: Careful, on line 8 of `arrayExample.c`, it looks like you're trying to access location 6 of `a`, which doesn't exist; `a` isn't that long. Keep in mind that arrays are 0-indexed.
./a.out ================================================================= arrayExample.c:8:5: runtime error: index 6 out of bounds for type 'int [6]' Execution stopped here in main() in arrayExample.c at line 8: x = 10; --> a[3 * 2] = 2 * 3 * 7; printf("%d\n", x); return 0; Values when execution stopped: a = {1633968431, 825193325, 829645615, 791753017, 1818391920, 1751081833} x = 10 3 * 2 = 6 a[3 * 2] = 795635060
So if 9 numbers were entered the program should print the 5th number entered. And if 27 numbers were entered the program should print the 14th number entered.
If an even number of numbers is entered there are two middle numbers, print the first of them.
For example if 8 numbers are entered, prints the 4th.
You can assume at most 10,000 numbers will be entered.
middle.c
#include <stdio.h> #define MAX_NUMBERS 100000 int main(void) { int numbers[MAX_NUMBERS]; int howMany, value, middleIndex; howMany = 0; while (howMany < MAX_NUMBERS && scanf("%d",&value) == 1) { numbers[howMany] = value; howMany = howMany + 1; } howMany = howMany - 1; middleIndex = howMany / 2; printf("%d\n", numbers[middleIndex]); return 0; }
6 6 6 6 6 6
and what scores do they produce.
total: 6+6+6+6+6+6 = 36 match-2: 2*6+19 = 31 match-3: 3*6 + 21 = 39 match-4: 4*6 + 23 = 47 match-5: 5*6 + 25 = 55 match-6: 6*6 + 27 = 63 The actual output would be: Rule match-6(6) - score 63.
1 1 2 2 3 9
total: 1 + 1 + 2 + 2 + 3 + 9 = 18 match-2(1,1): 2*1 + 19 = 21 match-2(2,2): 2*2 + 19 = 23 sequence-2 (1,2): 2*2+17 = 21 sequence-2 (2,3): 2*3+17 = 23 sequence-3 (1,2,3): 3*3+18 = 27 sum-2(1,1): 1 + 1 + 22 = 24 sum-2(1,2): 1 + 3 + 22 = 26 sum-5(1,1,2,2,3): 1 + 9 + 49 = 59 The actual output would be: Rule sum-5(1+1+2+2+3=9) - score 59.
int x,y; int numValuesRead = scanf("%d %d",&x,&y); printf("I read in %d values : x = %d y = %d\n",numValuesRead,x,y);with the following inputs
#include <stdio.h> #define N 10 int main(void) { int digitCount[N]; int x, lastDigit; while (scanf("%d", &x) == 1) { lastDigit = x % N; digitCount[lastDigit] = digitCount[lastDigit] + 1; } lastDigit = 0; while (lastDigit < N) { printf("%d numbers with last digit %d read\n", digitCount[lastDigit], lastDigit); lastDigit = lastDigit + 1; } return 0; }It works on the students laptop:
gcc -Werror -Wall -O -o last_digit last_digit.c ./last_digit 42 121 100 11 <ctrl-d> 1 numbers with last digit 0 read 2 numbers with last digit 1 read 1 numbers with last digit 2 read 0 numbers with last digit 3 read 0 numbers with last digit 4 read 0 numbers with last digit 5 read 0 numbers with last digit 6 read 0 numbers with last digit 7 read 0 numbers with last digit 8 read 1 numbers with last digit 9 readprint counts of how many numbers read with each possible last digit.
But when run at uni fails
dcc -o last_digit last_digit.c ./last_digit 42 121 100 11 <ctrl-d> 778121076 numbers with last digit 0 read 7632239 numbers with last digit 1 read -2032569224 numbers with last digit 2 read 32727 numbers with last digit 3 read 0 numbers with last digit 4 read 0 numbers with last digit 5 read -2032409578 numbers with last digit 6 read 32727 numbers with last digit 7 read -21600000 numbers with last digit 8 read 32767 numbers with last digit 9 readWhy doesn't the code work at uni .
Why doesn't dcc
detect an error?
digitCount
.
Their program used values elements of digitCount
which
had not previously had values stored in them.
This is illegal C and can hence produce *any* output.
On the student's laptop by chance the bytes used for the array already had zeros in them. This is not uncommon and leads to illegal C seeming to be correct. But changing compiler flags, machine, or even time of day can affect this.
dcc
checks (among other things) that array indices are valid but doesn't check
that array elements have been initialized.
dcc --valgrind
checks that array elements have been initialized (but not that indices are valid)
The student's program can be fixed by adding a loop to initialize the elements of the array digitCount to 0.
A less obvious problem is that entering a negative number will produce an (illegal) negative array index (also fixed below).
Fix the code (make sure you understand how it works - its a common & useful programming pattern).
#include <stdio.h> #define N 10 int main(void) { int digitCount[N]; int x, lastDigit; lastDigit = 0; while (lastDigit < N) { digitCount[lastDigit] = 0; lastDigit = lastDigit + 1; } while (scanf("%d", &x) == 1) { lastDigit = x % N; if (lastDigit < 0) { lastDigit = - lastDigit; } digitCount[lastDigit] = digitCount[lastDigit] + 1; } lastDigit = 0; while (lastDigit < N) { printf("%d numbers with last digit %d read\n", digitCount[lastDigit], lastDigit); lastDigit = lastDigit + 1; } return 0; }
occur.c
which reads 6 numbers then reads another number
and prints how many times that number occurred in the first 6.
For example:
./occur Enter 6 numbers: 1 3 1 3 1 9 Enter a number: 1 1 occurred 3 times in the 6 numbers readMake sure you make you make it very easy to change how many numbers the program reads. Note: For now let's do this without creating any functions.
occur.c
#include <stdio.h> #define N_NUMBERS 6 int main(void) { int x[N_NUMBERS], i, j, match, count; printf("Enter %d numbers: ", N_NUMBERS); i = 0; while (i< N_NUMBERS) { scanf("%d", &x[i]); i = i + 1; } count = 0; printf("Enter a number: "); scanf("%d", &match); j = N_NUMBERS - 1; while (j >= 0) { if (x[j] == match) { count = count + 1; } j = j - 1; } printf("%d occurred %d times in the %d numbers read\n", match, count, N_NUMBERS); return 0; }
occurFunctions.c
#include <stdio.h> #define N_NUMBERS 6 void readData(int data[],int size); int findOccurrences(int data[], int size, int key); int main(void) { int x[N_NUMBERS], match, count; printf("Enter %d numbers: ", N_NUMBERS); readData(x,N_NUMBERS); printf("Enter a number: "); scanf("%d", &match); count = findOccurrences(x,N_NUMBERS,match); printf("%d occurred %d times in the %d numbers read\n", match, count, N_NUMBERS); return 0; } void readData(int data[],int size){ int i = 0; while (i< size) { scanf("%d", &data[i]); i = i + 1; } } int findOccurrences(int data[], int size, int key){ int count = 0; int j = size - 1; while (j >= 0) { if (data[j] == key) { count = count + 1; } j = j - 1; } return count; }
int arrayLength(int nums[])which returns the number of elements in the array
nums
.
It is not possible for a C function to determine the length of an array it has been passed.
Programmers usually do one of 3 things.
int testAllInitialised(int nums[], int size)which returns 1 if all elements of array nums are initialized, otherwise returns 0.
It is not possible at runtime in C to determine if a variable has been initialized
C programmers must take care to ensure that all variables, including array elements, are appropriately initialized.
void sqrtIndex( double a[], int n )which takes an array
a
[] of n
double values and sets each values to be the square root of their index.
Hint: Use the math.h library function
double sqrt(double)
. How would you compile this if you were using gcc?
sqrtIndex
including a main function for testing.
#include <stdio.h> #include <math.h> #define MAX_NUMBERS 100 void sqrtIndex( double a[], int n ); int main(void) { int i; double numbers[MAX_NUMBERS]; sqrtIndex(numbers,MAX_NUMBERS); i = 0; while (i < MAX_NUMBERS) { printf("%lf ",numbers[i]); i = i + 1; } printf("\n"); return 0; } void sqrtIndex( double a[], int n ) { int i; i = 0; while( i < n ) { a[i] = sqrt(i); i = i + 1; } }
gcc -Wall -Werror -O -o sqrtIndex sqrtIndex.c -lmIf you were using dcc you would compile as usual.
It should have this prototype:
int nonDecreasing(double array[], int length)
nonDecreasing
that includes a main function for testing.
#include <stdio.h> #define MAX_NUMBERS 100000 int nonDecreasing(int array[], int length); int main(void) { int numbers[MAX_NUMBERS]; int n_numbers, number_read; n_numbers = 0; number_read = 1; while (number_read == 1 && n_numbers < MAX_NUMBERS) { number_read = scanf("%d", &numbers[n_numbers]); n_numbers = n_numbers + 1; } if (nonDecreasing(numbers, n_numbers-1)) { printf("The numbers are in non-decreasing order\n"); } else { printf("The numbers are not in non-decreasing order\n"); } return 0; } int nonDecreasing(int array[], int length) { int i; i = 1; while (i < length) { if (array[i - 1] > array[i]) { return 0; } i = i + 1; } return 1; }
dotProduct
, that calculates the dot-product
of two vectors of integers. Assume it has the following prototype
int dotProduct(int vector1[VECTOR_LENGTH], int vector2[VECTOR_LENGTH])
Reminder you calculate the dot product by multiplying corresponding elements and summing the result. For example the dot product of vector 1,3,1,3,2 and 2,1,2,1,2 would be 14
dotProduct.c
.
#include <stdio.h> #define VECTOR_LENGTH 10 int dotProduct(int vector1[VECTOR_LENGTH], int vector2[VECTOR_LENGTH]); int main(void) { int vector1[VECTOR_LENGTH]; int vector2[VECTOR_LENGTH]; int i; printf("Enter vector 1 of %d positive numbers: ", VECTOR_LENGTH); i = 0; while (i < VECTOR_LENGTH) { scanf("%d", &vector1[i]); i = i + 1; } printf("Enter vector 2 of %d positive numbers: ", VECTOR_LENGTH); while (i < VECTOR_LENGTH) { scanf("%d", &vector2[i]); i = i + 1; } printf("Their dot-product is %d.\n", dot_product(vector1, vector2)); return 0; } int dotProduct(int vector1[VECTOR_LENGTH], int vector2[VECTOR_LENGTH]) { int i, dotProduct; dotProduct = 0; i = 0; while (i < VECTOR_LENGTH) { dotProduct = dotProduct + vector1[i] * vector2[i]; i = i + 1; } return dotProduct; }
int nums1[10];
int nums2[] = {0,1,2,3,4,5,6,7,8,9};
int nums3[10] = {0,2,4,6,8,-2};
int nums4[10] = {0};
int nums5[2][10] = {{0,1,2,3,4,5,6,7,8,9}, {10,20,30,40,50,60,70,80,90,100}};
nums5[0]
contains
0,1,2,3,4,5,6,7,8,9. The array at nums5[1]
contains
10,20,30,40,50,60,70,80,90,100
int nums6[][10] = {{0},{9},{1}};
nums6[0]
contains
0,0,0,0,0,0,0,0,0,0. The array at nums6[1]
contains
9,0,0,0,0,0,0,0,0,0. The array at nums6[2]
contains
1,0,0,0,0,0,0,0,0,0.
int i; printf("%d\n",nums2[3]); prints 3 printf("%d\n",nums3[5]); prints -2 printf("%d\n",nums5[0][1]); prints 1 printf("%d\n",nums5[1][0]); prints 10 nums1[0] = nums2[1] + 10 ; printf("%d\n",nums1[0]); prints 11 i = 0; printf("%d\n",nums1[i]); prints 11
printf("%d\n",nums2[10]); This is an error. The indexes in nums2 go from 0..9. By using an index of 10 we are trying to go past the end of the array printf("%d\n",nums5[2][0]); This is an error. The first index in nums5 goes from 0..1. By using an index of 2 we are trying to go past the end of the array printf("%d\n",nums5[1][10]); This is an error. The second index in nums5 goes from 0..9. By using index of 10 we are trying to go past the end of the array
matrix
below hold?
#include <stdio.h> #define N_ROWS 12 #define N_COLUMNS 15 int main(void) { int matrix[N_ROWS][N_COLUMNS];
void initialiseMatrix(int matrix[N_ROWS][N_COLUMNS]);that uses nested while loops to set every element of
matrix
.
Each element should be set to the product of its two indices.
Write a function with the following prototype
void printMatrix(int matrix[N_ROWS][N_COLUMNS]);that uses nested while loops to print the elements of
matrix
plus sums of each
row and sums of each column.
Write a main program that uses these functions
The output of your code should look like this:
./a.out 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 105 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 | 210 0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 | 315 0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 | 420 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 | 525 0 6 12 18 24 30 36 42 48 54 60 66 72 78 84 | 630 0 7 14 21 28 35 42 49 56 63 70 77 84 91 98 | 735 0 8 16 24 32 40 48 56 64 72 80 88 96 104 112 | 840 0 9 18 27 36 45 54 63 72 81 90 99 108 117 126 | 945 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 | 1050 0 11 22 33 44 55 66 77 88 99 110 121 132 143 154 | 1155 --------------------------------------------------------------------------- 0 66 132 198 264 330 396 462 528 594 660 726 792 858 924
// Read SIZE x SIZE numbers and test if // they form a magic square http://en.wikipedia.org/wiki/Magic_square // // // Andrew Taylor - andrewt@cse.unsw.edu.au // 10/4/13 /* // Lo Shu Square // 4 9 2 // 3 5 7 // 8 1 6 // // Magic square of primes // 17 89 71 // 113 59 5 // 47 29 101 */ #include <stdio.h> #define SIZE 3 void readSquare(int square[SIZE][SIZE]); void printSquare(int square[SIZE][SIZE]); int sumFirstRow(int square[SIZE][SIZE]); int checkMagic(int square[SIZE][SIZE], int magicValue); int main(void) { int square[SIZE][SIZE]; int row,col; int magicValue; int isMagic = 1; // read potential magic square printf("Enter %d numbers please:\n", SIZE*SIZE); readSquare(square); // print potential magic square printf("Numbers are:\n"); printSquare(square); // Find magic value magicValue = sumFirstRow(square); isMagic = checkMagic(square,magicValue); if(isMagic == 1){ printf("It is magic\n"); } else { printf("It is NOT magic\n"); } return 0; } void readSquare(int square[SIZE][SIZE]){ int row,col; row = 0; while(row < SIZE){ col = 0; while(col < SIZE){ scanf("%d",&square[row][col]); col = col + 1; } row = row + 1; } } void printSquare(int square[SIZE][SIZE]){ int row,col; row = 0; while(row < SIZE){ col = 0; while(col < SIZE){ printf("%d ",square[row][col]); col = col + 1; } printf("\n"); row = row + 1; } } int sumFirstRow(int square[SIZE][SIZE]){ int col; int sum = 0; col = 0; while(col < SIZE){ sum = sum + square[0][col]; col = col + 1; } return sum; } int checkMagic(int square[SIZE][SIZE], int magicValue){ int row,col; int isMagic = 1; int sumRow; //Check all other rows. We have already checked the first. row = 1; while(row < SIZE){ //check the sum of the row col = 0; sumRow = 0; while(col < SIZE){ sumRow = sumRow + square[row][col]; col = col + 1; } if(sumRow != magicValue){ isMagic = 0; } row = row + 1; } return isMagic; }
magic_square.c
including a main function for testing and a few different implementations of checkMagic.
// Read SIZE x SIZE numbers and test if // they form a magic square http://en.wikipedia.org/wiki/Magic_square // // // Andrew Taylor - andrewt@cse.unsw.edu.au // 10/4/13 /* // Lo Shu Square // 4 9 2 // 3 5 7 // 8 1 6 // // Magic square of primes // 17 89 71 // 113 59 5 // 47 29 101 //If you change SIZE to 12 it should work for 1 120 121 48 85 72 73 60 97 24 25 144 142 27 22 99 58 75 70 87 46 123 118 3 11 110 131 38 95 62 83 50 107 14 35 134 136 33 16 105 52 81 64 93 40 129 112 9 8 113 128 41 92 65 80 53 104 17 32 137 138 31 18 103 54 79 66 91 42 127 114 7 5 116 125 44 89 68 77 56 101 20 29 140 139 30 19 102 55 78 67 90 43 126 115 6 12 109 132 37 96 61 84 49 108 13 36 133 135 34 15 106 51 82 63 94 39 130 111 10 2 119 122 47 86 71 74 59 98 23 26 143 141 28 21 100 57 76 69 88 45 124 117 4 */ #include <stdio.h> #define SIZE 3 void readSquare(int square[SIZE][SIZE]); void printSquare(int square[SIZE][SIZE]); int sumFirstRow(int square[SIZE][SIZE]); int checkMagic(int square[SIZE][SIZE], int magicValue); int main(void) { int square[SIZE][SIZE]; int row,col; int magicValue; int isMagic = 1; // read potential magic square printf("Enter %d numbers please:\n", SIZE*SIZE); readSquare(square); // print potential magic square printf("Numbers are:\n"); printSquare(square); // Find magic value magicValue = sumFirstRow(square); isMagic = checkMagic(square,magicValue); if(isMagic == 1){ printf("It is magic\n"); } else { printf("It is NOT magic\n"); } return 0; } void readSquare(int square[SIZE][SIZE]){ int row,col; row = 0; while(row < SIZE){ col = 0; while(col < SIZE){ scanf("%d",&square[row][col]); col = col + 1; } row = row + 1; } } void printSquare(int square[SIZE][SIZE]){ int row,col; row = 0; while(row < SIZE){ col = 0; while(col < SIZE){ printf("%d ",square[row][col]); col = col + 1; } printf("\n"); row = row + 1; } } int sumFirstRow(int square[SIZE][SIZE]){ int col; int sum = 0; col = 0; while(col < SIZE){ sum = sum + square[0][col]; col = col + 1; } return sum; } //This could be broken down into smaller functions //or done with less loops. int checkMagic(int square[SIZE][SIZE], int magicValue){ int row,col,i; int isMagic = 1; int sum; //Check all other rows. We have already checked the first. row = 1; while(row < SIZE){ //check the sum of the row col = 0; sum = 0; while(col < SIZE){ sum = sum + square[row][col]; col = col + 1; } if(sum != magicValue){ isMagic = 0; } row = row + 1; } //Check columns col = 0; while (col < SIZE) { sum = 0; row = 0; while (row < SIZE) { sum = sum + square[row][col]; row = row + 1; } if (sum != magicValue) { isMagic = 0; } col = col + 1; } //Check diagonals sum = 0; i = 0; while ( i < SIZE ) { sum = sum + square[i][i]; i = i + 1; } if (sum != magicValue) { isMagic = 0; } sum = 0; i = 0; while ( i < SIZE ) { sum = sum + square[SIZE-i-1][i]; i = i + 1; } if (sum != magicValue) { isMagic = 0; } return isMagic; }
// This version is broken down into more functions // Read SIZE x SIZE numbers and test if // they form a magic square http://en.wikipedia.org/wiki/Magic_square // // // Andrew Taylor - andrewt@cse.unsw.edu.au // 10/4/13 /* // Lo Shu Square // 4 9 2 // 3 5 7 // 8 1 6 // // Magic square of primes // 17 89 71 // 113 59 5 // 47 29 101 //If you change SIZE to 12 it should work for 1 120 121 48 85 72 73 60 97 24 25 144 142 27 22 99 58 75 70 87 46 123 118 3 11 110 131 38 95 62 83 50 107 14 35 134 136 33 16 105 52 81 64 93 40 129 112 9 8 113 128 41 92 65 80 53 104 17 32 137 138 31 18 103 54 79 66 91 42 127 114 7 5 116 125 44 89 68 77 56 101 20 29 140 139 30 19 102 55 78 67 90 43 126 115 6 12 109 132 37 96 61 84 49 108 13 36 133 135 34 15 106 51 82 63 94 39 130 111 10 2 119 122 47 86 71 74 59 98 23 26 143 141 28 21 100 57 76 69 88 45 124 117 4 */ #include <stdio.h> #define SIZE 3 void readSquare(int square[SIZE][SIZE]); void printSquare(int square[SIZE][SIZE]); int sumFirstRow(int square[SIZE][SIZE]); int checkMagic(int square[SIZE][SIZE], int magicValue); int checkRows(int square[SIZE][SIZE], int magicValue); int checkCols(int square[SIZE][SIZE], int magicValue); int checkDiagonals(int square[SIZE][SIZE], int magicValue); int main(void) { int square[SIZE][SIZE]; int row,col; int magicValue; int isMagic = 1; // read potential magic square printf("Enter %d numbers please:\n", SIZE*SIZE); readSquare(square); // print potential magic square printf("Numbers are:\n"); printSquare(square); // Find magic value magicValue = sumFirstRow(square); isMagic = checkMagic(square,magicValue); if(isMagic == 1){ printf("It is magic\n"); } else { printf("It is NOT magic\n"); } return 0; } void readSquare(int square[SIZE][SIZE]){ int row,col; row = 0; while(row < SIZE){ col = 0; while(col < SIZE){ scanf("%d",&square[row][col]); col = col + 1; } row = row + 1; } } void printSquare(int square[SIZE][SIZE]){ int row,col; row = 0; while(row < SIZE){ col = 0; while(col < SIZE){ printf("%d ",square[row][col]); col = col + 1; } printf("\n"); row = row + 1; } } int sumFirstRow(int square[SIZE][SIZE]){ int col; int sum = 0; col = 0; while(col < SIZE){ sum = sum + square[0][col]; col = col + 1; } return sum; } int checkMagic(int square[SIZE][SIZE], int magicValue){ return checkRows(square,magicValue) && checkCols(square,magicValue) && checkDiagonals(square,magicValue); } int checkRows(int square[SIZE][SIZE], int magicValue){ int row,col; int isMagic = 1; int sum; //Check all other rows. We have already checked the first. row = 1; while(row < SIZE){ //check the sum of the row col = 0; sum = 0; while(col < SIZE){ sum = sum + square[row][col]; col = col + 1; } if(sum != magicValue){ isMagic = 0; } row = row + 1; } return isMagic; } int checkCols(int square[SIZE][SIZE], int magicValue){ int row,col; int sum; int isMagic = 1; col = 0; while (col < SIZE) { sum = 0; row = 0; while (row < SIZE) { sum = sum + square[row][col]; row = row + 1; } if (sum != magicValue) { isMagic = 0; } col = col + 1; } return isMagic; } int checkDiagonals(int square[SIZE][SIZE], int magicValue){ int i; int sum; int isMagic = 1; sum = 0; i = 0; while ( i < SIZE ) { sum = sum + square[i][i]; i = i + 1; } if (sum != magicValue) { isMagic = 0; } //Check other diagonal sum = 0; i = 0; while ( i < SIZE ) { sum = sum + square[SIZE-i-1][i]; i = i + 1; } if (sum != magicValue) { isMagic = 0; } return isMagic; }
// This version restructured to use less while loops but // may be harder for a beginner to read // Read SIZE x SIZE numbers and test if // they form a magic square http://en.wikipedia.org/wiki/Magic_square // // // Andrew Taylor - andrewt@cse.unsw.edu.au // 10/4/13 /* // Lo Shu Square // 4 9 2 // 3 5 7 // 8 1 6 // // Magic square of primes // 17 89 71 // 113 59 5 // 47 29 101 //If you change SIZE to 12 it should work for 1 120 121 48 85 72 73 60 97 24 25 144 142 27 22 99 58 75 70 87 46 123 118 3 11 110 131 38 95 62 83 50 107 14 35 134 136 33 16 105 52 81 64 93 40 129 112 9 8 113 128 41 92 65 80 53 104 17 32 137 138 31 18 103 54 79 66 91 42 127 114 7 5 116 125 44 89 68 77 56 101 20 29 140 139 30 19 102 55 78 67 90 43 126 115 6 12 109 132 37 96 61 84 49 108 13 36 133 135 34 15 106 51 82 63 94 39 130 111 10 2 119 122 47 86 71 74 59 98 23 26 143 141 28 21 100 57 76 69 88 45 124 117 4 */ #include <stdio.h> #define SIZE 3 void readSquare(int square[SIZE][SIZE]); void printSquare(int square[SIZE][SIZE]); int sumFirstRow(int square[SIZE][SIZE]); int checkMagic(int square[SIZE][SIZE], int magicValue); int main(void) { int square[SIZE][SIZE]; int row,col; int magicValue; int isMagic = 1; // read potential magic square printf("Enter %d numbers please:\n", SIZE*SIZE); readSquare(square); // print potential magic square printf("Numbers are:\n"); printSquare(square); // Find magic value magicValue = sumFirstRow(square); isMagic = checkMagic(square,magicValue); if(isMagic == 1){ printf("It is magic\n"); } else { printf("It is NOT magic\n"); } return 0; } void readSquare(int square[SIZE][SIZE]){ int row,col; row = 0; while(row < SIZE){ col = 0; while(col < SIZE){ scanf("%d",&square[row][col]); col = col + 1; } row = row + 1; } } void printSquare(int square[SIZE][SIZE]){ int row,col; row = 0; while(row < SIZE){ col = 0; while(col < SIZE){ printf("%d ",square[row][col]); col = col + 1; } printf("\n"); row = row + 1; } } int sumFirstRow(int square[SIZE][SIZE]){ int col; int sum = 0; col = 0; while(col < SIZE){ sum = sum + square[0][col]; col = col + 1; } return sum; } //This is more efficient but maybe harder to understand int checkMagic(int square[SIZE][SIZE], int magicValue){ int i,j; int sumRow ; int sumCol; int sumDiagonal =0; int sumDiagonal2 = 0; i = 0; while(i < SIZE){ //check the sum of the row j = 0; sumRow = 0; sumCol = 0; while(j < SIZE){ sumRow = sumRow + square[i][j]; sumCol = sumCol + square[j][i]; j = j + 1; } if(sumRow != magicValue || sumCol != magicValue ){ return 0; } sumDiagonal = sumDiagonal + square[i][i]; sumDiagonal2 = sumDiagonal2 + square[i][SIZE-i-1]; i = i + 1; } if(sumDiagonal != magicValue || sumDiagonal2 != magicValue ){ return 0; } return 1; }