C에서는 다음 코드와 같이 배열에 문자열을 저장할 수 있다.

char str[14] = "Good morning!";
char str[] = "Good morning!";

"Good morning!"은 공백 포함 13자 이지만 배열을 선언할때 길이를 14로 설정해야 하고 배열의 길이를 생략해도 길이는 14로 결정된다. 문자열의 끝에는 '\0'이라는 특수문자(escape sequence)가 자동으로 삽입되기 때문이다. 따라서 char형 배열로 문자열을 선언할 경우 특수문자 '\0'이 저장될 공간까지 고려해야 한다. '\0'은 널(null)문자 라고 한다.

#include <stdio.h>

int main(void)
{
    char str[] = "Good morning!";
    printf("size of str array : %d \n", sizeof(str));
    printf("char Null print : %c\n",str[13]);
    printf("int Null print : %d\n",str[13]);
    return 0; 
}
/* output : 
size of str array : 14
char Null print : 
int Null print : 0
*/

위 코드와 같이 널문자를 문자열로 출력하면 공백이 출력되고, 정수형으로 출력하면 0이 출력된다. 널문자의 아스키 코드 값은 0임을 알 수 있다. 

int main(void)
{
    char nu = '\0';	// 널문자 저장
    char sp = ' ';	// 공백 저장
    printf("%d %d", nu, sp);	// output : 0 32
    return 0;
}

위 코드와 같이 널문자의 아스키코드 값은 0이고 공백문자의 아스키 코드값은 32이기 때문에 문자열로 출력했을때 같아 보일지라도 널문자와 공백 문자는 다른 값이다.

 

다음과 같이 서식문자 %s를 사용하여 scanf()함수를 이용해 문자열을 입력받을 수 있다.

#include <stdio.h>

int main(void)
{
    char str[50];
    int idx = 0;

    printf("문자열 입력 : ");
    scanf("%s", str);   // &연산자를 사용하지 않음
    printf("입력받은 문자열 : %s\n", str);

    printf("문자열 단위 출력 : ");
    while(str[idx] != '\0')
    {
        printf("%c", str[idx]);
        idx++;
    }
    printf("\n");
    return 0;
}

정수형과 같은 데이터를 저장하는 변수 앞에는 &연산자를 붙이지만, 문자열을 입력받는 배열의 이름 앞에는 &연산자를 붙이지 않는다. 

scanf()함수로 입력받은 문자열의 끝에도 널문자가 저장된다. C에서 표현하는 모든 문자열의 끝에는 널문자가 저장된다. 만약 다음 코드와 같이 널문자가 없으면 문자열이 아니다. 문자들을 저장한 배열일 뿐이다.

char arr[] = "{'h','e','l','l','o'};

문자열에서 끝에 널문자가 저장되는 것은 메모리상에서 문자열은 이진 데이터로 저장되어 있기 때문에 문자열의 시작과 끝을 구분해주기 위해서다. 0번 인덱스가 시작위치이고, 널문자가 끝나는 위치이다. 

scanf()함수에 공백을 포함한 문자열을 입력하게 되면 출력값은 공백 이전의 문자열만 출력되게 된다. scanf()함수는 공백을 기준으로 데이터를 구분짓기 때문에 "Hello World!"를 입력하면 "Hello", "World!"로 두개의 문자열이 입력된 것으로 인식한다.

 

#include <stdio.h>

int main(void)
{
    char str[50] = "Hello World!";
    printf("String: %s\n", str);

    str[5]='\0';
    printf("String: %s\n", str);

    str[3]='\0';
    printf("String: %s\n", str);
    return 0;
}
/* output :
String: Hello World!
String: Hello
String: Hel
*/

문자열 중간중간 널문자를 삽입되면 문자열 끝이 변경되어 변경된 끝을 기준으로 문자열이 출력된다.

 

'Language > C, C++' 카테고리의 다른 글

[C] 포인터와 배열  (0) 2020.12.17
[C] 포인터 변수  (0) 2020.12.16
[C] 1차원 배열(1)  (0) 2020.12.12
[C] 재귀함수  (0) 2020.12.10
[C] register 변수  (0) 2020.12.10

