관리 메뉴

나구리의 개발공부기록

2장 - 프로그래밍 언어 활용 | 섹션10. 배열과 문자열, 섹션11. 포인터, 섹션12. 구조체 본문

2024정보처리기사 준비 정리(필기 - 시나공, 실기 - 수제비)/필기 4강 - 프로그래밍 언어 활용

2장 - 프로그래밍 언어 활용 | 섹션10. 배열과 문자열, 섹션11. 포인터, 섹션12. 구조체

소소한나구리 2024. 5. 10. 09:47

2024년도 시나공 필기 책 내용 정리 


섹션10. 배열과 문자열

 

1. 배열의 개념

 

  • 동일한 데이터 유형을 여러 개 사용해야 할 경우 이를 손쉽게 처리하기 위해 여러 개의 변수들을 조합해서 하나의 이름으로 정의해 사용하는 것을 말함
  • 하나의 이름으로 여러 기억장소를 가리키기 때문에 배열에서 개별적인 요소들의 위치는 첨자를 이용해서 지정함
  • 변수명 뒤에 대괄호 []를 붙이고 그 안에서 사용할 개수를 지정
  • C언어에서의 배열의 위치는 0부터 시작됨
  • 행 우선으로 데이터가 기억장소에 할당됨
  • C 언어에서 배열의 위치를 나타내는 첨자 없이 배열 이름을 사용하면 배열의 첫 번째 요소의 주소를 지정하는 것과 같음

2. 1차원 배열

 

  • 변수들을 일직선상의 개념으로 조합한 배열
  • 자료형 변수명 [개수];
  • 자료형 : 배열에 저장할 자료의 형을 지정
  • 변수명 : 사용할 배열의 이름으로 사용자가 임의로 지정
  • 개수 : 배열의 크기를 지정하는 것으로 생략할 수 있음
  • ex) int a[5] : 5개의 요소를 갖는 정수형 배열 a
  • a[3] : a는 배열의 이름, 3은 첨자로서 배열 a에서의 위치를 나타냄, a[3]에 4를 저장시키려면 a[3] = 4와 같이 작성

// 예제 - 1차원 배열a의 각 요소에 10, 11, 12, 13, 14를 저장 후 출력
#include <stdio.h>
main()
{
  int a[5];
  int i;
  for (i = 0; i < 5; i++)   // 0 ~ 4까지 5회 반복
    a[i] = i + 10;			// 배열 a의[i]의 위치에 i + 10을 저장

  for (i = 0; i < 5; i++)
    printf("%d", a[i])      // a[i]의 값을 10진 정수형태로 출력
}
// 결과 10, 11, 12, 13, 14

 

JAVA에서의 배열 처리

 

  • 향상된 for문을 사용할 수 있는데, 향상된 for문은 객체를 대상으로만 가능함
  • JAVA에서는 배열을 객체로 취급하며, 배열을 이용하여 작업할 때 필요할 만한 내용은 이미 API로 만들어 두었기 때문에 골라서 사용할 수 있음

public class Example {
    public static void main(String[] args) {
        int[] a = new int[5];  // 자바는 보통 타입 앞에 []을 붙힘
                               // 자바는 배열을 객체로 취급하기 때문에 new를 사용해서 배열을 생성
        int i;
            for (i = 0; i < 5; i++)
                a[i] = i + 10;
            for (i = 0; i < 5; i++)
                System.out.printf("%d", a[i])
    }
}

// 향상된 for문이용하기
public class Example {
    public static void main(String[] args) {
        int[] a = {90, 100, 80, 70, 60, 50, 30}; // 배열에 값을 초기화하면서 선언
        int hap = 0;     // 합계 금액을 담을 int타입 변수 선언
        float avg;       // 평균을 담을 float타입 변수 선언
        for (int i : a)  // a의 요소의 수만큼 반복문을 수행하고, a의 요소의 값을 i에 저장
            hap = hap + i;  // 반복문이 수행될 동안 실행되는 코드
        avg = (float)hap / a.length; // hap을 float로 형변환하고 a배열의 길이의 값으로 나눈 후 avg에 저장
        System.out.printf("%d, %.2f", hap, avg) // 합계금액과 평균을 출력
    }
}

