C

KNK Chap.2 (2.5~2.7)

Daryl 2022. 12. 3. 19:56

2.5 Reading Input

 

dweight.c 프로그램은 설정된 박스의 용적 중량만 계산할 수 있어서 큰 쓸모는 없다.

그래서 사용자가 직접 박스 사이즈를 설정할 수 있게 하는 프로그램을 만들 것이다.

입력을 얻기obtain 위해서는 scanf 함수를 쓰면 된다.

scanf 함수란? C 라이브러리에 속해 있으면서, printf 함수에 대응되는 함수이다.  

두 함수의 f 약어는 '형식화formatted*'를 의미한다. 

 

*formatted <컴퓨터/통신> 형식화된
(1) 프린터나 단말기 등의 주변 장치 또는 컴퓨터에서 만들어지는 규격화된 입출력 정보
(2) 여러 형태의 자기 기억 매체가 데이터의 구조를 받아들일 수 있도록 준비가 완료된 상태

 

즉, printf: print format = 포맷 형식을 출력하라 / scanf: scan format = 포맷 형식을 입력하라

 

둘다 데이터를 입력받거나 출력할 때 형식 문자열format string이 필요하다.

 

형식 문자는 서식 지정자format specifier 라고도 한다. 대표적 예는 아래와 같다.

%i: 정수형 → i는 정수integer의 약어이다. scanf에서 10진수, 16진수, 8진수 모두 입력할 수 있다.

%d: 정수형 → d는 십진수decimal의 약어이다. scanf에서 10진수 이외의 숫자를 입력해도 10진수로 인식한다.

%f: 소수형 → f는 부동 소수점floating point의 약어이다. 

부동 소수점이란, 하나의 실수를 가수부와 지수부로 나누어 표현하는 방식이다.

%c: 문자형 → c는 형식character의 약어이다.

%s: 문자열 → s는 문자열string의 약어이다.

 

형식 문자를 이용해 scanf 함수에선 입력값의 형식을, prinf 함수에선 출력값의 형식을 정해준다.

 

정수int 값을 사용자에게서 입력받기 위해서는 아래의 구문처럼 scanf 함수를 쓰면 된다.

scanf("%d", &i); /* integer를 읽고 i에 저장함 */

 %d 문자열이 있어야 scanf 함수가 정수값을 읽고 인식해서 받을 수 있다.

scanf는 그렇게 받은 정수값을 int형 변수인 i에 저장한다.

&은 주로 scanf에 쓰이는 기호이다. 궁금하다면 Section 11.2를 참고.

 

float형 변수를 받으려면 조금 다른 방식으로 scanf 함수를 호출call해야 한다. 예제를 보라.

scanf("%f", &x); /* 소수를 받아 x에 저장한다 */

%d의 경우와 마찬가지로,  %f 문자열이 있어야 scanf 함수가 소수값을 입력 받을 수 있다.

따라서 scanf는 그렇게 받은 정수값을 float형 변수일 것이 확실한 x에 저장한다.

x는 소수점을 포함할 수도 있지만 아닐 수도 있다.


Program: Computing the Dimentional Weight of a Box (Revisited)

 

이제 사용자가 박스의 사이즈를 입력할 수 있는 버전이다.

printf 함수의 호출이 scanf 함수의 호출보다 앞서 있는 것에 주목하라.

이 방식에서, 사용자는 언제 입력값을 적고, 어떤 입력값을 적는지 알 수 있을 것이다.

 

program name: dweight2.c

 

만약 사용자가 h:8, l:12, w:10 을 입력했을 경우, 이 프로그램의 결과값은 다음과 같다.

 

사용자에게 입력을 요구하는 메시지(프롬프트a prompt)는 보통 개행 문자로 끝나지 않는다.

왜냐하면 프롬프트와 사용자의 대답이 같은 줄에 있는게 좋대. 보기 좋다는 뜻인가...

 

dweight2.c 프로그램은 문제가 하나 있다. 사용자가 숫자 이외의 값을 입력하면 작동하지 않는다.

Section 3.2 에서 이 부분을 자세히 다룰 것이다.


2.6 Defining Names for Constants

 

프로그램에 상수가 포함되어 있으면, 상수에 이름을 지어주는게 좋다.

앞서 만든 두개의 프로그램은 166이라는 상수에 의존하는데, 이렇게 숫자로만 표현하면

이 상수에 담긴 의도는 나중에 누군가 프로그램 코드를 볼 때 제대로 읽히지 않을 수도 있다.

이럴때 매크로 정의macro definition라는 기능을 쓰면 상수에 이름을 붙일 수 있다.