배열은 일반적인 변수와 다르게 여러 개의 값을 저장할 수 있다. 여러 개의 변수가 모여서 배열을 이룬다.

배열은 다음과 같이 선언할 수 있다.

int arr[4];

위 코드에는 배열을 이루는 요소의 자료형, 배열의 이름, 배열의 길이 이다. 따라서 위 코드의 의미는 'int형 변수 4개로 이뤄진 arr이라는 이름을 갖는 배열을 선언한다.' 이다. 이 형식을 갖추어 다양한 자료형과 다양한 길이의 배열을 선언할 수 있다.

 

배열은 다음과 같이 배열 이름 뒤의 대괄호([]) 안의 인덱스 값으로 접근할 수 있다. 인덱스 값은 0부터 시작한다. 배열의 길이가 3일 경우 인덱스 값은 2까지 있다.

#include <stdio.h>

int main(void)
{
    int arr[3];
    int sum = 0;

    arr[0] = 10, arr[1] = 30, arr[2] = 20;

    for(int i = 0; i < 3; i++)
        sum += arr[i];
    
    printf("배열 요소에 저장된 값들의 합 : %d\n", sum);
    return 0;
}

//output : 배열 요소에 저장된 값들의 합 : 60

위 코드는 크기가 3인 배열에 값들을 저장하여 배열의 값들의 합을 구하는 코드이다. 배열의 모든 요소는 반복문을 활용하여 순차적으로 접근 가능하다는 것을 알 수 있다.

 

배열도 기본 자료형 변수들과 마찬가지로 선언과 동시에 초기화하는 것이 가능하다.

다음 코드와 같이 중괄호 내에 초기화 할 값들을 나열하면 해당 값들이 순서대로 저장된다.

int arr[5] = {1,2,3,4,5};

위와 같이 초기화 리스트가 사용된 경우 배열의 길이정보를 생략할 수 있다. 

int arr[] = {1,2,3,4,5};

위 코드의 경우 배열의 길이정보 5가 자동으로 채워진다.

int arr[5] = {1,2};

위 코드의 경우 배열의 길이는 5이지만 초기화할 값은 2개밖에 존재하지 않는다. 위와 같은 경우 순차적으로 값을 채우고 채울 값이 존재하지 않는 요소들은 0으로 채워진다. 위의 경우 배열의 값은 1,2,0,0,0 과 같다.

 

#include <stdio.h>

int main(void)
{
    int arr1[5] = {1,2,3,4,5};
    int arr2[ ] = {1,2,3,4,5,6,7};
    int arr3[5] = {1,2};

    printf("arr1의 크기 : %d\n", sizeof(arr1));
    printf("arr2의 크기 : %d\n", sizeof(arr2));
    printf("arr3의 크기 : %d\n", sizeof(arr3));

    int ar1Len = sizeof(arr1) / sizeof(int);
    int ar2Len = sizeof(arr2) / sizeof(int);
    int ar3Len = sizeof(arr3) / sizeof(int);

    for(int i = 0; i<ar1Len; i++)
        printf("%d ", arr1[i]);
    printf("\n");
    for(int i = 0; i<ar2Len; i++)
        printf("%d ", arr2[i]);
    printf("\n");
    for(int i = 0; i<ar3Len; i++)
        printf("%d ", arr3[i]);
    printf("\n");

    return 0;
}
/* output : 
arr1의 크기 : 20
arr2의 크기 : 28
arr3의 크기 : 20
1 2 3 4 5       
1 2 3 4 5 6 7   
1 2 0 0 0
*/

sizeof로 배열의 크기를 반환하면 바이트 단위로 반환된다. 따라서 배열의 길이를 계산하려면 int 바이트수만큼 나눠줘야 한다.

'Language > C, C++' 카테고리의 다른 글

[C] 포인터 변수  (0) 2020.12.16
[C] 1차원 배열(2)  (0) 2020.12.14
[C] 재귀함수  (0) 2020.12.10
[C] register 변수  (0) 2020.12.10
[C] static 변수  (0) 2020.12.10

