라인 입출력 함수

언어로그/C/C++ 2011. 3. 27. 21:07



라인단위로 입출력을 다루는 함수들에 대해서 알아보자.  널문자를 삽입해주는지 여부와 버퍼에서 개행문자를
제거하는지 여부에 주목하여 보자. 


scanf(const char *TEMPLATE, ...)
scanf 함수를 사용하여, 한 라인의 문자열을 읽을 수 있지만, 개행문자를 표준입력버퍼에 남겨놓는다.  
연이은 읽기 동작에 오동작을 초래할 수 있기때문에, 입력버퍼에서 개행문자를 제거하는 것을 잊지 말자!



char* fgets(char *S, int COUNT, FILE *STREAM)
지정한 입력버퍼에서 최대 COUNT-1 개의 문자를 읽되, 엔터를 칠때까지  배열  S에 저장하는 함수이다. 
배열의 공간이 충분하다면, 개행문자와 함께 널문자를 삽입한다. (엔터에 의해 종료) 
하지만 공간이 충분하지 않다면,  COUNT-1개의 문자와 널문자를 삽입하고 종료한다. (사이즈 제약의 의해 종료)



int fputs(const char *S, FILE *STREAM)
버퍼 S의 내용을 지정한 출력버퍼에 출력하는 함수로, 널문자를 개행문자로 변환하지 않는다.  




fgets와 fputs 보다는 덜 사용되지만 라인단위로 입출력을 할 수 있는 다음과 같은 함수가 있다. 
char* gets(char *S)
표준 입력버퍼에서 개행문자를 만날 때까지 읽는 함수로,  개행문자는 S에 저장하지 않지만, 입력퍼버에서는 제거한다




int puts(const char *S)
S 문자열을 표준출력버퍼에 출력하는 함수로 널문자를 만나면 개행문자로 변환하여 출력한다. 

'언어로그 > C/C++' 카테고리의 다른 글

음수의 표현  (0) 2011.06.13
문자열 조작함수 직접 구현하기  (2) 2011.04.29
라인 입출력 함수  (0) 2011.03.27
배열의 이해  (0) 2011.03.27
기억부류(Storage Class) / 변수  (0) 2011.03.27
전역변수와 지역변수  (0) 2011.03.27

배열의 이해

언어로그/C/C++ 2011. 3. 27. 20:53



1. 배열이란?
프로그램이 필요한 이유 중의 하나는 많은 양의 데이터를 처리하기 위해서이다.  
그중에서도 동일한 형태를 갖는 다수의 데이터를 다루기 위해 배열을 사용할 수 있다.  배열은 연속적인 메모리 공간에
할당된 동일한 데이터 타입을 갖는 변수들의 묶음이다.  

int array[3];

위와 같은 선언은 4바이트의 메모리가 연속적으로 3개가 할당되어 총 12바이트의 메모리가 생성된다. 
이 때 array 라는 배열의 식별자에는 할당된 메모리의 시작주소가 할당된다.  즉 포인터 상수이다. 
이렇게 할당된 메모리 공간에 배열의 식별자를 사용하여 접근할 수 있다. 


배열의 첨자를 사용하여 접근하는 방법
scanf("%d %d %d \n", &array[0], &array[1], &array[2] );


배열 식별자(포인터 상수)를 사용하여 접근하는 방법
scanf("%d %d %d \n", array,  array + 1, array + 2 );



2. 배열의 초기화
배열 또한 일반적인 변수와 동일한 초기화 규칙을 따른다. 지역변수로 선언된 배열은 기본으로 쓰레기값으로 초기화되며, 
전역변수로 선언된 경우는 0으로 초기화 된다.  배열의 선언과 초기화를 다음과 같이 할 수 있다. 

int array[3] = { 10 , 20, 30 };   // 명시적으로 요소의 개수와 각 초기값을 설정   
int array[] = { 10, 20 , 30 };     // 초기값의 수에 따라 요소의 수가 결정됨      
int array[3] = { 10 };           // 첫요소만 10으로, 나머지는 0 으로 초기화됨       
int array[3] = { 0 };           // 모든 요소를 0으로 초기화    