3. 2차원 배열

 

  • 변수들을 평면(행,열)로 조합한 배열
  • 자료형 변수명[행개수][열개수]
  • 자료형 : 배열에 저장할 자료의 형을 지정
  • 변수명 : 사용할 배열의 이름으로 사용자가 임의로 지정
  • 행개수 : 배열의 행 크기를 지정
  • 열개수 : 배열의 열 크기를 지정
  • int b[3][3] : 3개의 행과 3개의 열을 갖는 정수형 배열 b

  • 예제 - 3행 4열의 배열에 다음과 같이 숫자 정하기

#include <stdio.h>
main()
{
  int a[3][4];               // 3행 4열 크기의 정수형 배열 a을 선언
  int i, j, k = 0;
  for (i = 0; i < 3; i++)    // 0 ~ 2까지(3번) 반복, i = 행의 값을 나타냄
  {
    for (j = 0; j < 4; j++)  // 0 ~ 3까지(4번) 반복, j = 열의 값을 나타냄
    {                        /* 2중 반복문 이므로 i가 0일때 j가 0 ~ 4까지 반목문을 수행하고
                             2차 반복문이 종료되면 다시 1차 반복문의 i의 값을 증가시켜서 반복 */
                             
      k++;                   // 2중 반복문이 실행되면 k의값을 1증가
      a[i][j] = k;           // a[i][j]의 요소에 k의 값을 저장
    }
  }
}

4. 배열의 초기화

 

  • 배열 선언 시 초기값을 지정할 수 있음
  • 배열을 선언할 때 배열의 크기를 생략하는 경우에는 반드시 초기값을 지정해야 초기값을 지정한 개수만큼 배열이 선언됨
# 1차원 배열 선언
char a[3] = {'A', 'B', 'C'};
char a[] = {'A', 'B', 'C'};

// 2차원 배열 선언
int a[2][4] = { {10,20,30,40}, {50,60,70,80} };
int a[2][4] = {10,20,30,40,50,60,70,80};

// 배열의 개수보다 적은 수로 배열을 초기화하면 입력된 값만큼 지정한 숫자가 입력되고, 나무지 요소에는 0이 입력됨
int a[5] = {3};
int a[5] = {3,};

  • 예제 - 2차원 배열에 다음과 같이 초기화 한 후 a[0][0]과 a[1][1]의 값을 출력

#include <stdio.h>
main()
{
  int a[2][4] = {
  {10, 20, 30, 40},
  {50, 60, 70, 80}
  };
  
  printf("%d", a[0][0]);
  printf("%d", a[1][1]);
}

5. 배열 형태의 문자열 변수

 

  • C언어에서는 큰따옴표 " "로 묶인 글자는 글자 수에 관계없이 문자열로 처리됨
  • 문자열을 저장하는 자료형이 없기 때문에 배열, 또는 포인터를 이용하여 처리함
  • char 배열이름[크기] = "문자열"
  • 배열에 문자열을 저장하면 문자열의 끝을 알리기 위한 널 문자('\0')가 문자열 끝에 자동으로 삽입 됨
  • 배열에 문자열을 저장할 때는 배열 선언 시 초기값으로 지정해야 하며 이미 선언 된 배열에는 문자열을 저장할 수 없음
  • 문자열 끝에 자동으로 널 문자가 삽입되므로 널 문자까지 고려하여 배열 크기를 지정해야함
  • ex) char a[5] = "love"

  • 예제 - 다음의 출력 결과를 확인
