[24.08.11] c언어의 기초 9

2024. 8. 11. 16:18·LAB/C
Chapter 10 배열과 포인터

 

1. 배열

  • 동일한 하나의 데이터형을 가진 연속된 원소들로 구성된다.
  • 배열 선언을 사용하여 컴파일러에게 알려야한다. (원소들의 데이터형을 알린다.)
  • 배열은 배열의 크기와 초기값 리스트에 들어있는 항목의 개수가 일치해야한다.
  • 배열의 크기를 생략하면, 컴파일러가 스스로 초기값 리스트에 맞게 배열크기를 설정한다.

* 배열 선언 예시

더보기

int main(void)

{

     float  candy[326];    /* 326개의 float형 값을 가지는 배열 */

     char  code[12];       /* 12개의 char형 값을 가지는 배열 */

     int  states[50];       /* 50개의 int형 값을 가지는 배열 */

}

1-1. 초기화

  • 변수와 같이 초기화가 필요하다.
  • 배열은 콤마로 분리된 값들의 리스트를 중괄호({ })로 감싸서 초기화 한다.
  • 원한다면 값과 콤마 사이에 스페이스를 넣을 수도 있다.
  • 이 형식으로 배열 초기화 시 신택스 오류 발생한다면, 버전이 낮은 컴파일러 이기 때문에 배열 선언 앞에 static을 붙이면 해결된다.

* 배열 초기화 예시

더보기

int main(void)

{

     int power[8] = {1,2,4,6,8,16,32,64};

}

*** 배열 예제1(10.1)

/* 배열 선언 출력*/
#include <stdio.h>
#define MONTHS 12

int main(void)
{
	// 배열 초기화
    int days[MONTHS] = {31,28,31,30,31,30,31,31,30,31,30,31};
    int index;
    
    for (index = 0; index < MONTHS; index++)
        printf("Month %d has %2d days.\n", index +1,
               days[index]);
    
    return 0;
}

 

- #define MONTHS 12 상수 선언으로 days[MONTHS] -> days[12] 로 선언된다.

 

*** 배열 예제2(10.2)

- 배열을 초기화 시키지 않았을 시

/* 배열 초기화 시키지 않았을때*/
#include <stdio.h>
#define SIZE 4
int main(void)
{
    int no_data[SIZE];  /*  초기화 시키지 않은 배열 */
    int i;
    
    printf("%2s%14s\n",
           "i", "no_data[i]");
    for (i = 0; i < SIZE; i++)
        printf("%2d%14d\n", i, no_data[i]);
    
    return 0;
}

 

- 시스템에 따라 다르게 나온다.

- C언어에서는 초기화를 시키지 않으면 아무값(쓰레기값)이 가지게 된다.

 

*** 배열 예제3(10.3)

- 배열의 크기와 초기화 항목의 개수가 맞지 않을 때 

/*  배열의 크기와 초기화값의 개수가 맞지 않을때 */
#include <stdio.h>
#define SIZE 4
int main(void)
{
    int some_data[SIZE] = {1492, 1066};
    int i;
    
    printf("%2s%14s\n",
           "i", "some_data[i]");
    for (i = 0; i < SIZE; i++)
        printf("%2d%14d\n", i, some_data[i]);
    
    return 0;
}

 

- 컴파일러는 값이 들어있는 리스트에만 넣어주고 나머지는 0으로 초기화 했다.

- 즉, 배열을 일부분만 초기화하면 나머지 원소들은 0으로(쓰레기값 : 사용하지않는값) 설정된다.

 

*** 배열 예제4(10.4)

- 배열의 크기를 생략하면, 컴파일러가 스스로 초기값 리스트에 맞게 배열크기를 설정

/* 배열의 크기를 생략하면, 자동으로 리스트에 맞게 배열크기설정 */
#include <stdio.h>
int main(void)
{
    const int days[] = {31,28,31,30,31,30,31,31,30,31};
    int index;
    
    for (index = 0; index < sizeof days / sizeof days[0]; index++)
        printf("Month %2d has %d days.\n", index +1,
               days[index]);
    
    return 0;
}

 

- for 루프 제어문 : 컴퓨터가 배열 크기를 계산해서 우리에게 알려주도록 부탁한다.

