'C언어'에 해당되는 글 26건

  1. 2020.12.08 함수 포인터
  2. 2020.12.08 동적 메모리 할당
  3. 2020.12.07 다차원 배열과 포인터 배열
  4. 2020.12.07 컴퓨터가 변수를 처리하는 방법
  5. 2020.12.05 문자열
  6. 2020.12.04 문자
  7. 2020.12.04 포인터
  8. 2020.12.04 배열
  9. 2020.12.04 함수
  10. 2020.12.04 반복문

함수 포인터

C언어 2020. 12. 8. 22:05

함수 포인터

1.

- C언어에서는 함수의 이름을 이용해 특정한 함수를 호출함

- 함수 이름은 메모리 주소를 반환함

#include <stdio.h>
#include <stdlib.h>

void function(){
    printf("It's my function");
}

int main(void) {
    printf("%d\n", function);
    system("pause");
    return 0;
}

 

2.

- 함수 포인터는 특정한 함수의 반환 자료형을 지정하는 방식으로 선언할 수 있음

- 함수 포인터를 이용하면 형태가 같은 서로 다른 기능의 함수를 선택적으로 사용할 수 있음

 

반환 자료형(*함수명)(매개변수) = 함수명;

반환 자료형(*이름)(매개변수) = 함수명;

 

* 매개변수 및 반환 자료형이 없는 함수 포인터

#include <stdio.h>
#include <stdlib.h>

void myFunction(){
    printf("It's my function.\n");
}

void yourFunction(){
    printf("It's your function.\n");
}

int main(void){
    void(*fp)() = myFunction;
    fp();
    fp = yourFunction;
    fp();
    system("pause");
    return 0;
}

 

* 매개변수 및 반환 자료형이 있는 함수 포인터

#include <stdio.h>
#include <stdlib.h>

int add(int a, int b) {
    return a + b;
}

int sub(int a, int b) {
    return a - b;
}

int main(void) {
    int(*fp) (int, int) = add;
    printf("%d\n", fp(10, 3));
    fp = sub;
    printf("%d\n", fp(10, 3));
    system("pause");
    return 0;
}

 

* 함수 포인터를 반환하여 사용하기

#include <stdio.h>
#include <stdlib.h>

int add(int a, int b) {
    return  a + b;
}

int(*process(char *a))(int, int) {
    printf("%s\n", a);
    return add;
}

int main(void){
    printf("%d\n", process("10과 20을 더한 값을 출력")(10, 20));
    system("pause");
    return 0;
}

 

 

- C언어 프로그램의 모든 함수는 내부적으로 포인터 형태로 관리할 수 있음

- 함수 포인터는 자주 사용되지 않지만 알고 있으면 컴퓨터의 구조를 이해하는데 도움을 줌

'C언어' 카테고리의 다른 글

파일 입출력  (0) 2020.12.08
구조체  (0) 2020.12.08
동적 메모리 할당  (0) 2020.12.08
다차원 배열과 포인터 배열  (0) 2020.12.07
컴퓨터가 변수를 처리하는 방법  (0) 2020.12.07
Posted by khon98
,

동적 메모리 할당

C언어 2020. 12. 8. 16:33

동적 메모리 할당의 개념

1.

- 일반적으로 C언어에서 배열의 경우 사전에 적절한 크기만큼 할당해주어야 함

- 우리가 원하는 만큼만 메모리를 할당해서 사용하고자 한다면 동적 메모리 할당을 사용함

- 동적이라는 말의 의미는 '프로그램 실행 도중에'라는 의미

- C언어에서는 malloc( ) 함수를 이용해 원하는 만큼의 메모리 공간을 확보할 수 있음

- malloc( ) 함수는 메모리 할당에 성공하면 주소를 반환하고, 그렇지 않으면 null을 반환함

- malloc( ) 함수는 <stdlib.h> 라이브러리에 정의되어 있음

 

malloc(할당할 바이트 크기);

 

2.

- 동적 메모리 할당을 수행할 때마다 할당되는 포인터의 주소는 변칙적임

#include <stdio.h>
#include <stdlib.h>

int main(void){
    int *a = malloc(sizeof(int));
    printf("%d\n", a);
    *a = malloc(sizeof(int));
    printf("%d\n", a);
    system("pause");
    return 0;
}

 

동적 메모리 할당 함수

1.

- 동적으로 할당된 변수는 <힙 영역>에 저장됨

 

코드 영역 - 소스코드

데이터 영역 - 전역 변수, 정적 변수

힙 영역 - 동적 할당 변수

스택 영역 - 지역 변수, 매개변수

 

2.

- 전통적인 C언어에서는 스택에 선언된 변수는 따로 메로리 해제를 해주지 않아도 됨

- 반면에 동적으로 할당된 변수는 반드시 free( ) 함수로 메모리 해제를 해주어야 함

- 메모리 해제를 하지 않으면 메모리 내의 프로세스 무게가 더해져 언젠가는 오류가 발생함

- 메모리 누수(Memory Leak) 방지는 코어 개발자의 핵심 역량임

- 할당한 메모리를 해제한 뒤에 다시 할당받아 사용한 경우 동일한 메모리 주소를 할당받을 확률이 높음

#include <stdio.h>
#include <stdlib.h>

int main(void){
    int *a = malloc(sizeof(int));
    printf("%d\n", a);
    free(a);
    a = malloc(sizeof(int));
    printf("%d\n", a);
    free(a);
    system("pause");
    return 0;
}

 