#include <stdio.h>
main()
{
  char a = 'A';
  char b[9] = "SINAGONG"; // {'S', 'I', 'N', 'A', 'G', 'O', 'N', 'G', '\0'}
  char *c = "SINAGONG"; // 포인터 변수c에 SINAGONG이라는 문자열이 저장된 곳의 주소를 저장
  
  printf("%c\n", a); // 문자 A 출력
  printf("%s\n", b); // 배열 위치를 나타내는 첨자없이 배열이름을 사용하면, 배열 첫번째 요소의
                     // 주소를 지정하는 것과 같으므로 배열B의 첫번째 요소가 가리키는 곳의 값을 문자열로 출력
  printf("%s\n", c); // 포인터 변수c가 가리키는 곳의 값을 문자열로 출력
}
/* 출력결과 
A
SINAGONG
SINAGONG */

 

JAVA의 문자열

 

  • 문자열을 처리할 수 있도록 String 클래스를 제공
public static Example {
    public static void main(String[] args) {
        String str = "Information!";    // 문자열 str 변수에 Infromation! 문자열 저장
        int n = str.length();           // str의 길이를 정수타입 n에 저장
        char[] st = new char [n];       // n의 길이만큼 문자 배열 st 생성
        n--;                            // n의 값을 1 감소 시킴(인덱스 값으로 for문을 돌리기 위함)
        for (int k = n; k >= 0; k--) {  // 초기값을 n의 값으로 정하고 0이 될때까지 1씩 감소시키며 for문 실행
            st[n-k] = str.charAt(k);    // 문자열의 k의 인덱스에 위치한 값을 꺼내서 문자배열 st의 [n-k]의 요소에 저장
        }
        for (char k : st) {             // 문자배열 st의 요소을 k에 하나씩 꺼내서 저장
            System.out.printf("%c", k); // k의 값을 출력
        }
    }
}
// 결과 : !noitamrofnI

섹션11. 포인터

 

1. 포인터와 포인터 변수

 

  • 포인터는 변수의 주소를 말하여, C언어에서는 주소를 제어할 수 있는 기능을 제공함
  • C언어에서 변수의 주소를 저장할 때 사용하는 변수를 포인터 변수라고 함
  • 포인터 변수를 선언할 때는 자료의 형을 먼저 쓰고 변수명 앞에 간접 연산자 *를 붙힘 (ex : int *a;)
  • 포인터 변수에 주소를 저장하기 위해 변수의 주소를 알아낼 때는 변수 앞에 번지 연산자 &을 붙힘 (ex : a = &b;)
  • 실행문에서 포인터 변수에 간접 연산자*을 붙이면 해당 포인터 변수가 가리키는 곳의 값을 말함 (ex : c = *a;)
  • 포인터 변수는 필요에 의해 동적으로 할당되는 메모리 영역인 힙 영역에 접근하는 동적 변수임
  • 포인터 변수의 용도

    • 연결된 자료 구조를 구성하기 위해 사용함
    • 동적으로 할당된 자료 구조를 지정하기 위해 사용
    • 배열을 인수로 전달하기 위해 사용
    • 문자열을 표현하기 위해 사용
    • 커다란 배열에서 요소를 효율적으로 저장하기 위해 사용
    • 메모리에 직접 접근하기 위해 사용
  • 예를 들어 a 변수에 100을 저장시키고, a의 변수의 주소를 포인터 변수 b에 기억시켰다면?

    • a의 메모리 주소가 4번지라고 하면, a는 메모리 4번지에 대한 이름이고, a변수의 주소는 4임
    • a의 변수에는 100이 기억되고 있음 = 메모리 4번지에는 100이 기억되어 있음
    • &a는 a변수의 주소를 말하며, a의 주소는 4 == &a 임
    • 포인터 변수 b는 a 변수의 주소를 기억하고 있음,
    • 포인터 변수가 가리키는 곳의 값을 말할 때는 *을 붙힘
    • *b는 b에 저장된 주소가 가리키는 곳에 저장된 값을 말하므로 100임
  • 예제 - 다음 C언어로 구현된 프로그램의 출력 결과를 확인
