달력

52024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

달팽이 배열과 주소 연산

문제: 달팽이 배열을 만들어서 출력하는 프로그램을 짜라.

 

 

여러 가지 방식이 있겠으나, 본인은 '배열을 1차원화 하여 그 주소를 2차원 배열처럼 접근'해서 풀었습니다.

얼핏보면 1차원 배열을 출력만 2차원 스럽게 한 것이 아니냐는 오해를 받을 수도 있는데,

아닙니다. 1차원 배열이든 2차원 배열이든 똑같이 연속된 주소값입니다.

따라서 본인이 만든 배열의 주소포인터로 2차원 배열로 선언하면 그 것이 곧 2차원 배열인 것이다.

(궤변이라고 생각하면 추천을 눌러라!)

 

 

우선 아래 코드를 보면..

본인은 1차원 배열을 할당하였다.

중요한 건. Scanf로 입력받는 달팽이 크기 length에 따라..

훗날 (in the future! 하나 알았다고 계속 써먹는구나!)…

즉, go up이나 go down 시에 1차원 내에서 이동하는 칸 수가 정해진다 (즉, length 만큼 이동한다).

변수 goright는 오른쪽으로 이동하려고 대기탈 때..이동하는 동선에 포함된 총 원소 개수다.

따라서…7*7배열에서..

1차 오른쪽 이동 동선에는 7개의 원소(0번지~6번지)가 있고,

2차 오른쪽 이동 동선에는 6개의 원소 (7번지~12번지)가 있다.

이 때 왜 13번지가 빠지냐 하면..1차 오른쪽 이동후, 1차 하향이동(코드 주석에 'go down'이라는 부분)하면서…

6번지+7->13번지에 값이 쓰여졌기 때문이다…아래 코드를 보면..

 

 

 

그래서 2차 오른 쪽 이동시에는 goright--로 인해 이동 동선의 원소의 개수 (즉, 값을 채워넣는 행위 횟수)가 1 줄어든다.

그렇다면 오른쪽 이동이 1차인지, 2차인지는 어떻게 판별할까?

바로 if(Dircnt>5)이다. 이 Dircnt라는 변수가 각 방향 이동시에 ++ 되어, 지금이 몇 차례 이동인지가 판별된다.

허나 오른쪽 이동외에는, 나머지 방향 (go down, go left, go up) 이동은..2차 시에 전부 2씩 줄어든다.

(아래 코드 참조)

 

 

그래서 각 방향의 이동코드에 첫 부분에.. godown=godown-2; 와 같은 식을 적는 것이당. 당당당!

 

 

아래 go up 부분도 마찬가지다.

뭐 go right 부분만 알면 나머지 세 개는 거의 똑같다.

첫 부분의 if문에서..goto labelA 요거는… goup의 원소갯수가 1일 때.

즉, 위로 올라갈려는데, 자기 말고는 더 이상 올라갈려는 게 없을 때를 말한다.

이 때는 모든 대입이 끝난 상태이므로, 출력 레이블로 탈출한다.

 

 

아래 출력레이블은 일반적인 출력용 반복문이다.

단지 특이사항이라고 하면, 주소 접근이다.

 

 

이상으로 달팽이 배열과 주소 연산에 대한 문제를 풀어보았습니다.

추천 눌러주시고~ 좋은 하루 보내세요~~~

Posted by C언어 보이
|

반복문을 사용하여 이차원 배열의 값을 회전시키는 문제 입니다.

문제 : 4*4배열을 선언하여 아래처럼 값을 회전시켜라.

 

 

위 배열을 icount[4][4]로 하여 값을 대입합니다.

밑에 newcount[4][4] 배열은 훗날 (int the future!ㅋ), icount를 회전시킨 값을 넣습니다.

그리고 그 아래 메인에서 반복문이 2개가 보이네요…

첫 번 째 반복문은 icout 배열의 초기상태를 출력하는 용도입니다.

그 아래 반복문은, 회전시킬지 말지를 입력받는 것입니다.

즉, change함수를 부르는 조건입니다.

 

 

인제 문제의 핵심인 change 함수를 보기로 할까요?

말까요?

