본문으로 바로가기

 

 

 

매크로 함수

 

속도는 향상되지만 실행 파일의 크기가 늘어나는 특징을 가진다.

 

문자열을 입력 받는 gets 함수

 

gets는 get string의 줄임 표현이다.

문자열을 입력 받는 표준 입력 함수이다.

Enter키를 입력할 때까지 입력한 모든 문자를 하나의 문자열로 본다.

gets 함수는 입력 버퍼에 Enter 키가 남지 않는다.

gets 함수로 입력 받은 문자열에는 Enter키를 입력한 위치에 NULL 문자 0이 추가된다.

 

char input_string[10];

gets(input_string);

 

 

gets 함수에서 사용자 키 입력 취소하기

 

표준 입력을 받는 중에 Ctrl + C 키를 입력하면 표준 입력이 취소되고 프로그램이 중지한다.

사용자가 정상적으로 입력을 완료하지 않은 상황에 대처할 수 있도록 코드를 구성해야 한다.

gets 함수의 반환값을 이용하여 사용자의 입력이 정상적으로 완료되었느지 확인 가능하다.

 

 

gets 함수에서 키 입력 횟수 제한하기

 

gets 함수는 자신이 예상한 길이 보다 더 긴 문자열이 입력되면 프로그램이 비정상적으로 종료된다.

gets 함수와 비슷한 함수를 직접 만들어 문제를 해결해야 한다. 

 

문자열을 정수로 변환해 사용하기

 

gets 함수로 입력 받는 숫자는 정수가 아닌 문자열로 인식된다.

gets 함수로 입력 받은 두 개의 문자열을 가지고 덧셈 연산을 하려면 문자열을 정수 값으로 변환해서 사용해야 한다.

 

int data = "12345"   //  데이터 타입이 다르기 때문에 대입될 수 없어 오류가 발생한다.

문자열 상수의 타입은 char *형이다. 문자열이라는 것은 문자의 집합체이긴 하지만 새로운 의미를 가진다.

정수는 4Byte, 실수는 8Byte처럼 크기가 고정되어 있지만 "abc"(4Byte), "abcd(5Byte)" 처럼 상수인데 크기가 다 다르다.

기계어 또는 프로그래밍 언어를 만드는 사람의 관점에서 이렇게 변하는 문자열을 다루기 힘들다. 따라서 포인터를 이용하여 문자열의 시작주소를 저장한다. 하지만 크기를 같이 명시할 수 없어 \0을 적어 주어 문자열의 끝을 확인한다.

 

숫자(0~9) 아스키 코드의 시작 값인 문자 '0'의 아스키코드 값을 각 숫자 형식 문자에서 빼면 정수 형태의 숫자로 변환된다.

 

'0' - '0' => 48 -48 => 0 : 문자 '0'이 숫자 0으로 변환되었다.

'1' - '0' => 49 -48 => 1 : 문자 '1'이 숫자 1으로 변환되었다.

 

atoi(23) = int형 정수 23으로 바꾸어 준다. atoi는 범용 함수이다. atoi는 생각보다 함수의 내용이 많다. 기본적으로 조건문, 반복문, 예외 처리등 복잡해서 모든 상황에서 atoi를 사용하는것은 비효율적이다. 그러나 만약 사용자가 어떤 값인지 모르겠지만 반드시 2자리 수로 나온다면 atoi를 사용하는 것 보다 직접 함수를 만들어서 사용하는 것이 더 좋다. 단, 몇자리 수로 나올지 모른다면 범용함수를 사용하는 것이 좋다.

 

문자열 형식의 숫자를 정수로 변환하기

 

숫자 형시을 문자열 정수로 만드는 좀 더 간단한 표현하기

 

자릿수에 곱할 숫자를 미리 구성하지 않고 문자열 순서대로 각 문자를 정수로 만들면서 10을 곱하면 동일한 결과  값을 얻을 수 있다.

 

 

길이 제한 없이 문자열 형식의 숫자를 정수로 변환하기

 

 

atoi 함수를 사용하여 문자열을 정수로 변환하기

 

ArrayToInteger 함수와 같은 기능을 제공하는 함수가 C 언어 표준 라이브러리에서 제공하는 함수이다.

atoi 함수를 사용하려면 stdlib.h 파일을 소스 파일에 include 해야한다.

 

만능 표준 입력 함수 scanf

 

표준 입력 함수 scanf는 scanf format의 줄임 표현이다.

다양한 키워드를 사용하여 문자, 문자열뿐만 아니라 정수, 실수까지 모두 입력 받을 수 있도록 형식화된 입력을 제공한다.

형식화된 입력 : 자신이 입력 받을 데이터의 종류 자릿수, 입력 형식을 저장하여 입력 할 수 있다.

 

 

printf : 어떻게 출력할것인지를 더 중요하게 생각한다.

scanf : 형식을 반드시 지켜주어야 한다. (포인터 사용)

 

scanf 함수에서 & 연산자를 사용하는 이유

 

scanf 함수는 포인터 기술을 사용하여 값을 반환한다.