동적으로 문자열 처리하기

- 일괄적인 범위의 메모리를 모두 특정한 값으로 설정하기 위해서는 memset( )을 사용함

- memset(포인터, 값, 크기);

- 한 바이트 씩 값을 저장하므로 문자열 배열의 처리 방식과 흡사함

- 따라서 memset( ) 함수는 <string.h> 라이브러리에 선언되어 있음

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void){
    char *a = malloc(100);
    memset(a, 'A', 100); // 65라는 아스키 코드로 100개의 만큼 채움
    for (int i = 0; i < 100; i++) {
        printf("%c", a[i]);
    }
    system("pause");
    return 0;
}

 

* 동적 메모리 할당의 다양한 예제

#include <stdio.h>
#include <stdlib.h>

int main(void){
    int **p = (int**)malloc(sizeof(int*) * 3); // 메모리 할당을 통해 행을 만들어줌
    for (int i = 0; i < 3; i++) {
        *(p + i) = (int*)malloc(sizeof(int) * 3); // 3 x 3의 2차원 배열
    }
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            *(*(p + i) + j) = i * 3 + j;
        }
    }
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", *(*(p + i) + j));
        }
        printf("\n");
    }
    system("pause");
    return 0;
}

 

 

- 동적 메모리 할당을 이용해 프로그램이 실행 중인 도중에 메모리 공간을 배정받을 수 있음

- 동적으로 할당받은 프로그램은 반드시 명시적으로 free( ) 함수를 이용해 할당 해제를 해야만 함

'C언어' 카테고리의 다른 글

구조체  (0) 2020.12.08
함수 포인터  (0) 2020.12.08
다차원 배열과 포인터 배열  (0) 2020.12.07
컴퓨터가 변수를 처리하는 방법  (0) 2020.12.07
문자열  (0) 2020.12.05
Posted by khon98
,

2차원 배열의 필요성

- 2차원 배열은 굉장히 많은 목적으로 사용됨

- 행렬 데이터를 표현할 때, 그래프 알고리즘을 처리할 때, 다수의 실생활 데이터를 처리할 때 등

- 흔히 우리가 보는 표 구조가 2차원 배열과 흡사함

 

이름        영어 성정       수학 성적       국어 성적

가나다          85                 97                 79

라마바        100                 89                98

사아자         99                  77                99

차카타         89                 70                78

파하            95                 98                 98

 

2차원 배열의 초기화

- 2차원 배열은 1차원 배열이 중첩되었다는 의미로 [](대괄호)를 두 번 연속하여 사용

- 초기화하고 싶은 값이 있다면 괄호를 두 번씩 중첩해서 사용하는 방식으로 초기화가 가능

 

자료형 배열 이름 [행] [열] = {{값, 값, 값, ...}, {값, 값, 값, ...}, ...}

int a[10][10];

 

- 2차원 배열 또한 기본적으로 0 인덱스부터 시작

A[0(행)][0(열)]  A[0][1]  A[0][2]

A[1][0]  A[1][1]  A[1][2]

A[2][0]  A[2][1]  A[2][2]

A[3][0]  A[3][1]  A[3][2]

A[4][0]  A[4][1]  A[4][2]

 

* 2차원 배열은 2중 for문과 함께 많이 사용됨

#include <stdio.h>
#include <stdlib.h>

int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

int main(void){
    int i, j;
    for (i = 0; i < 3; i++){
        for (j = 0; j < 3; j++) {
            printf("%d", a[i][j]);
        }
        printf("\n");
    }
    system("pause");
    return 0;
}

 

다차원 배열

- 2차원 배열 이상의 다차원 배열 또한 사용할 수 있음

- 컴퓨터는 기본적으로 화면에 2차원 형태만 출력할 수 있음

 

* 3차원 배열 다루기

#include <stdio.h>
#include <stdlib.h>

int a[2][3][3] = { { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } },
                   { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } } };

int main(void){
    int i, j, k;
    for (i = 0; i < 2; i++){
        for (j = 0; j < 3; j++) {
            for (k = 0; k < 3; k++) {
                printf("%d ", a[i][j][k]);
            }
            printf("\n");
        }
        printf("\n");
    }
    system("pause");
    return 0;
}

 

포인터 배열의 구조 분석

- 배열은 포인터와 동일한 방식으로 동작함

- 배열의 이름은 배열의 원소의 첫 번째 주소가 됨

- 유일한 차이점이라고 하면 포인터는 변수이며 배열의 이름은 상수

 

* 배열의 이름이 변수인지 상수인지 확인해보기

#include <stdio.h>
#include <stdlib.h>

int main(void){
    int a = 10;
    int b[10];
    b = &a; // 배열 이름 자체는 상수이기 때문에 다른 주소 값으로 넣어줄 수 없음
    system("pause");
    return 0;
}

 

* 포인터를 배열처럼 사용하기

#include <stdio.h>
#include <stdlib.h>

int main(void){
    int a[5] = { 1, 2, 3, 4, 5 };
    int *b = &a;
    printf("%d\n", b[2]);
    system("pause");
    return 0;
}

 

* 배열의 이름은 배열의 첫 번째 원소의 주소라는 것을 기억하는 게 중요

#include <stdio.h>
#include <stdlib.h>

int main(void){
    int a[5] = { 1, 2, 3, 4, 5 };
    int *b = &a[0];
    printf("%d\n", b[2]);
    system("pause");
    return 0;
}

 