봅시다! change함수는 한 번 호출될 때 마다 icount 배열의 값이 90도씩 회전하여 대입시키는 데요.

그 구조를 크게 요약하면..icount[i][j]값을 icount[i][j]에 입력하는 것이 아닙니다. 그렇게 되면...값이 덮어써져 버려요.

그래서 그와 같은 icount 배열은 쓰는 용도, newcount 배열은 값을 불러오는 용도가 되는 것이죵. 그럼 더 자세히 봅시다..

우선 위의 첫번 째 반복문..그 안에 있는 반복문 실행식이 핵찜! 입니다.

Icount[j][3-i]. 요 식을 자알~생각해 보세요. 긴 설명은 의미가 없을 것 같네요.

 

그 아래 반복문은 출력 및, newcount 업데이트용 반복문 입니다.

업데이트용? 다음 번 change함수 실행(윗 반복문)에서 값의 대입을 위한 것 입니다.

 

이상으로 배열값의 이동 : 반복문, 이차원 배열에 대하여 알아보았습니다.

추천, 링크 많이 많이 눌러주세요~ㅋ

Posted by C언어 보이
|

배열과 포인터의 다양한 형태와 활용에 대하여 공부하였습니다.

-----------[순서]--------------

[1] 배열

1. 삼차원 배열의 개념

2. 다차원 (이차원) 배열의 활용문제

   

[2] 포인터

1. 다차원 포인터의 개념과 활용

(1) 개념

(2) 활용

2. 다차원 배열과 포인터의 관계

(1) 개념

(2) 포인터 배열 'int * pnum[2]'와 배열 포인터'int(*parr)[2]'

----------------------------------

   

   

[1] 배열

1. 삼차원 배열의 개념

예시로 설명하겠습니다.

-      1차원 배열의 예: 학생의 국, 영, 수 성적을 1차원 배열로 저장하라.

   

   

   

각 각의 번지는 국, 영, 수 순서입니다.

   

-      2차원 배열 : 출석번호 1, 2, 3번 학생들의 국, 영, 수 성적을 2차원 배열로 저장하라.

위 1차원 배열의 구조가 그대로 들어가 있습니다. 다만, 1차원 배열이 원소가 된다는 점만 다릅니다. 참고로 5행, 6행, 7행의 실행결과는 동일합니다. 편한데로 쓰면 되겠습니다.

   

   

 -      3차원 배열: a반과 b반의 출석번호 1, 2, 3번 학생의 국, 영, 수 성적을 입력하라

   

   

'1차원->2차원 배열'과 '2->3차원 배열'은 동일한 관계를 가집니다. 즉, 3차원 배열은 2차원 배열을 원소로 가진다. 소대->중대->연대의 개념이라고 하면 될까요?

이렇듯 배열, 특히 다차원 배열은 자료입력을 하는 데에 용이합니다. 특히, 각종 명부, 신체 사이즈 등 정보의 종류와 구조가 특정되어 있는 경우에 유용합니다.

   

   

2. 다차원 (이차원) 배열의 활용문제

아래는, 이차원 배열의 활용에 관해 3문제 중 한 문제입니다.

학생들의 시험성적을 관리하는 프로그램입니다. 입력된 시험성적을 총점 구하기, 평균 구하기 등에 사용할 수 있습니다.

(상세한 설명은 제 블로그 'http://inocenttome.tistory.com/entry/20140331-03-이차원-배열의-활용-문제-3-성적관리-프로그램' 에 있습니다)

   

   

   

특징.

1.     입력과 출력을 같은 반복문을 쓰지 않고 나누어 코딩하였습니다. 수정과 디버깅의 용이함 때문으로 보이지만 사실 실력이 모잘랐..;

2.     그리고 숫자 외의 정보표현을 위해 name이라는 문자열 배열을 만든 것입니다. 각 각의 반복문에 분기문을 지저분하게 첨가할 수도 있었으나, 가능한 문자정보의 출력을 자동화하고자 노력하였습니다.

   