- sizeof 연산자를 사용하여 days의 바이트 수로 배열전체의 크기를 알 수 있다.

  • sizeof days[0] : 바이트 수로 배열 원소 하나의 크기다.
  • sizeof days / sizeof days[0] 
  • 배열 전체의 크기를 배열원소 하나의 크기로 나누면, 그 배열에 몇개의 원소가 있는지 알 수 있다.

- 단점 : 원소의 개수가 틀렸어도 컴파일러가 에러를 잡아내지 못한다.

 

1-2. 지정 초기화자

  • 지정 초기화자(Designated Initialalizer)기능을 사용하면 초기화할 원소들을 사용자가 선택할 수 있다.
  • 초기화 리스트에서 각괄호 안에 인덱스를 사용하여 특정원소를 초기화 하도록 지정할 수 있다.

int arr[6] = { [5] = 212};  /* arr[5]를 212로 초기화 한다. */

 

*** 배열 예제4(10.4)

// 지정 초기화자를 사용한다.
#include <stdio.h>
#define MONTHS 12
int main(void)
{
    int days[MONTHS] = {31,28, [4] = 31,30,31, [1] = 29};
    int i;
    
    for (i = 0; i < MONTHS; i++)
        printf("%2d  %d\n", i + 1, days[i]);
    
    return 0;
}

 

- 지정초기화자 뒤에 여러개의 값이 붙으면, 여분으로 붙는 값들은 이어지는 다음 원소들을 초기화 하는데 사용된다.

즉, days[4]가 31로 초기화되고, days[5]와 days[6]이 30과 31로 초기화된다.

- 특정원소가 어떤값으로 초기화되면, 마지막에 행해진 초기화가 유효하다. 

ex.) days[1] = 28로 초기화 되지만, 나중에 지정 초기화자 [1] = 29에 의해 초기화값이 지워지고 29가 된다.

 

1-3. 배열에 값 대입하기

- 배열을 선언한 후에는, 하나의 배열 인덱스를 사용하여 배열 원소들의 값들을 대입할 수 있다.

*** 배열에 값 대입하기 예제 

// 배열에 짝수의 값 대입하기 
#include <stdio.h>
#define SIZE 50

int main(void)
{
    int counter, evens[SIZE];

    for(counter = 0; counter < SIZE ; counter++)
    {
        evens[counter] = 2 * counter ;
        printf("evens[%d] = %d\n",counter, evens[counter]);
    }
}

 

 

*** 허용되지 않는 배열에 값 대입하기 예제

// 허용되지 않는 배열에 값 대입하기
#include <stdio.h>
#define SIZE 5

int main(void)
{
    int oxen[SIZE] = {5,3,2,8}; // 허용된다.
    int yaks[SIZE];

    yaks = oxen;   // 허용되지 않는다.
    yaks[SIZE] = oxen[SIZE]; // 유효하지 않는다.
    yaks[SIZE] = {5,3,2,8};  // 동작하지 않느다.
}

 

1-4. 배열의 범위

  • 유효한 범위 내에 있는 배열 인덱스를 사용하고 있는지 반드시 확인해야 한다!!!
  • 컴파일러가 인덱스에러를 모두 잡아낼 수 있는 것은 아니다. 왜냐하면 프로그램이 실행을 시작한 후에도 인덱스 값이 결정되지 않을 수도 있기 때문이다.
  • 안정을 보장하려면, 실행하는 동안에 인덱스 값을 검사하는 가외의 코드를 추가해야하고, 그것은 프로그램의 실행을 느리게 만든다.

*** 배열범위 예제1(10.6)

// 배열의 범위를 벗어난다.
#include <stdio.h>
#define SIZE 4
int main(void)
{
    int value1 = 44;
    int arr[SIZE];
    int value2 = 88;
    int i;
    
    printf("value1 = %d, value2 = %d\n", value1, value2);
    for (i = -1; i <= SIZE; i++)
        arr[i] = 2 * i + 1;
    
    for (i = -1; i < 7; i++)
        printf("%2d  %d\n", i , arr[i]);
    printf("value1 = %d, value2 = %d\n", value1, value2);
    
    printf("arr[-1]의 주소: %p\n", &arr[-1]);
    printf("arr[4]의 주소:  %p\n", &arr[4]);
    printf("value1의 주소:  %p\n", &value1);
    printf("value2의 주소:  %p\n", &value2);
   
    return 0;
}

 