포인터 배열의 구조 분석

1.

- 포인터는 연산을 통해 자료형의 크기만큼 이동함

- 따라서 정수(int) 형 포인터는 4바이트(Bytes)씩 이동함

#include <stdio.h>
#include <stdlib.h>

int main(void){
    int a[5] = { 1, 2, 3, 4, 5 };
    int i;
    for (i = 0; i < 5; i++) {
        printf("%d", a[i]);
    }
    system("pause");
    return 0;
}

 

* 크기가 10인 double형(각각의 원소는 8바이트) 배열을 선언했을 때 배열의 시작 주소가 X(마지막 원소까지 9칸을 뛰어야 함)라고 한다

이때 배열의 마지막 원소의 주소는 몇인가 (8 x 9를 해서 72만큼 시작 주소에서 떨어져 있는 거니까 정답은 x + 72라고 할 수 있음)

#include <stdio.h>
#include <stdlib.h>

int main(void){
    double b[10];
    printf("%d %d\n", b, b + 9);
    return 0;
}

 

* 배열을 포인터처럼 사용해 각 원소에 접근할 수도 있음

#include <stdio.h>
#include <stdlib.h>

int main(void){
    int a[5] = { 1, 2, 3, 4, 5 };
    int i;
    for (i = 0; i < 5; i++) {
        printf("%d", *(a + i));
    }
    system("pause");
    return 0;
}

 

* 다음 프로그램의 결과는? 1, 3, 5

#include <stdio.h>
#include <stdlib.h>

int main(void){
    int a[5] = { 1, 2, 3, 4, 5 };
    int *p = a;
    printf("%d\n", *(p++));
    printf("%d\n", *(++p));
    printf("%d\n", *(p + 2));
    system("pause");
    return 0;
}

 

* 2차원 배열 또한 포인터로 처리할 수 있음

#include <stdio.h>
#include <stdlib.h>

int main(void){
    int a[2][5] = { { 1, 2, 3, 4, 5 },
        { 6, 7, 8, 9, 10 } };
    int (*p)[5] = a[1];
    int i;
    for (i = 0; i < 5; i++) {
        printf("%d ", p[0][i]);
    }
    system("pause");
    return 0;
}

 

 

- 2차원 배열 이상을 표현할 수 있음

- C언어의 배열은 내부적으로 포인터와 동일하므로 포인터 연산으로 배열을 대체할 수 있음

'C언어' 카테고리의 다른 글

함수 포인터  (0) 2020.12.08
동적 메모리 할당  (0) 2020.12.08
컴퓨터가 변수를 처리하는 방법  (0) 2020.12.07
문자열  (0) 2020.12.05
문자  (0) 2020.12.04
Posted by khon98
,

프로그램 메모리 주소

- 컴퓨터에서 프로그램이 실행되기 위해서는 프로그램이 메모리에 적재(Load)되어야 함

- 당연히 프로그램의 크기를 충당할 수 있을 만큼의 메모리 공간이 있어야 함

- 일반적인 컴퓨터의 운영체제는 메모리 공간을 네 가지로 구분하여 관리함

 

코드 영역 - 소스코드

데이터 영역 - 전역 변수, 정적 변수

힙 영역 - 동적 할당 변수

스택 영역 - 지역 변수, 매개변수

 

전역 변수

- 전역 변수(Global Variable)란 프로그램의 어디서든 접근 가능한 변수

- main 함수가 실행되기도 전에 프로그램의 시작과 동시에 메모리에 할당됨

- 프로그램의 크기가 커질수록 전역 변수로 인해 프로그램이 복잡해질 수 있음

- 메모리의 데이터(Data) 영역에 적재됨

#include <stdio.h>
#include <stdlib.h>

int a = 5; // 전역 변수

void changeValue() {
    a = 10;
}

int main(void) {
    printf("%d\n", a);
    changeValue();
    printf("%d\n",a);
    system("pause");
    return 0;
}

 

지역 변수

- 지역 변수(Local Variable)란 프로그램에서 특정한 블록(Block)에서만 접근할 수 있는 변수를 말함

- 함수가 실행될 때마다 메모리에 할당되어 함수가 종료되면 메모리에서 해제됨

- 메모리의 스택(Stack) 영역에 기록됨

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int a = 7;
    if (1) {
        int a = 5;
    }
    printf("%d", a);
    system("pause");
    return <#expression#>;
}

 

정적 변수

- 정적 변수(Static Variable)란 특정한 블록에서만 접근할 수 있는 변수

- 프로그램이 실행될 때 메모리에 할당되어 프로그램이 종료되면 메모리에서 해제됨

- 메모리의 데이터(Data) 영역에 적재됨

#include <stdio.h>
#include <stdlib.h>

void proccess() {
    static int a = 5; // 변수 a가 메모리상에 적재됨
    a = a + 1; // process 함수를 불러올 때마다 a에 1을 더해 나감
    printf("%d\n", a); // 더해진 a값을 출력
}

int main(void) {
    proccess(); // 6
    proccess(); // 7
    proccess(); // 8
    system("pause");
    return 0;
}

 

레지스터 변수

- 레지스터 변수(Register Variable)란 메인 메모리 대신 CPU의 레지스터를 사용하는 변수