가벼운 마음으로 코드를 함 슥 보면… Score[i-5] 이 부분은 원래 score[i] 였습니다. 원래 의도한 바가 있어서 [i-5]형태로 쓴 건데, 코딩하다가 그 용도가 없어졌습니다. 이렇듯, 처음 변수를 정의할 때에도 전체 코드에서의 쓰임을 고려하여야 하며, 이를 간과하고 변수를 정의하면 후에 변수의 사용형태가 아래처럼 복잡해 집니다 (타산지석).

   

   

   

아래는 출력용 반복문입니다. 메인은 두 반복문 중에 아래 쪽 반복문입니다.

이중 반복문인데, 살펴보면 안쪽 반복문을 수행하기 전에 (즉, 철수의 각 과목 성적을 출력하기 전에), 사람의 이름이 찍혀야 합니다.

   

   

   

[2] 포인터

1. 다차원 포인터의 개념과 활용

(1) 개념 : 포인터의 포인터를 더블포인터라고 하며, 더블포인터를 가리키는 삼중포인터, 이 삼중포인터를 가리키는 사중포인터 등을 모두 합해 다차원 포인터 라고 합니다. '*'을 100개 까지 붙히면 백중 포인터도 만들 수 있으나 다차원 포인터는 잘 쓰이지 않으며 그나마 쓰이는 것이 더블 포인터 입니다.

(2) 더블 포인터의 활용 :

함수 내의 static 변수 접근을 위해 주로 사용됩니다. 아래 코드식으로 적어보면.. 

---------------[코드시작]----

main

{

int num=100;

int * pnum=&a;

int **ppnum=&pnum;

func(ppnum);

 }

   

void func(int** ppnum)

{

static snum=10;

*ppnum=&snum;  //ppnum이 &pnum이므로, *ppnum은 pnum이다.

                       //즉, 더블포인터로 메인의 싱글 포인터를 접근할 수 있게 된다.

                       //이 pnum에 &snum을 넣게 된다.

}

   

---------------[코드 끝]----

   

   

2. 다차원 배열과 포인터의 관계 

: 예제와 개념이 교재에서 충실히 설명되므로, 제가 이해한 표현으로 적겠습니다. 참고 바랍니다.

(1) 개념

2차원 배열의 이름이 곧 더블 포인터는 아닙니다.

   

크게 두 가지 이유가 있습니다.

1) 첫 번째로 배열명은 포인터와 달리 그 값이 여러 가지를 의미합니다.

포인터는 쉽게 말해 '아래 혹은 위로 타고 들어가는 것'이나 배열명은..

가령, 이차원 배열 'inum[2][2]'의 배열이름 inum은,

'배열 전체의 시작주소'이기도 하며,

'0번째 행의 시작주소inum[0]'이기도 하며,

'0번째 행의 0번째 원소 주소inum[0][0]'이기도 하기 때문입니다.   

   

 2) 두 번째로, 연산 (증가, 감소)의 형태가 다릅니다.

배열명 inum에 +n을 하면 '배열의 전체길이*배열자료형의 크기*n'만큼 주소 값이 건너뜁니다.

하지만 배열명 inum을 가리키는 'int형 싱글 포인터 pinum'(int*pinum=inum)에 +n을 하면 이는 '자료형의 크기*n'만큼 주소 값이 증가할 뿐입니다. 그렇다고 'int형 더블 포인터 ppnum'에 +n을 하여도 마찬가지 크기만큼 증가합니다. 즉, 포인터의 연산은 '자신의 선언형태'에 따라가는 것이지, 가리키는 대상(배열명)에 따라 달라지는 것이 아닙니다. 그럼 포인터의 연산을 배열명과 동일하게 하려면 어떻게 해야 할까요?

따라서 이차원 배열을 가리키는 포인터로 '포인터 배열'이라는 것이 필요해집니다. 아래를 참고.

   

   

(2) 포인터 배열 'int * pnum[2]'와 배열 포인터'int(*parr)[2]'

1) 포인터 배열: 이미 알고 있듯이 배열을 선언할 때에 배열의 자료형을 명시해 주어야 합니다. 가령 '정수형의 배열'은 int num[2] 처럼 말입니다. 즉, '자료형int+배열명+인자의 개수[2]'.

