아래의 여러가지 소스들은 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();
}



Posted by Scripter

댓글을 달아 주세요