- 레지스터는 매우 한정되어 있으므로 실제로 레지스터에서 처리될지는 장담할 수 없음

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    register int a = 10, i; // 레지스터 변수로 int형 a를 만들어서 10값을 넣어주고, i 변수 추가
    for (i = 0; i < a; i++) { // i는 0부터 a까지 반복
        printf("%d ", i); // i 출력
    }
    system("pause");
    return 0;
}

 

 

함수의 매개변수가 처리될 때

- 함수를 호출할 때 함수에 필요한 데이터를 매개변수로 전달함

- 전달 방식은 <값에 의한 전달 방식>과 <참조에 의한 전달> 방식이 있음

- 값에 의한 전달 방식은 단지 값을 전달하므로 함수 내에서 변수가 새롭게 생성됨

- 참조에 의한 전달 방식은 주소를 전달하므로 원래의 변수 자체에 접근할 수 있음(비유하자면 전역 변수에 더 가까움)

 

값에 의한 전달 방식(ADD 함수)

- ADD 함수로 두 개의 값을 넣으면 새롭게 두 변수가 메모리 내에 할당되어 처리됨

- 따라서 원래 변수의 값에는 영향을 미치지 못함

#include <stdio.h>
#include <stdlib.h>

void add(int a, int b) {
    a = a + b;
} // 이 함수 안에서만 적용

int main(void) {
    int a = 7;
    add(a, 10);
    printf("%d\n", a);
    system("pause");
    return 0;
}

 

참조에 의한 전달 방식(ADD 함수)

- 참조에 의한 전달 방식은 함수의 매개변수로 값을 전달하는 것이 아니라 변수의 조소(포인터 값)를 전달함

- 이러한 방식을 이용하면 원래 변수의 값에 접근하여 값을 변경할 수 있음

- 참조에 의한 전달 방식은 단지 매개변수로 포인터(Pointer) 변수를 보낼 뿐 딱히 특별한 게 아님

#include <stdio.h>
#include <stdlib.h>

void add(int *a) {
    (*a) = (*a) + 10; // 주소값 자체에 10을 더함
}

int main(void) {
    int a = 7;
    add(&a); // a의 주소값을 불러옴
    printf("%d\n", a);
    system("pause");
    return 0;
}

 

 

- C언어에서는 전역 변수, 지역 변수 등의 다양한 종류의 변수가 사용됨

- 함수에 데이터를 전달하는 방법은 값을 전달하는 방식과 주소를 전달하는 방식 두 가지가 있음

 

'C언어' 카테고리의 다른 글

동적 메모리 할당  (0) 2020.12.08
다차원 배열과 포인터 배열  (0) 2020.12.07
문자열  (0) 2020.12.05
문자  (0) 2020.12.04
포인터  (0) 2020.12.04
Posted by khon98
,

문자열

C언어 2020. 12. 5. 13:34

문자열의 개념

- 문자열은 말 그대로 문자들의 배열

- 문자열은 컴퓨터 메모리 구조상에서 마지막에 널(null) 값을 포함

- 널(null) 값은 문자열의 끝을 알리는 목적으로 사용됨

- printf( ) 함수를 실행하면 컴퓨터는 내부적으로 null을 만날 때까지 출력함

 

null : 존재하지 않는다라는 뜻

 

0 1 2 3 4 5 6  7 8 9 10 11

H E L L O   W O R L D  \0(null값)

 

문자열과 포인터

- 문자열 형태로 포인터를 사용하면 포인터에 특정한 문자열의 주소를 넣게 됨

- 다음 코드는 "Hello World" 문자열을 읽기 전용으로 메모리 공간에 넣은 뒤에 그 위치를 처리함

- 이러한 문자열을 '문자열 리터럴'이라고 말함 이는 컴파일러가 알아서 메모리 주소를 결정함

 

#include<stdio.h>
#include<cstdlib>

int main(void) {
	char *a = "Hello World"; // 오류 발생
	printf("%s\n", a);
	system("pause");
	return 0;
}
#include<stdio.h>
#include<cstdlib>

int main(void) {
	const char *a = "Hello World";
	printf("%s\n", a);
	system("pause");
	return 0;
}

"const char *" 형식의 값을 사용하여 "char *" 형식의 엔터티를 초기화할 수 없습니다. 이 오류가 뜨면

char 앞에 const를 붙이면 됨

 

- 포인터로 문자열을 선언했다고 하더라도 기존의 배열처럼 처리할 수 있음

#include<stdio.h>
#include<cstdlib>

int main(void) {
	const char *a = "Hello World";
	printf("%c\n", a[1]);
	printf("%c\n", a[4]);
	printf("%c\n", a[8]);
	system("pause");
	return 0;
}

 

 

문자열 입출력 함수

- 문자열 입출력을 수행

- scanf( ) 함수는 공백을 만날 때까지 입력받지만 gets( ) 함수는 공백까지 포함하여 한 줄을 입력 받음

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	char a[100];
	gets(a); // 오류 발생
	printf("%s\n", a);
	system("pause");
	return 0;
}

- gets 함수는 버퍼의 크기를 벗어나도 입력을 받아버림

 

- C11 표준부터는 버퍼의 크기를 철저히 지키는 gets_s( ) 함수가 추가됨

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	char a[100];
	gets_s(a, sizeof(a));
	printf("%s\n", a);
	system("pause");
	return 0;
}

- gets_s( )를 이용하는 경우 범위를 넘으면 그 즉시 런타임(Runtime) 오류가 발생하게 됨

 

문자열 처리를 위한 다양한 함수