- 컴파일러는 인덱스들이 유효한지 검사하지 않는다. 잘못된 인덱스를 사용했을 때 어떤결과가 나올지 정의되지않는다.

- arr[-1]은 value2와 동일한 메모리 위치에 대응되고, arr[4]는 value1과 동일한 메모리 위치에 대응된다.

  • 하지만 실행결과를 보면 내 컴파일러는 잘 찾아냈지만 컴파일러 by 컴파일러로 value1 = -1 / value2 = 9를 찾아야한다.

- 배열 범위를 벗어나는 인덱스를 사용하면, 프로그램이 다른 변수의 값을 변경하는 결과를 낳는다.

 

1-5. 배열 크기 지정하기

- 코드를 보고 가능한것을 익히자!!!!

#include<stdio.h>
#define SIZE 4
int main(void)
{
    int arr[SIZE];       // 기호 정수 상수
    double lots[144];   // 리터럴 정수 상수

    int n = 5;
    int m = 8;
    float a1[5];                // 가능
    float a2[5*2 +1];           //  가능
    float a3[sizeof(int) +1];   // 가능
    float a4[-4];               // 불가능 , 배열 크기는 0보다 커야한다.
    float a5[0];                // 불가능, 배열 크기는 0보다 커야한다.
    float a6[2.5];              // 불가능, 배열 크기는 정수여야한다.
    float a7[(int)2.5];         // 가능, float형을 int constant형으로 캐스트한다.(형변환)

    float a8[n];                // C99 이전에 허용되지 않았다.
    float a9[m];                // C99 이전에 허용되지 않았다.
}

 


2. 다차원 배열

(2차원 배열만 알면된다!!!)

- 배열의 배열을 사용하는것

float rain[5][12];  // float형 원소 12개인 배열이, 5개의 원소인 배열 

  • 먼저 안쪽 부분을 해석한다. rain[5] : rain은 원소가 5개인 배열이다.
  • float rain[5][12];    // 12개의 float형 원소를 가지는 배열로 해석하면 쉽게 이해된다.
  • rain의 원소가 float[12]형이라는 것을 나타낸다. 즉, rain을 구성하는 5개의 원소는 각각 12개의 float형 값을 가지는 배열들이다.
  • ex.) rain[2][3] (배열 인덱스는 0부터 카운트되므로, 2행은 세번째 3열을 가리킨다.)
  • ex.) rain[5][12] (5행 12열을 뜻함)

*** 다차원배열 예제1(10.7)

/* 강우량 데이터로부터 각 해의 총 강우량과 몇년에 걸쳐 계산한 연평균
강우량, 각 달의 월평균 강우량을 구한다.*/
#include <stdio.h>
#define MONTHS 12    // 1년의 달 수
#define YEARS   5    // 데이터를 수집한 햇수 
int main(void)
{
    //  2010 - 2014 까지의 강우량 데이터의 초기화
    const float rain[YEARS][MONTHS] =
    {
        {4.3,4.3,4.3,3.0,2.0,1.2,0.2,0.2,0.4,2.4,3.5,6.6},
        {8.5,8.2,1.2,1.6,2.4,0.0,5.2,0.9,0.3,0.9,1.4,7.3},
        {9.1,8.5,6.7,4.3,2.1,0.8,0.2,0.2,1.1,2.3,6.1,8.4},
        {7.2,9.9,8.4,3.3,1.2,0.8,0.4,0.0,0.6,1.7,4.3,6.2},
        {7.6,5.6,3.8,2.8,3.8,0.2,0.0,0.0,0.0,1.3,2.6,5.2}
    };
    int year, month;
    float subtot, total;
    
    printf(" 년도    강우량  (인치)\n");
    for (year = 0, total = 0; year < YEARS; year++)
    {             // 각 해에 대해 12달치 강우량을 더한다.
        for (month = 0, subtot = 0; month < MONTHS; month++)
            subtot += rain[year][month];
        printf("%5d %15.1f\n", 2010 + year, subtot);
        total += subtot; // 여러 해에 걸친 총 강우량을 구한다.
    }
    printf("\n연평균 강우량은 %.1f 인치입니다.\n\n",
           total/YEARS);
    printf("월평균 강우량은 다음과 같습니다.\n\n");
    printf(" Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct ");
    printf(" Nov  Dec\n");
    
    for (month = 0; month < MONTHS; month++)
    {             // 각 달에 대해 5년치 강우량을 더한다.
        for (year = 0, subtot =0; year < YEARS; year++)
            subtot += rain[year][month];
        printf("%4.1f ", subtot/YEARS);
    }
    printf("\n");
    
    return 0;
}

 