특히 마지막 문장은 다수의 요소를 갖는 배열을 초기화 할 때 유용한 구문이다. 
int array[100] = { 0 };

'언어로그 > C/C++' 카테고리의 다른 글

문자열 조작함수 직접 구현하기  (2) 2011.04.29
라인 입출력 함수  (0) 2011.03.27
배열의 이해  (0) 2011.03.27
기억부류(Storage Class) / 변수  (0) 2011.03.27
전역변수와 지역변수  (0) 2011.03.27
함수의 이해  (0) 2011.03.27

기억부류(Storage Class) / 변수

언어로그/C/C++ 2011. 3. 27. 20:40





데이터, 스택, 힙 영역
추상적인 분류이지만 프로그램을 위한 메모리 공간은 크게 데이터영역,  스택(Stack)영역,  힙(Heap)영역으로 나뉜다.
데이터 영역에는 전역(Global)변수와 정적(Static) 변수에게 할당되는 메모리 공간으로 프로그램 시작부터 끝나는 시점까지
존재하는 메모리 영역이다. 스택영역은 블럭 또는 함수 Scope 에 할당되는 메모리 공간이며,  제어흐름이 활성화 되었을 때
생성된다. 힙 영역은 프로그램이 유동적으로 사용할 수 있는 메모리 공간으로, 프로그래머가 해당 메모리를 필요한 만큼
사용하고 난 뒤 메모리를 해제해야 한다. 



레지스터 변수,  정적변수
변수의 타입 앞에 register 라는 키워드를 사용하여, 레지스터 변수를 선언할 수 있다.  레지스터 변수는 CPU의 메모리가 아닌
레지스터에 데이터를 저장하여,  데이터 접근 속도를 향상시킨다.  하지만  register 키워드를 사용했다고 무조건 레지스터에
데이터를 저장하는 것은 아닌다. 일반적으로 CPU에 존재하는 30여 가지의 레지스터 중 1~2 개의 레지스터가 남는데, 이 
레지스터들이 사용되고 있지 않을 경우에 사용되며, 그렇지 않을  경우 메모리에 할당된다. 

register int  i,  j;   // 레지스터에  i, j 생성을 요청.     

 
정적(Static) 변수는 전역변수와 같이 메모리의 데이터 영역에  생성이 된다.  지역 정적변수는 함수가 종료된 후에도 
그 값을 사용하고 싶을 경우에 쓰인다.  함수 내부에 선언된 지역정적 변수는 함수 호출시점에 최초로 생성이 되며, 
이후 메모리 데이터 영역에 프로그램 종료시점까지 유지가 된다.

void func()
{
    static int i = 0;    // 연이은 호출에도 처음 생성된 i가 사용됨.
    i++;
}
   

'언어로그 > C/C++' 카테고리의 다른 글

라인 입출력 함수  (0) 2011.03.27
배열의 이해  (0) 2011.03.27
기억부류(Storage Class) / 변수  (0) 2011.03.27
전역변수와 지역변수  (0) 2011.03.27
함수의 이해  (0) 2011.03.27
포인터의 이해  (0) 2011.03.11

전역변수와 지역변수

언어로그/C/C++ 2011. 3. 27. 20:15




1. 지역변수(local variable)
지역변수는 변수가 선언된 블럭(Scope) 내부에서만 유효한 변수이다. 지역변수는 제어흐름이 해당 블럭에
 진입되는 시점에 생성되고 , 블럭을 빠져나가는 순간 소멸되는데 흔히 자동변수라 하여 auto라는 키워드가 붙지만, 
디폴트로 생략할 수 있다. 또한 동일한 범위(Scope)  내 있는 코드에서만 접근할 수 있으며 생성 시, 의미없는 값이
들어가 있기 때문에 사용전에 반드시 초기화를 해야한다. 




2. 전역변수(global variable)
전역변수는 프로그램 실행타입 내내 유효한 변수이다. main함수가 호출되기 전에 생성되어, 프로그램 종료시 메모리가
회수된다.  프로그램 어떤 영역에서도 접근할 수 있는 특징이 있으며,  생성시 자동으로 0으로 초기화가 이루어진다.