재귀함수는 함수 내에서 자기 자신을 다시 호출하는 함수를 의미한다. 함수가 실행하는 도중 자기 자신의 함수가 호출되면 자기 자신의 복사본을 하나 더 만들어서 복사본을 실행하게 된다. 

재귀함수는 한번 호출되면 계속 호출되는 문제가 있기 때문에 재귀를 탈출시키는 조건이 있어야 한다.

#include <stdio.h>

void Recursive(int num)
{
    if(num<=0)  // 재귀 탈출 조건
        return; // 재귀 탈출
    printf("Recursive call! %d \n",num);
    Recursive(num-1);
}

int main(void)
{
    Recursive(3);
    return 0;
}
/* output:
Recursive call! 3
Recursive call! 2
Recursive call! 1
*/

 

'Language > C, C++' 카테고리의 다른 글

[C] 1차원 배열(2)  (0) 2020.12.14
[C] 1차원 배열(1)  (0) 2020.12.12
[C] register 변수  (0) 2020.12.10
[C] static 변수  (0) 2020.12.10
[C] 전역변수  (0) 2020.12.09

지역변수에 static 선언을 추가하면 전역변수의 성격을 지니는 변수가 된다. static변수의 특성은 다음과 같다. 

1. 선언된 함수 내에서만 접근이 가능하다.(지역변수 특성)

2. 한 번 초기화 되면 프로그램 종료 시까지 메모리 공간에 존재한다.(전역변수 특성)

#include <stdio.h>

void Func(void)
{
    static int num1 = 0;
    int num2 = 0;
    num1++, num2++;
    printf("static %d, local : %d\n", num1, num2);
}

int main(void)
{
    for(int i = 0; i<3; i++)
        Func();
    return 0;
}
/*
output:
static 1, local : 1
static 2, local : 1
static 3, local : 1
*/

static 변수는 전역변수와 동일한 시기에 할당되고 소멸된다. 변수의 접근 범위를 선언된 함수 내에서만 가능하도록 제한해주는 것이다. 

'Language > C, C++' 카테고리의 다른 글

[C] 재귀함수  (0) 2020.12.10
[C] register 변수  (0) 2020.12.10
[C] 전역변수  (0) 2020.12.09
[C] 지역변수  (0) 2020.12.09
[C] 함수(function)  (0) 2020.12.08

전역변수는 어디서든 접근이 가능한 변수로 프로그램이 처음 실행되면 메모리 공간에 할당되어 프로그램이 종료될 때 까지 메모리 공간에 남아있는 변수이다.

 

#include <stdio.h>

void Add(int val);
int num;

int main(void)
{
    printf("num : %d\n", num);
    Add(3);
    printf("num : %d\n", num);
    num++;
    printf("num : %d\n", num);
    return 0;
}

void Add(int val)
{
    num += val;
}

위 코드와 같이 전역변수는 어떠한 중괄호에도 포함되지 않는다.

전역변수는 별도의 값으로 초기화하지 않으면 0으로 초기화되고, 프로그램의 전체 영역 어디서든 접근이 가능하다.

 

만약 전역변수와 동일한 이름의 지역변수가 선언되면 해당 지역 내에서는 전역변수가 아닌 지역변수로 접근한다. 

'Language > C, C++' 카테고리의 다른 글

[C] register 변수  (0) 2020.12.10
[C] static 변수  (0) 2020.12.10
[C] 지역변수  (0) 2020.12.09
[C] 함수(function)  (0) 2020.12.08
[C] goto  (0) 2020.12.08

해결해야 할 문제의 규모가 크거나 복잡할 때 main 이라는 하나의 함수에서 모두 해결하는 것보다 문제 해결에 필요한 기능들을 분석하고 분석 결과를 바탕으로 작은 함수들로 나누어서 해결하는것이 쉽고, 효율적이다.

 

자주 사용하는  printf() 같은 경우도 인자를 콘솔에 출력하는 일종의 함수이다.

 

함수는 전달인자의 유무와 반환 값의 유무에 따라 4개의 형태로 나눌 수 있다. 