그럼 '정수형 포인터의 배열'의 선언방식은? 똑 같습니다. 즉,  '자료형int*+배열명pnum+인자의 개수[2]' 입니다.

   

2) 배열 포인터: 이미 알고 있듯이 포인터를 선언할 때에 포인터의 자료형을 명시해 주어야 합니다. 가령 '정수형의 포인터'는 int* pnum 처럼 말입니다. 즉, '자료형int+포인터표시*+포인터명pnum'.

그럼 '정수형 배열 포인터'의 선언방식은? 똑 같나요? 예 거의.

즉, '자료형+포인터표시+포인터명'의 위 방식 마지막에...배열 인자의 개수만 더해주면 됩니다. 즉, '자료형int+(포인터표시*+포인터명pnum)+배열인자의 개수[2]' 입니다.

 

잘 보셨으면 손가락을 꾸욱 눌러주세요~~

링크도 많이 많이 해 주세요 ㅎㅎ

   

Posted by C언어 보이
|

이차원 배열의 활용 마지막 문제이다.

자료입력에 적합한 배열의 특성에 맞게 성적관리 프로그램을 짜는 문제이다.

 

문제. 학생 4명 각 각의 4 과목 점수를 입력받고, 과목별 총점, 학생별 총점, 총합 까지 저장되게 하자.

즉, 5*5 배열을 만들어 값을 저장한 후, 출력하라.

 

특징.

  1. 본인은 입력과 출력을 같은 반복문을 쓰지 않고 나누어 코딩하였다. 수정과 디버깅의 용이함 때문으로 보이지만 사실 실력이 모잘랐 ㅠ;;
  2. 그리고 숫자 외의 정보표현을 위해 name이라는 문자열 배열을 만든 것이다. 각 각의 반복문에 분기문을 지저분하게 첨가할 수도 있었으나, 가능한 문자정보의 출력을 자동화하고자 노력하였다. 말이 엄청 거창하게 들리는데, 먼말인지 알거다;;

    일단 가벼운 마음으로 코드를 함 슥 보자. Score[i-5] 이 부분은 원래 score[i] 였다. 원래 의도한 바가 있어서 [i-5]형태로 쓴 건데, 코딩하다가 그 용도가 없어졌다. 그래도 있어 보이므로 그대로 남겨두었다.

 

 

우선 아래 입력용 반복문부터 보자.

기본적으로 행4회, 열4회로 4*4 반복을 하고 있다. 당연하다 4*4 회 입력하고, 나머지 총점들은 알아서 더해지니깐.

변수 때문에 복잡해 보이지만, 기본적으로 [학생0][과목0]~[학생4][과목4] 까지 입력을 받는 코드이다. 다만 각 행의 모든 입력값을 마지막행에 누적해 주자. 또, 바깥 쪽 포문이 1회 돌 때 (즉, 행이 바뀔 때 혹은 즉 i가 ++할 때)에..마지막 원소의 값 (즉 과목별 총점)을 score[4][4]에 더해주면 총점 반영이 된다.

입력용 반복문의 핵심은, 각 원소에 입력된 데이터가 적합한 원소에 적합하게 합산 되는 지가 중요하다.

 

 

참고적으로 아래 코드에서 (i-5)를 그냥 i로 고치고 초기값도 5가 아닌 0을 넣자.

사람이름 배열에 접근하기 위한 변수를 i로 공통으로 썼는데, 역시나 코드가 보기 어려워 졌다.

 

 

그 다음 아래의 출력용 코드를 보자. 메인은 두 반복문 중에 아래 쪽 반복문이다.

이중 반복문인데, 살펴보면 안쪽 반복문을 수행하기 전에 (즉, 철수의 각 과목 성적을 출력하기 전에), 사람의 이름이 찍혀야 한다. 그래서 첫 줄에 프린트문으로 현재 사람이름(철수)을 찍고 들어가는 것이다.

그 외에는 일반적인 형태의 출력용 반복문이다.

 

그리고 윗 부분의 반복문은 과목명 배열을 접근하여 출력하기 위한 코드이다.

즉, 우리의 5*5 성적 배열을 출력하기 전에, 첫 줄에 각 과목명을 찍어 놓는 것이다.

 