- C언어의 문자열처리와 관련해서는 기본적인 문자열 함수를 알고 있는 것이 좋음

- 나중에 C++을 이용하면 더욱 간편하고 다양한 함수를 사용할 수 있음

- C언어에서의 문자열 함수는 <string.h> 라이브러리에 포함되어 있음

 

strlen( ) - 문자열의 길이를 반환

strcmp( ) - 문자열 1이 문자열 2보다 사전적으로 앞에 있으면 -1, 뒤에 있으면 1을 반환

strcpy( ) - 문자열을 복사

strcat( ) - 문자열 1에 문자열 2를 더함

strstr( ) - 문자열 1에 문자열 2가 어떻게 포함되어 있는지를 반환

 

* strlen( )

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>
#include<string.h> // 없으면 strlen 오류 발생

int main(void) {
	char a[20] = "khon";
	printf("%d\n", strlen(a));
	system("pause");
	return 0;
}

 

* strcmp( )

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>
#include<string.h> // 없으면 strcmp 오류 발생

int main(void) {
	char a[20] = "khon";
	char b[20] = "khon98";
	printf("두 배열의 사전순 비교: %d\n", strcmp(a, b));
	system("pause");
	return 0;
}

 

* strcpy( )

- C언어에서는 기본적으로 'a = b'와 같은 간단한 방식으로는 문자열 복사가 안됨

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>
#include<string.h> // 없으면 strcpy 오류 발생

int main(void) {
	char a[20] = "My Name";
	char b[20] = "khon";
	strcpy(a, b);
	printf("복사된 문자열: %s", a);
	system("pause");
	return 0;
}

 

* strcat( )

- 뒤에 있는 문자열을 앞에 있는 문자열에 합침

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>
#include<string.h> // 없으면 strcat 오류 발생

int main(void) {
	char a[30] = "My Name is "; // 합쳐지는 배열의 크기가 적지 않도록 해줘야함
	char b[20] = "khon";
	strcat(a, b);
	printf("합쳐진 결과 문자열: %s\n", a);
	system("pause");
	return 0;
}

 

* strstr( )

- 긴 문자열에서 짧은 문자열을 찾아 그 위치를 반환함

- 짧은 문자열을 찾은 주소 값 자체를 반환하므로 단순히 출력하도록 하면 찾은 이후 모든 문자열이 반환됨

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>
#include<string.h> // 없으면 strstr 오류 발생

int main(void) {
	char a[30] = "I like you ";
	char b[20] = "like";
	printf("찾은 문자열: %s\n", strstr(a, b));
	system("pause");
	return 0;
}

 

 

- C언어에서 문자열은 배열이므로 포인터 형태로 사용할 수 있음

- C언어에서 문자열 비교, 연산, 탐색 등의 알고리즘의 사용 방법은 각각 함수 형태로 제공됨

'C언어' 카테고리의 다른 글

다차원 배열과 포인터 배열  (0) 2020.12.07
컴퓨터가 변수를 처리하는 방법  (0) 2020.12.07
문자  (0) 2020.12.04
포인터  (0) 2020.12.04
배열  (0) 2020.12.04
Posted by khon98
,

문자

C언어 2020. 12. 4. 17:55

아스키코드

1.

- C 프로그램의 문자는 아스키코드(Ascii Code)를 따름

- 아스키코드는 0~127중의 1바이트로 구성되며 주요 문자를 출력하도록 해줌

 

0 48

A 65

a 97

 

2.

- 캐릭터형(char) 자체에 숫자를 넣어서 처리할 수 있음

- 문자 입출력에서 형식 지정자로 %c를 사용

#include<stdio.h>
#include<cstdlib>

int main(void) {
	char a = 65;
	printf("%c\n", a);
	system("pause");
	return 0;
}

 

 

문자 입출력 함수

- 이러한 문자는 getchar( )를 이용해서 입력을 받는 방식을 이용할 수 있음

- getchar( )는 단 하나의 문자를 입력 받음

#include<stdio.h>
#include<cstdlib>

int main(void) {
	char a = getchar();
	printf("%c\n", a);
	system("pause");
	return 0;
}

 

 

문자

- 문자열을 처리할 때 버퍼의 개념이 많이 사용됨

- 버퍼(Buffer)란 임시적으로 특정한 데이터를 저장하기 위한 목적으로 사용됨

- C 프로그램은 기본적으로 사용자가 의도하지 않아도 자동으로 버퍼를 이용해 입출력을 처리함

 

문자와 버퍼

- 입력 버퍼로 인해 흔히 발생하는 오류

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main()
{
	int a;
	char c;
	scanf("%d", &a);
	printf("%d\n", a);
	scanf("%c", &c);
	printf("%c\n", c);
	system("pause");
	return 0;
}

 

- 남아 있는 입력 버퍼를 항상 지울 수 있음

EOF(End Of File) - 파일의 끝

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main()
{
	int a; char c;
	scanf("%d", &a);
	printf("%d\n", a);
	int temp;

	// 한 자씩 받아서 파일의 끝이거나 개행 문자를 만나면 입력을 멈추므로 항상 입력 버퍼를 비워야 함
	while ((temp = getchar()) != EOF && temp != '\n') {}
	scanf("%c", &c);
	printf("%c\n", c);
	system("pause");
	return 0;
}

 

- C언어에서는 문자 입출력의 내부에는 버퍼(Buffer)가 존재함

'C언어' 카테고리의 다른 글