main()
{
  int a = 50;
  int *b;    // 포인터 변수(정수타입) b 선언 - 주소를 기억하는 포인터 변수
  b = &a;    // 포인터 변수 b에 a의 주소값을 저장(기억시킴)
  *b = *b + 20;  // *b는 a의 주소값을 저장했으므로 a의 값을 가리킴(50)
                 // 50 + 20연산한 값을 *b(a의 주소값을 가르키는 변수)에 저장했으므로 a의 값도 변경됨
  printf("%d, %d", a, *b);
}
// 결과 70, 70


main()
{
  int a = 3, *b; // 인트 타입 변수a에 3을 저장하여 선언하고, 포인터변수 b를 선언
  b = &a;        // 포인트 변수 b에 a의 메모리 주소값을 저장(a의 주소값을 가르킴)
  printf("%d", ++*b);   // *b의 값 == b가 가르키는 메모리의 주소a의 값
}
// 결과 4

2. 포인터와 배열

 

  • 배열을 포인터 변수에 저장한 후 포인터를 이용해 배열의 요소에 접근할 수 있음
  • 배열 위치를 나타내는 첨자를 생략하고 배열의 대표명만 지정하면 배열의 첫 번째 요소의 주소를 지정하는 것과 같음
  • 배열 요소에 대한 주소를 지정할 때는 일반 변수와 동일하게 & 연산자를 사용함
int a[5], *b;

b = a // 배열의 대표명을 적었으므로 a배열의 시작 주소인 a[0]의 주소를 b에 저장
b = &a[0] // a 배열의 첫 번째 요소인 a[0]의 주소(&)을 b에 저장

  • 배열의 요소가 포인터인 포인터형 배열을 선언할 수 있음
  • 예제 - 다음 코드의 출력 결과 확인
main()
{
  int a[5];
  int i;
  int *p;  // 포인터 변수 선언
  for (i = 0; i < 5; i++)
    a[i] = i + 10;   // 배열a[0] ~ [4]까지 10, 11, 12, 13, 14를 순서대로 저장
  p = a;   // 포인터 변수 p에 a[0]의 메모리 주소를 저장
  for (i = 0; i < 5; i++)
    printf("%d", *(p + i)); // 배열의 포인터 표기 방법으로 포인터가 가르키는 요소의 값들을 출력
}
// 출력 결과 : 10, 11, 12, 13, 14


int a = 5, b, *c;
c = &a;
b = ++*c;
printf("%d", b);
// 출력 결과 : 6

int a = 10, *b;
b = &a;
for (int i = 0; i < 5; i++)
  *b += i;
printf("%d", *b);
// 출력 결과 : 20

int a = 31, b, *c, *d;
c = &a;                        // 포인터 변수 c는 a의 주소값을 가르킴
d = &b;
*d = --*c % 3 ? a + a : a * a; // --*c == 30(a의 값) % 3을 하면 0(거짓이됨)
                               // 조건식이 거짓이 되어 a(30) * a(30) = 900
printf("%d", d);
// 출력 결과 : 341

int a = 5, b = 7, c, *d;
d = &c;
*d = a & b;     // a의 2진수와 b의 2진수의 각 자릿수를 비교하여 둘다 1이면 1, 아니면 0을 반환
                // 5 = 101, 7 = 111 & 연산하면 1(둘다1), 0(하나만 1,) 1(둘다1)로 101 = 5가 됨
printf("%d", c);
// 출력 결과 : 5

섹션12. 구조체

 

1. 구조체의 개요

 

  • 자료의 종류가 다른 변수의 모임
  • 구조체의 정의

    • int나 char같은 자료형을 하나 만드는 것을 의미
    • structure의 약어 struct를 사용하여 정의
    • struct : 구조체를 정의하는 예약어
    • sawon : 구조체의 이름, 임의로 정하면 됨
    • 멤버 : 일반 변수를 선언하는 것과 동일하게 필요한 필드를 선언
