아래의 여러가지 소스들은 C 언어용으로 만들어 둔 것들을 Cygwin 환경에서의 Objective-C 언어용으로 수정한 것들이다. 컴파일 벙법과 #import 부분만 수정하였으므로 C 언어용과 거의 마찬가지이다.
콘솔에 삼각형
*
* *
* *
* *
* *
* *
* *
* *
*****************
을 출력하는 Objective-C 컨솔 애플리케이션을 만들어 보자. 이런 소스 코드의 작성은 학원이나 학교에서 프로그래밍 입문자에게 과제로 많이 주어지는 것 중의 하나이다. 코끼리를 보거나 만진 사람들이 저마다 그 생김새를 말할 때 제각기 다르게 표현할 수 있듯이 이런 소스 코드의 작성도 알고 보면 얼마든지 많은 방법이 있을 것이다. 여기서는 쉬운 코드 부터 작성해 보고 차츰차츰 소스를 바꾸어 가면서 Objective-C 프로그래밍의 기초부분을 터득해 보기로 한다.
삼각형 출력 부분을 main() 함수에서 하지 않고, 별도로 구현된 printTriange() 함수에서 하기로 한다.
우선 첫번 째 예제는 C 언어의 컨솔 출력 함수 printf() 의 사용법 만 알면 누구나 코딩할 수 있는 매우 단순한 소스 코드이다.
삼각형 출력 예제 1
/*
* Filename: printTriangle1.m
* Print a triangle on console.
*
* Compile: gcc -o printTriangle1 printTriangle1.m -lobjc
* Execute: ./printTriangle1
*
* Date: 2012/05/01
* Author: PH Kim [ pkim (AT) scripts.pe.kr ]
*/
#import <stdio.h>
void println(const char *s) {
printf("%s\n", s);
}
void print(const char *s) {
printf("%s", s);
}
void printTriange() {
println(" * ");
println(" * * ");
println(" * * ");
println(" * * ");
println(" * * ");
println(" * * ");
println(" * * ");
println(" * * ");
println("*****************");
}
void main(int argc, char *argv) {
printTriange();
}
위의 소스 코드는 아무 알고리즘도 없는 너무 단순한 코드이다. 이런 코드를 작성했다간 출력 모양이나 크기를 변경해야 하는 상황을 맞이하면 위드프로세서로 문서 만드는 것 이상으로 많은 수작업을 하거나 아니면 포기하는 지경에 이를 수도 있다. 그래서 다음 처럼 좀 더 나은 소스 코드를 작성하였다.
삼각형 출력 예제 2
/*
* Filename: printTriangle2.m
* Print a triangle on console.
*
* Compile: gcc -o printTriangle2 printTriangle2.m -lobjc
* Execute: ./printTriangle2
*
* Date: 2012/05/01
* Author: PH Kim [ pkim (AT) scripts.pe.kr ]
*/
#import <stdio.h>
void println(const char *s) {
printf("%s\n", s);
}
void print(const char *s) {
printf("%s", s);
}
void printTriange() {
int i, k;
for (i = 0; i < 8; i++) {
for (k = 0; k < 8 - i; k++) {
print(" ");
}
for (k = 0; k < 2*i + 1; k++) {
if (k == 0 || k == 2*i)
print("*");
else
print(" ");
}
for (k = 0; k < 8 - i; k++) {
print(" ");
}
println("");
}
for (i = 0; i < 17; i++) {
print("*");
}
println("");
}
void main(int argc, char *argv) {
printTriange();
}
위의 소스 코드는 컨솔 출력 함수 메소드 printf() 와 for 구문을 적절히 사용하여 구현되었다. 숫자 몇 곳만 수정하면 출력되는 삼각형의 크기를 바꿀 수 있다. 한 줄에 출력될 문자를 구성하는 알고리즘은 위의 예제와 근본적으로 같지만 char[] 과 char * 타입의 변수를 적절히 사용하여 한 즐씩 출력하는 소스 코드를 다음 예제와 같이 작성해 보았다.
삼각형 출력 예제 3
/*
* Filename: printTriangle3.m
* Print a triangle on console.
*
* Compile: gcc -o printTriangle3 printTriangle3.m -lobjc
* Execute: ./printTriangle3
*
* Date: 2012/05/01
* Author: PH Kim [ pkim (AT) scripts.pe.kr ]
*/
#import <stdio.h>
#import <string.h>
void println(const char *s) {
printf("%s\n", s);
}
void print(const char *s) {
printf("%s", s);
}
void printTriange() {
char line[] = " ";
char line2[] = " ";
char *pline2 = (char *) line2;
int i, k;
for (i = 0; i < 8; i++) {
strcpy(pline2, line);
pline2[8-i] = '*';
pline2[8+i] = '*';
println(line2);
}
strcpy(pline2, line);
for (i = 0; i < 17; i++) {
pline2[i] = '*';
}
println(line2);
}
void main(int argc, char *argv) {
printTriange();
}
별(*) 문자를 이용하여 삼각형을 출력하는 일은 빈칸 문자와 별 문자를 적당한 좌표(위치)에 촐력하는 일이다. 기본 문자열을 빈칸 만으로로 구성된 문자열로 하고, 이 st문자열에 한 두 개의 빈칸을 별(*) 문자로 바꾸어 출력하는 기법으로 작성한 것이 다음 소스 코드이다. 단, 마지막 줄에 츨력될 문자열은 stars라는 별도의 변수로 처리하였다.
삼각형 출력 예제 4
/*
* Filename: printTriangle4.m
* Print a triangle on console.
*
* Compile: gcc -o printTriangle4 printTriangle4.m -lobjc
* Execute: ./printTriangle4
*
* Date: 2012/05/01
* Author: PH Kim [ pkim (AT) scripts.pe.kr ]
*/
#import <stdio.h>
#import <string.h>
void println(const char *s) {
printf("%s\n", s);
}
void print(const char *s) {
printf("%s", s);
}
void printTriange() {
char whites[] = " ";
char stars[] = "*****************";
char line2[] = " ";
int i;
strncpy(line2 + 8, "*", 1);
println(line2);
for (i = 1; i < 8; i++) {
strcpy(line2, whites);
strncpy(line2 + 8 - i, "*", 1);
strncpy(line2 + 8 + i, "*", 1);
println(line2);
}
println(stars);
}
void main(int argc, char *argv) {
printTriange();
}
빈칸 문자를 별(*) 문자로 바꾸기 위해, 위의 소스 코드에서는 strcpy() 함수를 이용하였지만, 다음 소스 코드에서는 str[인덱스] = 문자 의 구문을 이용하였다.
삼각형 출력 예제 5
/*
* Filename: printTriangle5.m
* Print a triangle on console.
*
* Compile: gcc -o printTriangle5 printTriangle5.m -lobjc
* Execute: ./printTriangle5
*
* Date: 2012/05/01
* Author: PH Kim [ pkim (AT) scripts.pe.kr ]
*/
#import <stdio.h>
#import <string.h>
void println(const char *s) {
printf("%s\n", s);
}
void print(const char *s) {
printf("%s", s);
}
void printTriange() {
char whites[] = " ";
char stars[] = "*****************";
char line[] = " ";
int i;
int start = 8;
line[start] = '*';
println(line);
for (i = 1; i < 8; i++) {
strcpy(line, whites);
line[start - i] = '*';
line[start + i] = '*';
println(line);
}
println(stars);
}
void main(int argc, char *argv) {
printTriange();
}
출력되는 삼각형이 좌우 대칭이라는 사실에 착안하여, 다음 소스 코드에서는 각 줄을 처음 8자, 중앙 한 문자, 끝 8자(처음 8자의 역순)로 string을 만들어 출력하였다.
삼각형 출력 예제 6
/*
* Filename: printTriangle6.m
* Print a triangle on console.
*
* Compile: gcc -v -o printTriangle5 printTriangle5.m -lobjc
* Execute: ./printTriangle6
*
* Date: 2012/05/01
* Author: PH Kim [ pkim (AT) scripts.pe.kr ]
*/
// #import <Foundation/Foundation.h> // for usual Linux system with GNUStep installed
#import <Objc/Object.h> // for Cygwin system with GNUStep npninstalled
#import <stdio.h>
#import <string.h>
#import <memory.h>
void println(const char *s) {
printf("%s\n", s);
}
void print(const char *s) {
printf("%s", s);
}
void reverse(char *s) {
int n = strlen(s);
int i;
char c;
for (i = 0; i < n/2; i++) {
c = s[n - i - 1];
s[n - i - 1] = s[i];
s[i] = c;
}
}
void printTriange() {
char whites[] = " ";
char stars[] = "********";
char *pline = NULL;
int i;
int start = 8;
pline = (char *) calloc(sizeof(char), 17 + 1);
if (pline != NULL) {
print(whites);
print("*");
println(whites);
for (i = 1; i < 8; i++) {
strcpy(pline, whites);
pline[start - i] = '*';
print(pline);
print(" ");
reverse(pline);
println(pline);
}
print(stars);
print("*");
println(stars);
free(pline);
}
}
void main(int argc, char *argv) {
printTriange();
}
다음 소스 코드는 한 줄에 출력될 문자열의 데이터를 17비트 이진법 수로 구성하고, 이 이진법수의 비트가 0인 곳에는 빈칸을, 1인 곳에는 별(*)을 출력하는 기법으로 작성되었다.
삼각형 출력 예제 7
/*
* Filename: printTriangle7.m
* Print a triangle on console.
*
* Compile: gcc -v -o printTriangle7 printTriangle7.m -lobjc
* Execute: ./printTriangle7
*
* Date: 2012/05/01
* Author: PH Kim [ pkim (AT) scripts.pe.kr ]
*/
// #import <Foundation/Foundation.h> // for usual Linux system with GNUStep installed
#import <Objc/Object.h> // for Cygwin system with GNUStep npninstalled
#import <stdio.h>
#import <string.h>
#import <memory.h>
void println(const char *s) {
printf("%s\n", s);
}
void print(const char *s) {
printf("%s", s);
}
#define MAX_BUF 81
enum { FALSE, TRUE };
char BASE36[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
void convertItoA(char *pstr, long num, int radix) {
char tmp[2];
char ret[MAX_BUF];
char arr[MAX_BUF];
long q, r;
int i, n;
int isNegative = FALSE;
if (num < 0L) {
isNegative = TRUE;
num = -num;
}
arr[0] = '\0';
q = num;
r = 0L;
while (q >= (long) radix) {
r = q % (long) radix;
q = q / (long) radix;
tmp[0] = BASE36[r];
tmp[1] = '\0';
strcat(arr, tmp);
}
tmp[0] = BASE36[q];
tmp[1] = '\0';
strcat(arr, tmp);
if (isNegative) {
strcat(arr, "-");
}
n = strlen(arr);
for (i = 0; i < n; i++) {
ret[i] = arr[n - i - 1];
}
ret[n] = '\0';
strcpy(pstr, (char *) ret);
}
long convertAtoI(const char *pstr, int radix) {
char tmp[2];
long ret = 0L;
char arr[MAX_BUF];
long q, r;
int isNegative = FALSE;
int len = strlen(pstr);
char c;
int i;
long val;
c = pstr[0];
if (c == '-') {
isNegative = TRUE;
}
else if (c >= '0' && c <= '9') {
ret = (long) (c - '0');
}
else if (c >= 'A' && c <= 'Z') {
ret = (long) (c - 'A') + 10L;
}
else if (c >= 'a' && c <= 'z') {
ret = (long) (c - 'a') + 10L;
}
if (ret >= (long) radix) {
println(" Invalid character!");
return ret;
}
for (i = 1; i < len; i++) {
c = pstr[i];
ret *= radix;
if (c >= '0' && c <= '9') {
val = (long) (c - '0');
}
else if (c >= 'A' && c <= 'Z') {
val = (long) (c - 'A') + 10L;
}
else if (c >= 'a' && c <= 'z') {
val = (long) (c - 'a') + 10L;
}
if (val >= (long) radix) {
println(" Invalid character!");
return ret;
}
ret += val;
}
return ret;
}
void printTriange() {
int start = 0x100;
int total = 0;
int val = start;
char data[18];
int i, k;
for (k = 0; k < 8; k++) {
val = (start << k) | (start >> k);
convertItoA(data, val, 2);
for (i = 0; i < 17 - strlen(data); i++) {
print(" ");
}
for (i = 0; i < strlen(data); i++) {
if (data[i] == '0')
print(" ");
else
print("*");
}
println("");
total |= val;
}
val = (start << 8) | (start >> 8);
total |= val;
convertItoA(data, total, 2);
for (i = 0; i < 17 - strlen(data); i++) {
print(" ");
}
for (i = 0; i < strlen(data); i++) {
if (data[i] == '0')
print(" ");
else
print("*");
}
println("");
}
void main(int argc, char *argv) {
printTriange();
}
기본적인 원리는 위의 소스 코드와 같지만 이진법수의 한 비트 마다 한 문자씩 츨력하는 대신에 출력된 한 줄의 문자열을 완성하여 이를 printf() 로 출력하는 기법으로 재작성한 것이 다음의 소스 코드이다. 자체 구현된 replaceAll() 함수를 이용하여, 모든 0을 빈칸으로, 모든 1을 별(*) 문자로 바꾸었으며, 별(*) 문자만으로 이루어진 마지막 줄 출력을 위해 변수 total을 준비하였다. for 반복 구문의 블럭 내에서 구문
total |= val;
이 하는 일이 무엇인지 이해할 수 있으면 좋다.
삼각형 출력 예제 8
/*
* Filename: printTriangle8.m
* Print a triangle on console.
*
* Compile: gcc -v -o printTriangle8 printTriangle8.m -lobjc
* Execute: ./printTriangle8
*
* Date: 2012/05/01
* Author: PH Kim [ pkim (AT) scripts.pe.kr ]
*/
// #import <Foundation/Foundation.h> // for usual Linux system with GNUStep installed
#import <Objc/Object.h> // for Cygwin system with GNUStep npninstalled
#import <stdio.h>
#import <string.h>
#import <memory.h>
void println(const char *s) {
printf("%s\n", s);
}
void print(const char *s) {
printf("%s", s);
}
#define MAX_BUF 81
enum { FALSE, TRUE };
char BASE36[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
void convertItoA(char *pstr, long num, int radix) {
char tmp[2];
char ret[MAX_BUF];
char arr[MAX_BUF];
long q, r;
int i, n;
int isNegative = FALSE;
if (num < 0L) {
isNegative = TRUE;
num = -num;
}
arr[0] = '\0';
q = num;
r = 0L;
while (q >= (long) radix) {
r = q % (long) radix;
q = q / (long) radix;
tmp[0] = BASE36[r];
tmp[1] = '\0';
strcat(arr, tmp);
}
tmp[0] = BASE36[q];
tmp[1] = '\0';
strcat(arr, tmp);
if (isNegative) {
strcat(arr, "-");
}
n = strlen(arr);
for (i = 0; i < n; i++) {
ret[i] = arr[n - i - 1];
}
ret[n] = '\0';
strcpy(pstr, (char *) ret);
}
long convertAtoI(const char *pstr, int radix) {
char tmp[2];
long ret = 0L;
char arr[MAX_BUF];
long q, r;
int isNegative = FALSE;
int len = strlen(pstr);
char c;
int i;
long val;
c = pstr[0];
if (c == '-') {
isNegative = TRUE;
}
else if (c >= '0' && c <= '9') {
ret = (long) (c - '0');
}
else if (c >= 'A' && c <= 'Z') {
ret = (long) (c - 'A') + 10L;
}
else if (c >= 'a' && c <= 'z') {
ret = (long) (c - 'a') + 10L;
}
if (ret >= (long) radix) {
println(" Invalid character!");
return ret;
}
for (i = 1; i < len; i++) {
c = pstr[i];
ret *= radix;
if (c >= '0' && c <= '9') {
val = (long) (c - '0');
}
else if (c >= 'A' && c <= 'Z') {
val = (long) (c - 'A') + 10L;
}
else if (c >= 'a' && c <= 'z') {
val = (long) (c - 'a') + 10L;
}
if (val >= (long) radix) {
println(" Invalid character!");
return ret;
}
ret += val;
}
return ret;
}
void replaceAll(char *str, char s, char t) {
int i;
for (i = 0; i < strlen(str); i++) {
if (str[i] == s)
str[i] = t;
}
}
void printTriange() {
char zeros[] = "00000000";
int start = 0x100;
int total = 0;
int val = start;
char data[17 + 1];
char line[MAX_BUF];
int i, k;
for (k = 0; k < 8; k++) {
val = (start << k) | (start >> k);
convertItoA(data, val, 2);
strncpy(line, zeros, 17 - strlen(data));
line[17 - strlen(data)] = '\0';
strcat(line, data);
replaceAll(line, '0', ' ');
replaceAll(line, '1', '*');
println(line);
total |= val;
}
val = (start << 8) | (start >> 8);
total |= val;
convertItoA(line, total, 2);
replaceAll(line, '0', ' ');
replaceAll(line, '1', '*');
println(line);
}
void main(int argc, char *argv) {
printTriange();
}
심각형의 좌우 대칭성과 chat[] 타입의 자료를 이용하여 한 줄씩 출력하는 기법이다.
별(*) 문자만으로 이루어진 마지막 줄 출력을 위해 변수 last를 준비하였다.
삼각형 출력 예제 9
/*
* Filename: printTriangle9.m
* Print a triangle on console.
*
* Compile: gcc -v -o printTriangle9 printTriangle9.m -lobjc
* Execute: ./printTriangle9
*
* Date: 2012/05/01
* Author: PH Kim [ pkim (AT) scripts.pe.kr ]
*/
// #import <Foundation/Foundation.h> // for usual Linux system with GNUStep installed
#import <Objc/Object.h> // for Cygwin system with GNUStep npninstalled
#import <stdio.h>
#import <string.h>
#import <memory.h>
void println(const char *s) {
printf("%s\n", s);
}
void print(const char *s) {
printf("%s", s);
}
#define WIDTH 17
void printTriange() {
int start = 8;
char data[WIDTH];
char last[WIDTH];
int i, k;
for (k = 0; k < WIDTH; k++) {
data[k] = ' ';
last[k] = ' ';
}
data[start] = '*';
last[start] = '*';
for (i = 0; i < WIDTH; i++) {
printf("%c", data[i]);
}
println("");
data[start] = ' ';
for (k = 1; k < WIDTH/2; k++) {
data[start - k] = '*';
last[start - k] = '*';
data[start + k] = '*';
last[start + k] = '*';
for (i = 0; i < WIDTH; i++) {
printf("%c", data[i]);
}
println("");
data[start - k] = ' ';
data[start + k] = ' ';
}
last[start - WIDTH/2] = '*';
last[start + WIDTH/2] = '*';
for (i = 0; i < WIDTH; i++) {
printf("%c", last[i]);
}
println("");
}
void main(int argc, char *argv) {
printTriange();
}
다음 예제는 수학에서 xy-좌표평면에 점을 찍듯이 논리 구문
(x + y - 8 == 0) || (y - x + 8 == 0) || (y - 8 == 0)
가 참이 되는 위치에 별(*) 문자를 표시하는 기법으로 작성된 소스 코드이다.
삼각형 출력 예제 10
/*
* Filename: printTriangle10.m
* Print a triangle on console.
*
* Compile: gcc -o printTriangle10 printTriangle10.m -lobjc
* Execute: ./printTriangle10
*
* Date: 2012/05/01
* Author: PH Kim [ pkim (AT) scripts.pe.kr ]
*/
#import <stdio.h>
void println(const char *s) {
printf("%s\n", s);
}
void print(const char *s) {
printf("%s", s);
}
#define WIDTH 17
void printTriange() {
char a;
int x, y;
for (y = 0; y <= 8; y++) {
for (x = 0; x <= 16; x++) {
if ((x + y - 8 == 0) || (y - x + 8 == 0) || (y - 8 == 0))
a = '*';
else
a = ' ';
printf("%c", a);
}
println("");
}
}
void main(int argc, char *argv) {
printTriange();
}