컴퓨터가 변수를 처리하는 방법  (0) 2020.12.07
문자열  (0) 2020.12.05
포인터  (0) 2020.12.04
배열  (0) 2020.12.04
함수  (0) 2020.12.04
Posted by khon98
,

포인터

C언어 2020. 12. 4. 17:07

포인터의 개념

- 지금까지의 변수는 그 자체로 자신의 자료형에 맞는 값을 저장함

- 포인터(Pointer) 변수는 특이한 변수로, 메모리 주소를 저장함

- 포인터는 *표시를 이용해 나타낼 수 있음

- 포인터는 특정한 변수 자체가 존재하는 메모리 주소의 값을 가짐

- 따라서 다음 예제에서는 기존에 a를 이용해서도 5라는 값을 찾을 수 있지만 포인터 변수인 b를 이용해서도 5라는 값을 찾을 수 있음

- int *b = &a;처럼 '선언할 때' 쓰는 *는 포인터 변수임을 알려주기 위한 목적을 가짐

- 이후에 *b라고 쓰게 되면, 이것은 포인터 변수 b가 가리키는 주소의 값을 의미

- 다시 말해서 아래 예제에서 5라는 값 자체가 됨

 

int a = 5;                    int *b = &a;

5                        <    0xAFB03954

주소 : 0xAFB03954        0xCA29839F

 

포인터 관련 연산자

- 주소 연산자(&) : 변수 앞에 붙어서 변수의 메모리 시작 주소 값을 구함

- 포인터(*) : 포인터 변수를 선언할 때 사용함

- 간접 참조 연산자(*) : 선언된 포인터 변수가 가리키는 변수를 구함

 

* 선언할 때와 선언 이후의 포인터 연산자(*)는 생긴 것만 같지 기능은 다름

#include<stdio.h>
#include<cstdlib>

int main(void) {
	int a = 5;
	int* b = &a; // 포인터 변수 b가 변수 a를 가리킴
	printf("%d\n", *b);
	system("pause");
	return 0;
}

- 실제로 int a = 5; 와 같이 변수를 할당하면 메모리 주소상에서는 다음과 같이 기록됨

- int형은 4바이트를 차지하므로 메모리 주소를 1바이트씩 표현할 때 4칸을 차지함

 

* 배열 각 원소의 주소 값 출력

#include<stdio.h>
#include<cstdlib>

int main(void) {
	int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int i;
	for (i = 0; i < 10; i++) {
		printf("%d\n", &a[i]);
	}
	system("pause");
	return 0;
}

 

 

포인터의 강력한 기능

1.

- 포인터는 컴퓨터 시스템의 특정한 메모리에 바로 접근할 수 있음

- 따라서 기존에 존재하던 중요한 메모리 영역에 접근하지 않도록 해야 함

- 다음과 같은 코드는 굉장히 위험한 코드임

 

int *a = 0x33484735;

*a = 0;

 

* 포인터는 다중으로 사용할 수 있음

#include<stdio.h>
#include<cstdlib>

int main(void) {
	int a = 5;
	int *b = &a;
	int **c = &b;
	printf("%d\n", **c);
	system("pause");
	return 0;
}

 

2.

- 배열과 포인터는 사실 내부적으로 거의 동일함

- 배열을 선언한 이후에는 그 이름 자체를 포인터 변수처럼 쓸 수 있음

#include<stdio.h>
#include<cstdlib>

int main(void) {
	int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int *b = a;
	printf("%d\n", b[2]);
	system("pause");
	return 0;
}

 

 

- 포인터는 특정한 변수가 메모리 상에 존재하는 위치 주소를 저장함

- 포인터는 특정한 메모리 주소에 바로 접근할 수 있으므로 조심스럽게 사용해야 함

'C언어' 카테고리의 다른 글

문자열  (0) 2020.12.05
문자  (0) 2020.12.04
배열  (0) 2020.12.04
함수  (0) 2020.12.04
반복문  (0) 2020.12.04
Posted by khon98
,

배열

C언어 2020. 12. 4. 14:25

배열을 사용하는 이유

- 3개의 숫자가 있을 때 가정 큰 숫자를 구하는 프로그램을 작성

- 기본적으로 변수의 이름을 a, b, c로 설정하면 된다는 것을 예상할 수 있음

- 비효율적이긴 하지만 변수 100개를 만들어서 선언할 수는 있음

- 하지만 숫자가 10000000개라면 이 때는 일일이 변수를 만들어서 처리할 수 없음

- 동일한 자료형을 여러 개 담는 기술이 바로 배열

- 배열을 사용하면 동일한 성격의 데이터를 다수 표현할 수 있음

 

인덱스 0 1 2 3 4 5 6 7 8 9

데이터 6 5 4 3 9 8 0 1 2 7

 

배열의 선언과 초기화

자료형 배열명[배열의 크기] = {초기화 값};

                                       초기화 값은 없을 수도 있음

 

* 배열에선 기본적으로 특정한 데이터에 접근하고자 할 때 중괄호를 넣어주고 중괄호 안에는 인덱스가 들어감

이 인덱스에 해당하는 원소에 접근하겠다는 뜻

만약에 차례대로 a배열에 0 1 2가 들어가 있을 때 a배열에 인덱스 2는 값이 2가 됨

 

* 배열을 만들고 배열을 초기화 한 이후에 각각의 원소에 접근하는 방법

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	int a[10] = { 6, 5, 4, 3, 9, 8, 0, 1, 2, 7 };
	int i;
	for (i = 0; i < 10; i++) {
		printf("%d ", a[i]);
	}
	system("pause");
	return 0;
}