scanf 함수에서 작업한 후 값을 되돌려 줄때 return문을 써야하지만 return문은 반환값 하나만 돌려줄 수 있다. scanf는 여러개를 입력받고 여러개의 입력값을 반환 해주어야 하기 때문에 포인터 문법을 사용해서 여러개의 변수를 한번에 주소를 넘겨 받고 반환값으로 한번에 다시 념겨 준다.

 

scanf 함수에서 입력된 값을 구분하는 방법

 

입력된 여러 개의 데이터를 Enter키와 공백(Space) 문자로 구분한다.

특별한 값 없이 Enter키나 공백 문자가 여러 개 입력되면 입력을 무시하고 실제 정보를 기준으로 입력 받는다.

 

scanf 함수로 문자열을 입력 받을 때 주의할 점

 

scanf 함수로 문자열을 입력 받을 때 중간에 공백이 들어가면 자신이 원하는 문자를 다 입력 받지 못하는 문제가 발생한다.

사용자가 입력하는 문자열에 공백이 포함된다면 gets 함수를 사용하는 것이 더 좋다.

 

scanf 함수를 사용하여 문자열 입력 받기

 

 

공백 문자로 구분해서 여러 개의 정보 입력 받기

 

scanf 함수로 정수 값을 입력 받을 때 8진법(%o), 10진법(%d), 16진법(%x)을 구별해서 사용 가능하다.

 

공백 문자로 구분해서 scanf 함수로 8, 10, 16진수 입력 받기

 

scanf 함수는 입력 형식 키워드와 자료형이 일치해야 한다.

 

printf 함수와 다르게 scanf 함수는 포인터를 사용하기 때문에 형식을 지정하는 키워드와 변수의 자료형이 맞지 않으면 프로그램에 오류가 발생한다.

 

scnaf 함수를 사용하여 나이 입력 받기(1)

 

 

scanf 함수를 사용할 때 잘못된 사용자 입력 처리하기

 

사용자의 실수로 "abc" 라고 입력하면 'Incorrect Age!!' 라는 메시지가 무한 반복되어 출력한다.

형식을 지정하는 키워드와 사용자가 입력한 형식이 맞지 않아 문제가 발생한다.

 

scanf는 항상 성공하는 함수가 아니고 잘못된 값을 받으면 실패하는 함수이다. 실패하면 0을 반환하고 실패한다.

표준입력장치는 입력버퍼에 한 바이트라도 있다면 사용자에게 입력받지 않고 입력버퍼에 있는것을 최대한 사용하려고 한다.

 

 

scanf 함수를 사용하여 나이 입력 받기(2)

 

 

배열 표기법과 포인터 표기법의 관계

 

 

배열에서 포인터 표기법을 사용하는 이유

 

배열에 캐스팅을 사용할 수 있다. 배열 항목의 크기와 상관없이 자유롭게 값을 수정 할 수 있다.

즉, 배열 표기법의 한계를 극복할 수 있다.

 

char data[8];

data[4] = 1;  //  무조건 상수값을 대입한다.

*(data + 4) = 1 // data[4] = 1; 과 같은 표현이다.

*(short *)(data + 4) = 1 // short 포인터형으로 캐스팅 할 수 있다.

 

배열 변수의 이름은 배열의 시작주소

 

char data[4];

char *p = &data[0] // 배열의 첫 번째 항목의 주소는 배열 전체의 시작 주소와 같다.

 

char *p = &data[0];

char *p = &*(data + 0);

char *p = &*data;  //  data에 가서 data의 번지를 구해라. data를 의미한다.

char *p = data;  //  주소를 얻는 & 연산자와 주소를 지정하는 * 연산자는 서로 반대 개념의 연산자이기 때문에 서로 상쇄된다.

 

포인터로 배열의 주소를 저장하여 사용하기

 

배열은 배열의 시작 주소를 기준으로 색인 작업된 요소의 위치를 계산한다.

배열의 같은 요소를 반복적으로 사용하는 경우 효율이 떨어진다.

 

char data[5] = {1, 2, 3, 4, 5};

int i, sum = 0, select =2;

for(i=0; i<10; i++) sum = sum + data[selet]; // sum

 

배열을 기준으로 포인터와 합체하기

 

char *p[5];  //  char *p1, *p2, *p3, *p4, *p5; 라고 선언한 것과 같다.

포인터가 5개 선언된 것이기 때문에 p 배열의 크기는 20바이트이다.

개별 포인터를 사용하려면 'p[0], p[1], p[2], p[3], p[4]'와 같이 사용한다.

각 포인터가 가리키는 대상의 값을 읽거나 쓰고 싶다면 '*p[0], *[1], *p[2], *p[3], *p[4]'라고 사용 가능하다.

[ ] 연산자가 *보다 우선순위가 높기 때문에 배열 문법이다. 

포인터도 변수이기 때문에 배열을 이용하여 그룹으로 묶을 수 있다.

p++;  //  p = p + 1;과 같으므로 주소가 5 증가한다.

 

char (*p)[5]

 

포인터가 하나 있는데 포인터의 변위가 5바이트이다. 여기서 변위는 이름을 뺀 나머지가 변위이다.

(*p)[2]=7이라고 사용하면 5바이트 크기의 메모리중 3번째 메모리를 가리킨다는 뜻이다!

아래의 그림으로 잘 표현되어 있다.