- for (year = 0, total = 0; year < YEARS; year++) : 각 해에 대해 처리한다.

- for (month = 0, subtot = 0; month < MONTHS; month++) : 각 달에 대해 처리한다.

 

2-1. 2차원 배열의 초기화

- 2차원 배열을 초기화 하려면, 콤마로 분리된 이와 같은 리스트가 필요하다.

const float rain[YEARS][MONTHS] =
    {
        {4.3,4.3,4.3,3.0,2.0,1.2,0.2,0.2,0.4,2.4,3.5,6.6},
        {8.5,8.2,1.2,1.6,2.4,0.0,5.2,0.9,0.3,0.9,1.4,7.3},
        {9.1,8.5,6.7,4.3,2.1,0.8,0.2,0.2,1.1,2.3,6.1,8.4},
        {7.2,9.9,8.4,3.3,1.2,0.8,0.4,0.0,0.6,1.7,4.3,6.2},
        {7.6,5.6,3.8,2.8,3.8,0.2,0.0,0.0,0.0,1.3,2.6,5.2}
    };

- const float rain[5][12]로 해석된다.

 


3. 포인터와 배열

- 배열표기는 실제로는 포인터의 변장된 사용에 불과하다.

  • flizny가 배열이라면, flizny == &flizny[0]  // 배열의 이름은 첫 번째 원소의 주소다.
  • flizny와 &flizny[0]은 둘 다 첫 번째 원소의 메모리 주소를 나타낸다.

* & 연산자는 주소 연산자라는 것을 기억하고 있어라!!!

* flizny와 &flizny[0]은 고정값으로 상수이다. 그러나 이들은 둘 다 포인터 변수에 값으로 대입될 수 있다.

 

*** 포인터와 배열 예제1(10.8)

// 포인터 덧셈
#include <stdio.h>
#define SIZE 4
int main(void)
{
    short dates [SIZE];
    short * pti;
    short index;
    double bills[SIZE];
    double * ptf;
    
    pti = dates;    // 배열의 주소를 포인터에 대입한다.
    ptf = bills;
    printf("%23s %15s\n", "short", "double");
    for (index = 0; index < SIZE; index ++)
        printf("포인터 + %d: %10p %10p\n",
               index, pti + index, ptf + index);
    
    return 0;
}

 

- 바이트 단위로 주소가 매겨진다.

- short형은 2바이트를 사용하고, double형은 8바이트를 사용한다.

 

 

* 스칼라 변수 (개념만 알고가자)

  • 두가지 유형이 있다. (가변 변수 와 불변 변수)
  • 가변 변수(Variable) : 재할당이 가능하다.
  • 불변 변수(Value) : 한 번 값이 정해지면 변경되지 않기때문에 데이터 처리에 있어 단순하게 처리할 수 있는 장점이 있다.
  • 스칼라는 동시처리를 중요하게 생각하기 때문에 변경 불가능한 데이터를 중요하게 생각합니다. 데이터의 변경이 가능하면 동시처리시에 데이터에 대한 고민이 많아지게 됩니다. 따라서 불변 변수로 설정하는 것을 선호합니다.
더보기

var variable = 10

val value = 20

 

// var 값의 재할당은 처리 가능

scala> variable = 30

variable: Int = 30

 

/// value 값의 재할당은 오류 발생

scala> value = 40

 

<console>:12: error: reassignment to val value = 40 ^

* 포인터 (개념)

  • 포인터의 값은 원소 객체의 주소이다.
  • 바이트 단위로 주소를 매긴다. 이것은 메모리의 각 바이트들이 연속적으로 번호가 매겨져 있다는 것을 의미한다.
  • 포인터에 *연산자를 적용하면, 그 포인터가 가리키는 객체에 저장되어 있는 값을 얻는다.
  • 포인터에 1을 더하면, 그 포인터가 가리키는 객체의 바이트 수 크기만큼 포인터 값이 증가한다.
  • double형 변수와 같이, 큰 객체의 주소는 첫번째 바이트안에 주소값을 갖는다!!!!!
  • ex.) int array [2] = {1,2} => int는 4바이트 이기때문에 array[0]의 주소값은 첫번째에 갖는다. array[1]의 주소값은 array[0]번째 주소값에 + 4를 더하면 array[1]의 주소값을 찾을 수 있다.
  • ex.) double형이면 , +8을 해줘야 array[1]의 주소값을 찾을 수 있다.