전달인자와 반환값이 모두 있는 경우, 전달인자만 있고 반환값은 없는 경우, 전달인자가 없고 반환값만 있는 경우, 전달인자와 반환값이 모두 없는 경우로 총 4가지가 있다.

 

전달인자와 반환값이 모두 있는 경우

두 수의 덧셈 기능을 하는 함수로 예를 들면 전달인자는 int형 정수 두 개 이고, 덧셈 결과는 반환이 되고, 반환형도 int 형이다. 함수의 이름은 Add로 한다.

함수 호출 시 전달 되는 인자를 매개변수라 한다. 

함수를 정의하고 호출하는 코드는 다음과 같다.

#include <stdio.h>

int Add(int num1, int num2) // 반환형 함수이름(매개변수1, 매개변수2)
{
    return num1 + num2;     // 값 반환
}

int main(void)
{
    int result = Add(3,5);
    printf("Add Result : %d\n", result);
    return 0;
}
// output : Add Result : 8

int result = Add(3,5); 를 보면 함수의 호출문이 반환하는 값으로 대체된다는 것을 알 수 있다.

함수가 호출되면 호출된 함수의 영역으로 실행의 흐름이 이동한다.

 

전달인자나 반환값이 존재하지 않는 경우

void 라는 반환형은 반환하지 않는다 라는 뜻이 담겨 있다. void로 반환형이 지정된 함수의 몸체에는 return문이 없다.

매개변수의 선언 위치에 void가 들어가면 인자를 전달하지 않는다는 뜻이다.

반환형과 매개변수의 위치에 둘다 void를 사용하여 전달 인자와 반환값이 모두 존재하지 않는 함수도 정의할 수 있다.

#include <stdio.h>

int Add(int num1, int num2) // 인자 전달, 반환값
{
    return num1 + num2;
}

void ShowAddResult(int num) // 인자 전달
{
    printf("Add Result : %d", num);
}

int ReadNum(void)   // 반환값
{
    int num;
    scanf("%d", &num);
    return num;
}

void HowToUseThisProg(void)
{
    printf("If you input two number, print add result.\ninput two number.\n");
}

int main(void)
{
    int result, num1, num2;
    HowToUseThisProg();
    num1 = ReadNum();
    num2 = ReadNum();
    result = Add(num1,num2);
    ShowAddResult(result);
    return 0;
}

 

return

키워드 return은 두가지 의미가 있다. 값을 반환하며 함수를 빠져나간다는 의미지만, return문 뒤에 반환한 값이 없는 경우 값의 반환 없이 함수만 빠져나간다는 의미로 사용할 수 있다.

 

int Add(int num1, int num2);

int main(void)
{
	int result = Add(3,4);
    printf("%d",result);
    return 0;
}

int Add(int num1, int num2)
{
	return num1+num2;
}

위 코드와 같이 함수의 선언을 먼저 하고 호출 된 후에 정의를 할 수도 있다. 함수의 선언에는 매개변수의 갯수와 자료형의 정보만 포함하면 된다. 따라서 다음과 같이 매개변수의 이름을 생략하여 함수를 선언할 수 있다.

int Add(int, int);

 

'Language > C, C++' 카테고리의 다른 글

[C] 전역변수  (0) 2020.12.09
[C] 지역변수  (0) 2020.12.09
[C] goto  (0) 2020.12.08
[C] switch  (0) 2020.12.08
[C] continue  (0) 2020.12.05

goto는 프로그램의 흐름을 원하는 위치로 이동시킬 때 사용하는 키워드이다. goto는 프로그램의 자연스러운 흐름을 방해한다는 이유와, goto를 사용했을 때의 이점이 크지 않기 때문에 goto의 사용에 대한 인식은 부정적이다.

 

goto 키워드로 레이블을 지정하면 지정한 위치로 코드의 흐름을 이동시킨다.

#include <stdio.h>