이상으로, 이차원 배열의 활용 문제 3 성적관리 프로그램을 만들어 보았다.

잘 보았다 싶으시면 손가락을 꾸욱 눌러주세요 ㅋㅋ

Posted by C언어 보이
|

이차원 배열의 활용 문제 1 구구단 저장 문제이다.

3*9배열에 아래처럼 저장, 출력하라.

 

 

행렬의 위치를 그대로 대입하면 된다.

다만, 2단을 나타내는 행은 [0], 3단에 대해서는 [1]이 된다. 즉, 행의 원소번호에 +2을 해줘야 한다.

마찬가지 원리로 열의 원소번호에는 +1을 해주어야 한다.

그래야만 3*2는, 3(1행+2)*2(1행+1)이 되기 때문이다.

 

이상으로 이차원 배열의 활용 문제 1 구구단 저장 문제를 풀어보았다.

잘 보았다 싶으시면 손가락을 꾸욱 눌러주세요 ㅋㅋ

Posted by C언어 보이
|

이차원 배열은 대입과 관련하여 다양한 알고리즘을 만들 수 있다.

(대표적으로 그래픽 분야에서 응용이 많이 된다. 그림의 화소정보를 각 각의 배열 원소로 넣을 수 있다.)

우선 문제를 보자.

문제 : 2행 4열의 A배열은..{{1,2,3,4},{5,6,7,8}} 처럼 되어 있다.

이를 4*2 배열의 A배열에 아래와 같이 값이 대입되도락 하라.

 

풀이: 핵심은 규칙성을 발견하는 것이다.

잘 보면, A배열의 행과 B배열의 열이 동일하게 값이 변하는 것을 알 수 있다.

(참고로 수학의 '등차수열' 이다.)

그럼 b배열은 a배열과 행과 열을 반대로 적으면 된다.

즉, a배열의 i행 j열의 값을 b 배열의 j행 i열에 넣으면 된다.

참고로 이 방식은 영상처리에서 '화면 좌우반전, 회전' 등의 분야에 그대로 응용할 수 있다.

 

이상으로 이차원 배열의 활용 문제를 풀어보았다.

잘 보았다 싶으시면 손가락을 꾸욱 눌러주세요 ㅋㅋ

 

Posted by C언어 보이
|

문제 : 길이 10인 배열을 선언, 숫자 입력하게 하여 아래처럼 나오게 하라.

 

풀이 : 함수의 인자로서 포인터 사용법, 배열과 포인터의 주소 접근법을 알면 풀 수 있다.

함수호출 및 종료조건도 잘 적어야 한다.

아래 메인에서는 배열입력 및 함수호출, 메뉴 종료조건을 다루고 있다.

 

 

아래 코드는 메인 함수 아래에 있는 짝수출력, 홀수출력 함수이다. 기본적으로 두 함수의 구조는 동일하다. 유일한 차이점은 호출대상이 짝수이냐, 홀수이냐며 코드상에서 숫자%2의 값이 0이냐 1이냐의 차이만 있다. 그러므로 둘 중 하나의 함수만 이해하면 된다. 홀수출력 함수만 살펴보겠다.

핵심은 배열의 각 원소에 접근하여 그 값이 조건식 (숫자%2==1)을 만족할 때에만 출력하게 하면 된다.

다만 동일한 조건식을 두 개 쓴 이유는 쉼표의 출력 때문이다.

 

 

이상으로 배열의 홀수출력, 짝수출력, 주소 포인터에 대해 알아보았다.

Posted by C언어 보이
|

Apple,banana,tomato라는 문자열들의 각 글자를 caStr에 넣어 출력을 하는 것이다.

아래 코드에서는 일일이 수동대입을 하고 있다. 개 노가다다ㅜㅜ

성실함은 인생을 불행하게 함으로. 아래 노가다 코드를 반복문으로 바꾸어 보자.

 

 

간단히 요약하면, '과일이름'이라는 문자열의 주소를 배열로 만들었다. 즉, 포인터 배열을 활용하였다.