dates + 2 == &dates[2]   // 주소가 같다

*(dates + 2) == &dates[2] // 값이 같다

 

  • C언어 표준은, 배열 표기를 포인터로 서술한다. 즉, ar[n]이 *( ar + n )을 의미하도록 정의한다.
  • *( ar + n )을 "메모리 위치 ar로 가라. n개의 기억단위 만큼 이동하라. 거기에 있는 값을 꺼내라)
  • ex.) *( dates + 2)   // dates의 세번째 원소의 값이다.
  • ex.) *dates + 2 // dates의 첫번째의 원소값에 2를 더한다.

*** 배열과 포인터예제1 (10.9)

/* 포인터 표기를 사용한다. */
#include <stdio.h>
#define MONTHS 12

int main(void)
{
    int days[MONTHS] = {31,28,31,30,31,30,31,31,30,31,30,31};
    int index;
    
    for (index = 0; index < MONTHS; index++)
        printf("%2d월: 날짜수 %2d\n", index +1,
               *(days + index));   // days[index]와 같다.
    
    return 0;
}

 

- days는 그 배열의 첫 번째 원소의 주소이다. days + index는 원소 days[index]의 주소다.

- *(days + index)는 그 원소의 값 즉, days[index]다.

- 배열의 표기와 포인터 표기가 동등한 방법이다.

 


4. 함수, 배열, 포인터 (통합하여 사용하는 방법)

- 어떤 배열의 원소들의 합을 리턴하는 함수를 원할때 , marbles가 int형의 원소들을 가지는 배열이라고 가정하자 

  • 함수호출 모습 : total = sum(marbles);
  • 프로토 타입 : int sum(int *ar);  // 배열의 이름은 첫번째 원소의 주소라는 사실을 기억해라 + sum()은 그 위치에서 하나의 int형을 찾을 수 있다는 사실을 알게 된다. 단, 원소의 개수는 알 수가 없다.
  • 함수 정의 : 

[1번째 방법]

고정된 배열의 크기를 함수 안에 코딩하는 것
- 배열을 찾을 장소와 배열에 있는 데이터형을 함수에게 알린다.

#include <stdio.h>
int sum(int *ar);
int main()
{
    int total;
    int marbles[10];

    total = sum(marbles);
}
int sum(int *ar) // 대응하는 함수정의
{
    int i;
    int total =0;

    for(i=0;i<10;i++)   // 원소가 10개라고 가정한다.
    {
        total += ar[i];  // ar[i]는 *(ar+i)와 같다
                         // total = 원소들의 누계
    }
    return total;
}

[2번째 방법]

고정된 배열의 크기를 함수 안에 코딩하는 것

- 그 배열에 몇 개의 원소가 있는지 함수에게 알린다.

- int sum (int *ar, int n) 추가

#include <stdio.h>
int sum(int *ar, int n);
int main()
{
    int total;
    int marbles[10];

    total = sum(marbles);
}
int sum(int *ar, int n) // 대응하는 함수정의
{
    int i;
    int total =0;

    for(i=0;i<10;i++)   // 원소가 10개라고 가정한다.
    {
        total += ar[i];  // ar[i]는 *(ar+i)와 같다
                         // total = 원소들의 누계
    }
    return total;
}

 

 

4-1. 배열 매개변수의 선언

- 배열 이름은 첫 번째 원소의 주소이기 때문에, 배열 이름을 실전달인자로 사용하려면 대응하는 형식 매개변수가 포인터가 되어야한다.

더보기

int ar[ ]를 int * ar와 같은 의미로 즉, ar이 int형을 가리키는 포인터형이라고 해석한다.

  • int sum(int *ar, int n);
  • int sum(int *, int);
  • int sum(int ar[ ], int n);
  • int sum(int [ ], int);

프로토 타입에서는 이름을 생략 가능하다 이와같이 4개의 이름은 동등하다.

 