struct sawon {
   char name[10];
   char jikwi[10];
   int pay;
};

 

  • 구조체 변수의 선언
    • 일반 변수를 선언할 때 앞에 자료형을 선언하 듯이 구조체 변수를 사용하려면 자료형을 구조체로 입력후 변수명을 입력하여 선언해야 함
    • struct : 구조체 변수를 선언하는 예약어
    • ansan : 정의한 구조체 sawon 자료형으로 변수를 ansan이라는 변수의 이름으로 선언, 변수명은 임의로 지정
    • *seoul : 구조체의 포인터 변수, struct sawon ansan *seoul; 처럼 별도로 선언 가능
struct sawon ansan, *seoul;

 

  • 구조체 멤버의 지정
    • 구조체의 멤버는 모든 요소들이 개별적인 이름을 가지고 있어 구조체 멤버를 지정할 때는 구조체 변수와 함께 멤버 이름을 지정해야함
  •  
// '.'으로 지정 : 구조체 일반 변수를 이용해 구조체 멤버를 지정할 때
ansan.name = "김한국";
ansan.jikwi = "대리";
ansan.pay = 4000000;

// '->'으로 지정 : 구조체 포인터 변수를 이용해 구조체 멤버를 지정
seoul->name = "홍길동";
seoul->jikwi = "과장";
seoul->pay = 5000000;

// 구조체의 포인터 변수는 일반 포인터 변수처럼 *을 사용하여 멤버를 지정할 수도 있음
(*seoul).name = "홍길동";
(*seoul).jikwi = "과장";
(*seoul).pay = 5000000;

2. 구조체의 활용

 

  • 다음 C언어로 구현된 프로그램의 실행 결과를 확인
#include <stdio.h>
struct jsu {    // 구조체 jsu 정의
    char nae[12];           // 구조체의 멤버로 길이가 12인 char배열 변수 nae 선언
    int os, db, hab, hhab;  // 구조체의 멤버로 정수형 변수들 선언
};

int main() {
    // 구조체 jsu 자료형으로 3개짜리 배열 st를 선언 후 값을 초기화
    
    // st[0] 안에 nae의 변수에 '데','이','터','1','\0' 이 저장되고
    // 구조체의 선언한 변수 순서대로 os에 95, db에 88이 저장됨
    // st[1]과 st[2]에도 마찬가지로 저장됨
    struct jsu st[3] = {{"데이터1",95,88}, {"데이터2",84,91}, {"데이터3",86,75}};
    
    struct jsu *p; // 구조체 포인터 변수 p선언
    p = &st[0];    // 구조체 포인터 변수 p 에 st배열[0]번째 주소를 저장
    
    // (p + 1) 은 st[1]요소를 뜻하며 그 멤버변수 hab에 아래의 연산 결과를 저장
    // 그 hab에 (p+1)즉 st[1]이 가르키는 멤버 os의 값과 (p+2)즉 st[2]가 가르키는 멤버 db의 값을 더하기 연산
    // (p + 1), st[1]의 멤버변수 hab에는 st1의 os 변수의 값과 st2의 db변수의 값을 더한 값이 저장됨
    // st[1]의 hab = 84(st[1]의 os값) + 75([st2]의 db값)
    (p + 1)->hab = (p + 1) -> os + (P + 2) -> db;
    
    // st[1]의 hhab 변수에, st[1]의 hab변수의 값과 p, 즉st[0]의 os 변수의 값과 st[0]의 db의 값을 모두 더해서 저장
    // st[1]의 hhab = 159 + 95(st[0]의 os값) + 88(st[0]의 db값)
    (p + 1)->hhab = (p + 1) -> hab + p -> os + p -> db;
    
    // 출력은 st[1]의 hab변수와 hhab변수의 값을 더한 값을 출력
    // 159 + 342
    
    printf("%d", (p + 1) -> hab + (p + 1) -> hhab);
}
// 출력결과 : 501