- 전체 원소가 초기화되게 하고 싶으면 {0, }를 하면 됨

 

* 배열의 원소 중에서 최댓값 찾기

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>
#include<limits.h> // 다양한 자료형들의 최솟값이나 최댓값 즉 그 한 개에 해당하는 값들을 포함 하고 있음

int main(void) {
	int a[10] = { 6, 5, 4, 3, 9, 8, 0, 1, 2, 7 };
	int i, maxValue = INT_MIN; // INT_MIN은 상수
	for (i = 0; i < 10; i++) {
		if (maxValue < a[i]) maxValue = a[i];
	}
	printf("%d ", maxValue);
	system("pause");
	return 0;
}

INT_MIN

- INT_MIN은 최댓값을 구하기 위해 자주 사용되는 기능

- <limits.h> 헤더 파일에 정의가 되어 있는 것으로 int형 범위의 최솟값을 반환함(약 -20억)

- INT_MAX 또한 사용할 수 있음

 

 

문자열과 배열

1.

- 원시적인 C언어는 기본적으로 자체적인 문자열 자료형을 제공하지 않음

- 따라서 C언어에서는 문자(character)를 여러 개 묶어 놓는 형태로 문자열을 표현함

- C++에서는 이러한 불편함을 알고 있기 때문에 자체적으로 string 자료형을 제공함

 

2.

- C언어에서는 하나의 문자는 1바이트만을 담으므로 다음과 같이 문자의 배열을 사용

- 다시 말해 문자열은 사실 배열이라고 할 수 있음

 

char a[20] = "Hello World"

 

3.

- 기본적으로 문자열을 선언할 때는 문자열의 크기보다 배열의 크기가 크도록 해야 함

- 문자열을 입력받을 때 및 출력할 때는 %s라는 형식 지정자를 사용함

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	char a[20];
	scanf("%s", &a);
	printf("%s\n", a);
	system("pause");
	return 0;
}

 

4.

- C언어는 특정한 인덱스의 문자에 바로 접근할 수 있다는 장점이 있음

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	char a[20] = "Hello World";
	a[4] = ',';
	printf("%s\n", a);
	system("pause");
	return 0;
}

 

* 문자열에 포함된 l의 개수 출력하기

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	char a[] = "Hello World";
	int count = 0;
	for (int i = 0; i <= 10; i++) {
		if (a[i] == 'l') count++;
	}
	printf("%d\n", count);
	system("pause");
	return 0;
}

 

 

- 배열을 이용하면 많은 양의 데이터를 쉽게 처리할 수 있음

- C언어에서의 문자열은 내부적으로 문자의 배열임

'C언어' 카테고리의 다른 글

문자  (0) 2020.12.04
포인터  (0) 2020.12.04
함수  (0) 2020.12.04
반복문  (0) 2020.12.04
조건문  (0) 2020.12.03
Posted by khon98
,

함수

C언어 2020. 12. 4. 11:59

함수

1.

- 함수는 입력을 받아 처리한 뒤에 출력하는 구조를 가짐

 

입력 > 함수 > 출력

 

2.

- 함수는 특정한 기능에 대한 소스코드가 반복되는 것을 줄이도록 해줌

 

반환 자료형 함수명(매개변수) {

            // 수행될 명령어

            return 반환할 값;

}

 

3.

- 함수에서 매개변수와 반환할 값은 경우에 따라서 없을 수 있음

- 매개변수 및 반환할 값이 없을 때의 자료형은 void

 

반환 자료형 함수명(매개변수) {

           // 수행될 명령어

           return 반환할 값;

}

 

* 매개변수와 return 반환할 값은 없어도 되는 코드

 

* 말머리 붙이기

#include<stdio.h>
#include<cstdlib>

void dice(int input) {
	printf("khon이 던진 주사위: %d\n", input);
}

int main(void) {
	dice(3);
	dice(5);
	dice(1);
	system("pause");
	return 0;
}

 

* 더하기 함수 만들기

#include<stdio.h>
#include<cstdlib>

int add(int a, int b) { // 매개변수
	return a + b;
}

int main(void){
	printf("%d\n", add(10, 20));
	printf("%d\n", add(50, -20));
	printf("%d\n", add(70, 105));
	system("pause");
	return 0;
}

 

* 사칙연산 함수 만들기

#include<stdio.h>
#include<cstdlib>

void calculator(int a, int b) {
	printf("%d + %d = %d\n", a, b, a + b);
	printf("%d - %d = %d\n", a, b, a - b);
	printf("%d * %d = %d\n", a, b, a * b);
	printf("%d / %d = %d\n", a, b, a / b);
	printf("\n"); // 줄 바꿈
}

int main(void) {
	// 연산한걸 출력
	calculator(10, 3); 
	calculator(15, 2);
	calculator(18, 4); 
	system("pause");
	return 0;
}

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

 

재귀 함수

- 재귀 함수란 자기 자신을 포함하는 함수

- 기본적으로 자기 자신을 계속 불러냄

- 따라서 반드시 재귀 종료 조건이 필요함

 

* 재귀 함수를 이용한 팩토리얼

팩토리얼

- 자기 자신까지 모든 숫자를 곱한 결과

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