단, 함수정의에서는 이름을 생략할 수 없다. 그래서 함수 정의에서는 다음 두가지 형식으로 나타낸다.

 

1. int sum(int *ar, int n)

{

      // 여기에 실행 할 코드 작성

}

 

2. int sum(int ar[ ], int n)

{

    // 여기에 실행 할 코드 작성

}

 

*** 배열 매개변수예제 1(10.10)

- 최초 배열의 크기와 그 배열을 나타내는 함수 매개변수의 크기를 출력한다.

// 배열 원소들의 합을 구하는 예제
// %zd가 동작하지 않는다면 %u, %lu를 사용하세요.
#include <stdio.h>
#define SIZE 10
int sum(int ar[], int n);
int main(void)
{
    int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20};
    long answer;
    
    answer = sum(marbles, SIZE);
    printf("구슬의 전체 개수는 %ld개 입니다.\n", answer);
    printf("marbles의 크기는 %zd 바이트 입니다.\n",
           sizeof marbles);
    
    return 0;
}

int sum(int ar[], int n)     // how big an array?
{
    int i;
    int total = 0;
    
    for( i = 0; i < n; i++)
        total += ar[i];
    printf("ar의 크기는 %zd 바이트입니다.\n", sizeof ar);
    
    return total;
}


4-2. 포인터 매개변수의 이용

*** 포인터 배열 함수 사용 예제1(10.11)

- 함수가 포인터 자체의 값을 변경할 수 있다.

/* 배열 원소들의 합을 구한다. */
#include <stdio.h>
#define SIZE 10
int sump(int * start, int * end);
int main(void)
{
    int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20};
    long answer;
    
    answer = sump(marbles, marbles + SIZE);
    printf("구슬의 전체 개수는 %ld입니다.\n", answer);
    
    return 0;
}

/* 포인터 계산을 사용한다.   */
int sump(int * start, int * end)
{
    int total = 0;
    
    while (start < end)
    {
        total += *start; // total에 값을 더한다.
        start++;         // 포인터를 증가시켜 다음 원소를 가리킨다.
    }
    
    return total;
}

 

*** 포인터 전위 후위 연산 (10.12)

/* 포인터 연산에서의 우선순위 */
#include <stdio.h>
int data[2] = {100, 200};
int moredata[2] = {300, 400};
int main(void)
{
    int * p1, * p2, * p3;
    
    p1 = p2 = data;
    p3 = moredata;
    printf("  *p1 = %d,   *p2 = %d,     *p3 = %d\n",
           *p1     ,   *p2     ,     *p3);
    printf("*p1++ = %d, *++p2 = %d, (*p3)++ = %d\n",
           *p1++     , *++p2     , (*p3)++);
    printf("  *p1 = %d,   *p2 = %d,     *p3 = %d\n",
           *p1     ,   *p2     ,     *p3);
    
    return 0;
}

'LAB > C' 카테고리의 다른 글

[24.08.13] c언어의 기초 11  (0) 2024.08.13
[24.08.12] c언어의 기초10  (1) 2024.08.12
[24.08.10] c언어의 기초8  (0) 2024.08.10
[24.08.09] c언어의 기초7  (1) 2024.08.09
[24.08.08] c언어의 기초6  (2) 2024.08.08
'LAB/C' 카테고리의 다른 글
  • [24.08.13] c언어의 기초 11
  • [24.08.12] c언어의 기초10
  • [24.08.10] c언어의 기초8
  • [24.08.09] c언어의 기초7
it-lab-0130
it-lab-0130
it-lab-0130 님의 블로그 입니다.
  • it-lab-0130
    빠냐냐~
    it-lab-0130
  • 전체
    오늘
    어제
    • 분류 전체보기 (69)
      • 개인 (2)
        • 개발TIP Program (2)
      • LAB (47)
        • Python (5)
        • C (13)
        • TCP_IP (7)
        • C++ (9)
        • QT_C++ (4)
        • C# (9)
      • Project (0)
        • 오류 모음 (0)
        • Python (0)
        • C 와 TCP_IP소켓 (0)
        • C++ (0)
      • Study_ (17)
        • 예제_문제풀이 (10)
        • 학습일지 (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • Python
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
it-lab-0130
[24.08.11] c언어의 기초 9
상단으로

티스토리툴바