매크로 정의를 쓸 때 상수에 소괄호를 두르면 좋다. 이유는 chap 14에서 확인.

#define INCHES_PER_POUND (166)

#define은 #include와 같은 전처리 지시자다. 그래서 코드 뒤에 세미콜론이 올 필요가 없다.

프로그램이 컴파일될 때,  전처리기는 각 매크로를 그것이 대신하는 값(지정된 값)으로 대체한다.

예를 들어 다음 구문을 보자.

weight = (volume + INCHES_PER_POUND - 1) / INCHES_PER_POUND;

이건 밑의 구문과 같다.

weight = (volume + 166 -1) / 166;

매크로의 값value은 표현식expression이 될 수 있다.

#define RECIPROCAL_OF_PI (1.0f / 3.14159f)

매크로 이름을 지을때 대문자를 사용하는 것은 전통과 비슷한 개념으로, 꼭 필수는 아니다.

그러나 지금까지도 다들 그렇게 쓰니까, 사용하기를 권장한다.


Program: Converting from Fahrenheit to Celsius

이 프로그램은 사용자가 화씨 온도를 입력하게 하고, 그걸 동일한 섭씨 온도로 출력한다.

여기서 16번째 코드

이 코드가 화씨 온도를 섭씨 온도로 변환한다.

FREEZING_PT가 32.0f 이고, SCALE_FACTOR가 (5.0f / 9.0f) 이기에, 컴파일러에게는 아래와 같다.

Celsius = (fahrenheit - 32.0f) * (5.0f / 9.0f);

여기서 SCALE_FACTOR의 값이 (5 / 9)가 아니라 (5.0f / 9.0f) 인 것이 중요하다.

C는 두 정수를 나누면 소수점 아래는 그냥 잘라먹어서, (5 / 9)로 하면 결과가 0이 된다.

 

그 뒤에 오는 17번째 코드인 printf 함수 호출은 섭씨 온도를 출력한다.

여기서 주목: 소수점 이하 한자리 표현에는 %.1f 가 사용됐다.

 


2.7 Identifiers

 

프로그램을 짤 때 변수, 함수, 매크로 등에 이름을 정해야 한다. 이 이름들을 식별자identifier라고 한다.

C에서는 식별자에 문자, 숫자, 언더바(밑줄 문자)를 쓴다. 하지만 숫자로 이름을 시작할 수는 없다.

(C99에서는 특정 유니버셜 문자명도 포함 가능하다. 궁금하면 section 25.4 참고.)

ilike3 / do_re_mi / _aww

이런 식으로 지으면 식별자 가능하고,

8seconds / h-e-y

이런 식으로 지으면 식별자 안 된다고.

 

게다가 C는 대소문자를 구분한다case-sensitive. 그러니까

job joB jOb Job jOB JOb JoB JOB

이 8개의 식별자가 완전히 다르다는 뜻이다.

모두 다른 용도로 사용할 수 있다. 눈은 아프겠지만.

 

보통 매크로에는 대문자, 식별자에는 소문자, 가독성이 필요할 땐 언더바를 쓴다.

my_name_is_daryl / time_is_running_out / guns_and_roses

이런 식으로.

근데 언더바 대신 대문자로 표기하는 사람들도 많다.

myNameIsDaryl / timeIsRunningOut / gunsAndRoses

이렇게. 물론 첫글자도 대문자로 쓸 때도 있긴 하다. 

일단 전자는 익숙한 전통, 후자는 요즘 흐름이라고 알아두면 된다.


Keywords

 

아래의 표에 명시된 키워드keyword들은 C 컴파일러가 중요하게 인식한다.

따라서 식별자로 쓰면 안된다.

auto enum restrict* unsigned
break hextern return void
case float short volatile
char for sighned while
const goto sizeof _Bool*
continue if static _Complex*
default inline* struct _Imaginary*
do int switch  
double long typedef  
less register union  

*C99 only

 

키워드는 보다시피 소문자로 작성되어야 한다. 함수의 이름도 마찬가지(ex. printf).

키워드나 함수를 대문자로 작성하면 C 컴파일러가 인식하지 못하니까 주의하자.

 

[!!!] 식별자에 대한 다른 제한도 주의하자.

어떤 컴파일러들은 asm과 같은 특정 식별자를 추가적 키워드로 본다.

표준 라이브러리standard library에 속한 식별자도 당연히 쓰면 안된다.

식별자가 언더바로 시작하는 경우도 안된다.

위 경우의 식별자를 쓰면 컴파일이나 링크할 때 에러 난다.