int main(void)
{
    int num;
    printf("input number : ");
    scanf("%d", &num);

    if(num==1)
        goto ONE;
    else if(num==2)
        goto TWO;
    else
        goto OTHER;
    
ONE:
    printf("input 1\n");
    goto END;
TWO:
    printf("input 2\n");
    goto END;
OTHER:
    printf("input other num\n");
    goto END;

END:
    return 0;
}

위 코드와 같이 레이블은 실행하는 코드가 아닌 위치를 표시하는 역할로 사용되기 때문에 왼쪽 정렬시켜 구분하기 쉽게 한다.

'Language > C, C++' 카테고리의 다른 글

[C] 지역변수  (0) 2020.12.09
[C] 함수(function)  (0) 2020.12.08
[C] switch  (0) 2020.12.08
[C] continue  (0) 2020.12.05
[C] break  (0) 2020.12.05

switch문은 if~else 문과 비슷한 역활을 한다. switch 문은 다음과 같은 형태로 구성된다.

switch(n)
{
case 1:
	...
case 2:
	...
...
case n:
	...
default:
}

n은 switch문으로 전달되는 인자로 정수형 변수여야 한다. 전달되는 n 값에 따라 실행할 영역이 결정된다. n의 값이 2면 case 2의 영역을 실행하게 된다. n의 값에 일치하는 case 영역이 없을 경우 default 영역을 실행한다.

 

#include <stdio.h>

int main(void)
{
    int num;
    printf("Input 1~3 number : ");
    scanf("%d", &num);

    switch (num)
    {
    case 1:
        printf("input 1\n");
        break;
    case 2:
        printf("input 2\n");
        break;
    case 3:
        printf("imput 3\n");
        break;
    default:
        printf("I don't know! \n");
    }
    return 0;
}

switch문에서 위 코드와 같이 break문을 사용하면 조건을 만족할 경우 해당 영역을 실행 후 switch문을 탈출한다. break문을 사용하지 않는다면 조건에 맞는 영역과 그 아래 영역까지 모두 실행한다. 예를 들어 num 값이 2라면 case 2, 3, default 영역까지 모두 실행되는 것이다.

'Language > C, C++' 카테고리의 다른 글

[C] 함수(function)  (0) 2020.12.08
[C] goto  (0) 2020.12.08
[C] continue  (0) 2020.12.05
[C] break  (0) 2020.12.05
[C] 조건 연산자(삼항 연산자)  (0) 2020.12.05

continue 키워드는 반복문 안에 들어가며 cotinue 문장을 실행하게 되면 이 문장의 위치와 상관 없이 반복문의 조건 검사 위치로 이동한다. 

#include <stdio.h>

int main(void)
{
    for(int i = 0; i < 10; i++)
    {
        printf("%d\n",i);
        continue;
        printf("continue test\n");
    }
}

위 코드같은 경우 continue가 실행되면 반복 조건 검사 위치로 다시 돌아가기 때문에 continue test 라는 문자열은 한번도 출력되지 않는다. 

'Language > C, C++' 카테고리의 다른 글

[C] goto  (0) 2020.12.08
[C] switch  (0) 2020.12.08
[C] break  (0) 2020.12.05
[C] 조건 연산자(삼항 연산자)  (0) 2020.12.05
[C] 조건적 실행  (0) 2020.12.05

break는 반복문을 빠져 나올때 사용하는 키워드이다. 

다음 코드의 경우 무한 루프를 하는 반복문이지만 조건문에 break가 있기 때문에 조건을 만족시킨다면 반복문을 빠져 나올 수 있다. 1+2+3+...+n의 결과가 최초로 5000을 넘길때 n의 값을 구하는 코드이다. 

#include <stdio.h>

int main(void)
{
    int sum=0, num=0;
    
    while (1)
    {
        sum += num;
        if(sum > 5000)
            break;
        num++;
    }

    printf("sum = %d\nnum = %d\n", sum,num);
    return 0;
}

'Language > C, C++' 카테고리의 다른 글

[C] switch  (0) 2020.12.08
[C] continue  (0) 2020.12.05
[C] 조건 연산자(삼항 연산자)  (0) 2020.12.05
[C] 조건적 실행  (0) 2020.12.05
[C] for  (0) 2020.11.29

+ Recent posts