// 5! = 1 * 2 * 3 * 4 * 5 = 120
int factorial(int a) {
	if (a == 1) return 1; // a가 1일때 return 1을 해줌으로 무한 반복이 되지 않도록 막아줌
	else return a * factorial(a - 1); // a가 1이 아니라면 a를 곱하고 팩토리얼에 a - 1을 매개변수로 넣어줌
}

int main(void) {
	int n;
	printf("n 팩토리얼을 계산합니다. ");
	scanf("%d", &n);
	printf("%d\n", factorial(n));
	system("pause");
	return 0;
}

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

 

- C언어는 함수로 시작해서 함수로 끝나는 언어

- 재귀 함수는 반복적으로 자기 자신을 불러내므로 경우에 따라서 연산 횟수가 급격히 증가할 수 있음(무한루프 조심)

'C언어' 카테고리의 다른 글

포인터  (0) 2020.12.04
배열  (0) 2020.12.04
반복문  (0) 2020.12.04
조건문  (0) 2020.12.03
연산자  (0) 2020.12.02
Posted by khon98
,

반복문

C언어 2020. 12. 4. 10:28

for문

- for문 내부의 조건에 부합하면 계속해서 특정한 구문을 실행

- 반복문을 탈출하고자 하는 위치에 break 구문을 삽입

 

for (초기화; 조건; 반복 끝 명령어) {

             // 반복적으로 실행할 부분

}

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	for (int i = 0; i <= 100; i++) {
		printf("%d\n", i);
	}
	system("pause");
	return 0;
}

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

 

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

1부터 n까지의 합 출력하기

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	int n, sum = 0;
	printf("n을 입력하세요. ");
	scanf("%d", &n);
	for (int i = 0; i <= n; i++) {
		sum = sum + i;
	}
	printf("%d\n", sum);
	system("pause");
	return 0;
}

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

 

무한 루프

- 무한 루프(Infinite Loop)란 종료 조건 없이 한없이 반복되는 반복문을 의미

- 일부러 무한 루프를 발생시키는 경우도 있지만 일반적인 경우 개발자의 실수로 인해 발생

 

for (초기화; 조건; 반복 끝 명령어) {

             // 조건이 항상 참(True)인 경우 무한 루프 발생

}

 

* 이럴 경우 무한 루프

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	for (;;) {
		printf("Hello World\n");
	}
	system("pause");
	return 0;
}

모든 내용을 비우고 결과가 참인 경우

 

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	for (int i = 0; i <=100; i--) {
		printf("Hello World\n");
	}
	system("pause");
	return 0;
}

개발자의 실수로 인한 무한 루프

 

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

-1이 입력될 때까지 더하기

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	int sum = 0;
	for (; 1;) {
		int x;
		scanf("%d", &x);
		if (x == -1) break;
		sum += x;
	}
	printf("%d\n", sum);
	system("pause");
	return 0;
}

-1이 입력되면 입력했던 숫자들의 합을 알려줌

중간에 / 들어가면 입력이 안됨

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

 

While문

- While문의 조건에 부합하면 계속해서 특정한 구문을 실행함

- 반복문을 탈출하고자 하는 위치에 break 구문을 삽입

 

while (조건) {

             // 반복적으로 실행할 부분

}

 

* 특정 문자를 n번 출력하기

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	int n;
	char a; // 문자
	scanf("%d %c", &n, &a);
	while (n--) { 
		/* while문이 처음 실행 되면 n이 참 값인지 검사, 
		참이라면 밑에 코드가 진행, 
		다시 돌아오는 순간 1 감소, 
		감소된 n이 여전히 참이라면 코드 계속 진행,
		n이 거짓이 될때까지 n번 만큼 진행*/
		printf("%c", a); // n번 만큼 반복
	}
	system("pause");
	return 0;
}

 

* 특정 숫자의 구구단 출력하기

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<cstdlib>

int main(void) {
	int n;
	scanf("%d", &n);
	int i = 1;
	while (i <= 9) { 
		printf("%d * %d = %d\n", n, i, n * i);
		i++;
	}
	system("pause");
	return 0;
}

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

 

중첩된 반복문

- 중첩된 반복문이란 반복문 내부에 다른 반복문이 존재하는 형태의 반복문

- 반복문이 중첩될수록 연산 횟수는 제곱 형태로 늘어남

 

* 전체 구구단 출력(while문)

#include<stdio.h>
#include<cstdlib>

int main(void) {
	int i = 1;
	while (i <= 9) {
		int j = 1;
		while (j <= 9) {
			printf("%d * %d = %d\n", i, j, i * j);
			j++;
		}
		printf("\n");
		i++;
	}
	system("pause");
	return 0;
}

 

* 전체 구구단 출력하기(for문)

#include<stdio.h>
#include<cstdlib>

int main(void) {
	for (int i = 1; i <= 9; i++) {
		for (int j = 1; j <= 9; j++) {
			printf("%d * %d = %d\n", i, j, i * j);
		}
		printf("\n");
	}
	system("pause");
	return 0;
}

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

 

for문과 while문의 관계

- 모든 for문은 while문으로 변경할 수 있으며 모든 while문은 for문으로 변경할 수 있음

- C언어 소스코드가 최적화되면서 어셈블리어 단에서는 동일한 명령어로 동작하기 때문

'C언어' 카테고리의 다른 글

배열  (0) 2020.12.04
함수  (0) 2020.12.04
조건문  (0) 2020.12.03
연산자  (0) 2020.12.02
기본 입출력  (0) 2020.12.01
Posted by khon98
,