3. 지역변수와 전역변수는 어떻게 사용해야하나?
전역변수는 어떤영역에서도 데이터에 접근할 수 있기 때문에 데이터 공유에 유용하다.  하지만 프로그램 실행타임
동안 계속 사용되기 때문에 과하게 사용하면 메모리에 낭비를 가져온다. 또한 전역변수에 대한 변경은 그 변수를
사용하는 모든 함수에 파급효과를 미쳐서 강한 결합(tight coupling)의 겨로가를 가져온다. 그렇기 때문에  프로그램을
용이하게 하는 범위에서 최소한으로 사용하고, 그 외의 경우는 지역변수를 사용하는 것이 좋다. 

 

'언어로그 > C/C++' 카테고리의 다른 글

배열의 이해  (0) 2011.03.27
기억부류(Storage Class) / 변수  (0) 2011.03.27
전역변수와 지역변수  (0) 2011.03.27
함수의 이해  (0) 2011.03.27
포인터의 이해  (0) 2011.03.11
매크로, 연산자  (3) 2011.03.10

함수의 이해

언어로그/C/C++ 2011. 3. 27. 20:10




함수가 필요한 이유?
중복된 작업을 함수로 분리하면,  한번 작성으로 여러번 사용할 수 있어서 효율적인 프로그램이 된다.
또한 큰 문제를 작은 문제들로 나누어 이해하기 쉬워지며, 수정사항이 발생하면 함수 부분만 수정하면
되기 때문에 유지보수도 용이해진다. 


 
함수의 원형(프로토타입)과 정의
C언어에서 함수는 원형(프로토타입)과 정의로  분리된다.  함수의 원형(프로토타입)은 보통 헤더파일이나
메인함수 이전에 선언이 되며,  컴파일러에게 이러 이러한 함수를 아래에 정의했으니까 메인함수 또는 특정함수에서 
이 함수를 사용해도 됨을 알려주는 것이다. 
함수의 정의는 실제적으로 함수가 하는 일을 기술하는 부분이다.  C언어에서는 함수의 시그니처로 함수의 이름만을
사용하기 때문에, 파라미터의 타입과 반환값의 타입이 달라도 동일한 이름의 함수를 사용 할 수  없다.


#include <stdio.h>
 
void swap(int , int);// 함수원형(프로토타입)   

int main() {
...
return 0;
}

void swap(int a, int b) {   // 함수의 정의         
...
}





Call By Value vs Call By Reference
함수 호출시 파라미터를 넘기는 방식에 따라  Call By Value 또는 Call By Reference 라고 구분한다.
함수 호출시 변수들의 데이터(값)가 복사되는데, 함수 내에서 이 복사된 변수에  대한 조작은 원본 변수에
에  아무런 영향을 미치지 못하는데 이러한 호출방식을 Call By Value라고 부른다.   
파라미터로 변수의 주소를 넘기면, 피호출자 쪽에서는 이 주소를 조작하여 원본 변수의 데이터를 변경 할
수 있다. 이러한 호출방식을 Call By Pointer 또는 Call By Reference 라고 부른다.

 
Call By Value
#include <stdio.h>

main() {
    int a = 1, b = 5;
    swap(a, b);// 변수의 값을 전달함 
}

void swap(int a, int b)  {// main함수의 a, b는 변경되지 않음    
    int temp = a;
    a = b;
    b = temp      
}


Call By Reference 
#include <stdio.h>

main()  {
    int a = 1, b = 5;
    swap(&a, &b);// 변수의 주소를 전달함    
}
 
void swap(int *a, int *b)  { // main함수의 a, b가 변경됨    
    int temp = *a;
    *a = *b;
    *b = temp;
}

'언어로그 > C/C++' 카테고리의 다른 글

기억부류(Storage Class) / 변수  (0) 2011.03.27
전역변수와 지역변수  (0) 2011.03.27
함수의 이해  (0) 2011.03.27
포인터의 이해  (0) 2011.03.11
매크로, 연산자  (3) 2011.03.10
표준입출력함수 getchar() / putchar()  (0) 2011.02.22