* 포인터 배열을 쓰지 않고 하는 것이 훨씬 쉽다. 다만, 나름데로의 장점 (과일의 개수변동, 과일명칭 길이 변동 등에 대한 코드 수정이 용이)이 있어 이와 같이 하였다. 님이 초심자이거나 코드가 더러워서 어렵게 보인다면…apple문자 넣는 반복문, banana용 반복문, tomato용 반복문 등을 따로 따로 만들기를 강추!!!!! 하는 바이다. 그리고 fruit[]같은 과일 배열 (과일이름이 원소. 즉, 포인터 배열)을 안 써도 된다.).

다시 말하지만, 아래 코드는 해석하기 어려우므로 임산부나 초심자는 이쯤에서 포기해라 (이리 말해주면 승부욕 발동될 걸 잘 안다 ㅋ).

 

상세한 풀이는 아래와 같다.

  1. 특징 : Fruit[]이라는 배열에 과일명칭 문자열의 주소(cpApple,cpBanana,cpTomato)를 원소로 삽입한다.

    향후 과일이 추가될 때에는, 이 배열의 원소만 추가시키면 된다.

  2. 기본설명 : fruit[1]+fruitcharnum(0)은 "apple"의 'a'의 주소. fruit[1]+fruitcharnum(1) 은 "apple"의 'p'의 주소이다.
  3. 변수사용

    Straddrnow: 아래 반복문에서 casstr[]배열에 원소를 지정하기 위해서이다.castr[straddrnow]='글자' 식으로 쓴다.

    Fruitnow: 아래 반복문에서 caStr에 대입할 과일을 지정하는 수이다. Fruitnowp=fruit[fruitnowp]+fruitcharnum;

                                 castr[straddrnow]=*fuitnowp; 식으로 쓴다.

    Fruitnum : 과일의 개수. fruit[]배열의 길이가 자동으로 구해진다.

 

  1. 반복문
    1. if실행식 (문자대입식) : 맨 처음 fruitnow=0, fruitcharnow=0이다. 따라서, 'Fruitnowp=fruit[fruitnow]+fruitcharnum'에서 fruit[fruitnowp]가 fruit[1]의 된다. Fruit[1]은 "banana"의 주소(즉,'b'의 주소)이므로, if문 안에서 castr[0]에는 *(fruit[1]의 주소="banana"의 주소='b'의 주소)가 들어간다.
    2. 문자대입 조건 : if문은 ' *fruitnowp가 null 아닐 때'를 조건으로 한다. apple에서 e뒤에는 null 들이 있다. 따라서 e를 넣고 난 후에 다음 반복문 수행시에는 e다음의 널이 와서, else문을 수행하게 된다.
    3. Else 실행식 (대상과일 변경, 초기화): e다음에 널이 왔다는 것은 과일이름 하나를 다 넣었다는 것이다. 따라서 다음 과일로 넘어가기 위해 fuitnow++해주고 fruitcharnum=0을 해준다. 그러면, 반복문을 다음 수행할 때에는 if문을 수행하여 fruitnowp=fruit[fruitnowp=1]+fruitcharnum(=0)'이 된다. fruit[1]+fruitcharnum(0)은 "apple"의 'a'의 주소. fruit[1]+fruitcharnum(1) 은 "apple"의 'p'의 주소이다.

 

 

자, 이번에는 중간에 pineapple을 추가해 보자. 아래 그림에서와 같이 기존코드의 선언부에 pineapple문자열 포인터 추가, fruite 배열에 이를 추가. 하면 끝이다. 삽입 코드를 별도로 길게 작성할 필요가 없다!단,,, 워닝이 x라 많다..bb

  1. 출력 형태에 따라 이상한 버그 혹은 메시지가 뜬다 : "startup initialized natural state" 뭐 이런 메시지가 들어 있다.

 

프로그래밍을 처음 배우는 사람은 어려워 보일 수 있다. 하지만 차근차근 하다 보면, 감이 잡히게 될 거이다. 이상으로 과일이름 출력을 문자열,배열,포인터 배열, 반복문을 사용하여 해 보았다. 변수명 등은 댓글로 물어보고.

도움이 되었다 싶으시면 손가락을 꾹 눌러줄래??ㅎㅎ

Posted by C언어 보이
|