| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- 개발
- DART
- 에러
- 퇴근길
- 템플릿
- Linux
- FreeBSD
- 인프라
- VM
- 가상머신
- 오블완
- 휘발류
- 개발기
- ubuntu
- 티스토리챌린지
- C언어
- 연습문제
- Bloc
- 잡담
- Flutter
- 리눅스
- 일상
- K&R
- 오토바이
- virtualmachine
- node.js
- 주유소
- VMware
- 객체지향프로그래밍
- podman
- Today
- Total
그냥저냥
문제풀이 | The C Programming Language (K&R): Exercise 1-3 본문
문제풀이 | The C Programming Language (K&R): Exercise 1-3
sync86 2026. 4. 28. 23:44
책: The C Programming Language (K&R)
본문의 연습문제는 저작권 이슈로 그 내용을 직접적으로 언급하지 않습니다. 이점 양해 바랍니다.
Exercise 1-3은 책속에 예제로 제공된 화씨 -> 섭씨 변환 테이블에 타이틀을 추가하는 문제입니다.
#include <stdio.h>
/**
* print Fahrenheit-Celsius table
* for fahr = 0, 20, ..., 300
*/
int main(int argc, char** argv)
{
int fahr, celsius;
int lower, upper, step;
lower = 0; /* lower limit of temperature scale */
upper = 300; /* upper limit */
step = 20; /* step size */
fahr = lower;
while (fahr <= upper)
{
celsius = 5 * (fahr-32) / 9;
printf("%d\t%d\n", fahr, celsius);
fahr = fahr + step;
}
return 0;
}
위 예제는 책에서 발췌한 소스코드입니다.
우선 이전에 Exercise 1-1 예제에서 언급했던 제가 선호하는 스타일로 코드를 수정하였습니다.
이것이 C99 표준입니다.
$ cc exercise1-3.c
위 명령으로 실행하면 a.out 파일이 생성되는데 아래와 같은 결과를 확인할 수 있습니다.
$ ./a.out
0 -17
20 -6
40 4
60 15
80 26
100 37
120 48
140 60
160 71
180 82
200 93
220 104
240 115
260 126
280 137
300 148
여담.
방해될 수 있는 요소가 있는 여담이지만, 또 하나 제가 선호하는 스타일은 아래의 코드와 같습니다.
아래와 같은 형태를 좀 더 선호합니다.
#include <stdio.h>
/**
* print Fahrenheit-Celsius table
* for fahr = 0, 20, ..., 300
*/
int main(int argc, char** argv)
{
int lower = 0; /* lower limit of temperature scale */
int upper = 300; /* upper limit */
int step = 20; /* step size */
int fahr = lower;
int celsius = 0;
while (fahr <= upper)
{
celsius = 5 * (fahr-32) / 9;
printf("%d\t%d\n", fahr, celsius);
fahr = fahr + step;
}
return 0;
}
주석 (Comment)
가장 먼저 주석에 대해서 설명이 나옵니다.
주석은 코드에 추가로 설명을 다는 것인데, 이 주석은 컴파일할 때 코드로 변환되거나 그러지 않습니다.
때문에 주석에서는 일기를 작성하셔도 되고, 메모를 작성해도 됩니다.
주로 프로젝트에 투입되었다면, 혼자가 아닌 여러명이 작업을 할 경우가 많습니다.
이 때는 개인적인 이야기 보다 코드에서 전부 표현하기 어려운 내용을 위주로 기록하면 됩니다.
/* (내용) */
위 내용은 C언어에서 기본 주석 형태입니다.
// (내용)
간혹 위 형태의 주석을 보신적 있을텐데, 이것은 C++에서 지원하는 주석 형태입니다.
C표준으로 정식으로 포함된 것은 C99입니다.
- ISO/IEC 9899:1999 (C99)
C언어에서 위 주석을 보신적 있으시다면, 아마도 Visual C++에서 확률이 큽니다.
Visual C++ 프로젝트를 생성하고 기본은 C++ 컴파일러가 선택됩니다.
따라서 위 주석은 C++ 컴파일러에 의해 번역되어 에러가 없었을 겁니다.
책에서 주석은 아래와 같습니다.
/* print Fahrenheit-Celsius table
for fahr = 0, 20, ..., 300 */
다만, 주석의 형태를 제가 선호하는 형태로 아래와 같이 수정하였습니다.
/**
* print Fahrenheit-Celsius table
* for fahr = 0, 20, ..., 300
*/
변수 (Variable)
변수는 값을 일시적으로 기억할 때 사용하는 언어의 기능으로, 컴퓨터 메모리의 특정 영역을 의미합니다. 세부적으로는 복잡한 메모리 주소에 사람이 이해하기 쉬운 이름을 붙여놓은 것이죠.
변수를 다룰 때 프로그래머가 반드시 이해해야 할 두 가지 필수 개념은 값의 범위와 생존 범위입니다.
- 값의 범위
- 생존 범위
값의 범위
변수에서 값의 범위는 숫자가 어디서부터 어디까지인지를 정하는 것입니다. 단순히 1~5, 0~1000 같은 범위를 지정한다고 보면 됩니다. 하지만 컴퓨터 메모리는 무한하지 않기 때문에 언어에서는 이를 더 세부적인 타입으로 관리합니다.
- 정수: 자연수, 0, 음수를 포함합니다. 사람은 인지적 제한으로 모든 연락처를 기억하지 못하듯, 컴퓨터도 메모리 제한으로 무한한 정수를 표현할 수 없습니다. 따라서 기본 제공 범위를 넘어서는 거대한 수를 다뤄야 한다면 별도의 외부 라이브러리를 고려해야 합니다.
- 실수: 수학의 실수와 유사하지만, 컴퓨터는 이를 근사치로 저장합니다.
- 정밀도: 단정밀도(float)와 배정밀도(double)로 나뉘며, 소수점 이하 몇 자리까지 정확하게 표현할 수 있는지를 다룹니다.
- 주의: 근사치 저장 방식 특성상 소수점 수치가 정확해야 하는 곳(금융권 계산, 정밀 물리 시뮬레이션 등)에서는 반드시 꼼꼼한 검증이 필요합니다. 더 깊은 내용은 IEEE 754 표준을 참고하세요. (영어입니다.)
생존 범위
메모리는 유한하기 때문에, 수명이 다한 변수를 즉각 소멸시켜야 다른 데이터가 들어올 공간이 생기기 때문이죠. 변수는 임시로 기억할 때 사용하는 언어의 기능입니다. 따라서 "이 데이터를 얼마나 오래 기억할 것인가?"가 중요합니다.
- 이는 변수가 메모리에서 언제까지 살아있을지를 결정하는 것이며, 프로그래머가 지정할 수 있습니다.
- 보통 { } 블록 안에서 선언되어 사용되다가, 블록이 끝나면 냉정하게 소멸하여 메모리 공간을 반납합니다.
- 이러한 생존 범위 제약 역시 유한한 메모리를 효율적으로 재사용하기 위한 규칙입니다.
루프 (Loop)
루프는 특정한 조건이 만족될 때까지 동일한 작업을 반복하여 결과를 얻어야 할 때 사용하는 문 입니다. 프로그래밍에서 반복문을 사용하는 이유는 단순히 코드를 줄이기 위함이 아니라 데이터의 양이 아무리 많아져도 동일한 로직으로 처리하기 위해서입니다.
C언어에서 대표적으로 사용하는 반복문은 for와 while입니다. 이번 챕터 예를 보면 while 문만 사용되었다는 점을 확인할 수 있습니다.
while 루프의 특징
- 조건 우선: while (조건) 형식을 취하며, 괄호 안의 조건이 '참'인 동안에만 블록 내부의 코드를 실행합니다.
- 유연성: 반복 횟수가 명확하지 않거나, 특정 상태에 도달할 때까지 계속 돌아야 하는 상황(예: 사용자 입력 대기, 네트워크 신호 대기 등)에 적합합니다.
while( {condition } )
{
}
루프 작성 시 주의할 점
- 종료 조건의 확실함: 루프 내부에서 조건을 '거짓'으로 만드는 장치가 없다면, 프로그램은 영원히 멈추지 않는 무한 루프(Infinite Loop)에 빠져 메모리와 CPU 자원을 갉아먹게 됩니다.
- 가독성: while은 자유도가 높은 만큼 코드가 지저분해지기 쉽습니다. 반복 횟수가 명확하다면 for문을, 조건에 따른 반복이 중요하다면 while문을 선택하는 안목이 필요합니다.
포맷 스트링 (Format String)
printf 함수에서 데이터를 어떤 모양으로 출력할지 결정하는 규격입니다. 큰따옴표 "" 안에 %로 시작하는 기호를 넣어 사용하며, 뒤에 오는 변수의 값을 해당 위치에 치환하여 보여줍니다.
대표적인 서식 지정자
| 구분 | 설명 |
| %d | 정수(Decimal)를 출력합니다. |
| %f | 실수(Float)를 출력합니다. |
| %s | 문자열(String)을 출력합니다. |
| %c | 문자(Character) 한 개를 출력합니다. |
※ 참고: 현대 언에서는 타입에 따라 %ld를 사용해야 하는 경우도 있습니다.
좀 더 '이쁘게' (폭 지정)
우리가 1-3 연습문제를 수정하면서 가장 공들여야 할 부분입니다. 숫자의 길이에 상관없이 줄을 맞추고 싶을 때 사용합니다.
- %3d: 정수를 출력하되, 무조건 3칸의 공간을 확보하고 오른쪽으로 정렬합니다.
- %6.1f: 실수를 출력하되, 전체 6칸의 공간을 확보하고 소수점 아래는 1자리만 표시합니다.
왜 중요한가?
컴퓨터는 기본적으로 왼쪽 정렬을 수행하지만, 숫자 데이터(특히 표 형태)는 우측 정렬이 되어 있어야 사람이 읽기 편합니다. 포맷 스트링은 바로 그 '가독성'을 위해 사용하는 서식입니다.
연산자 (Operaters)
연산자는 CPU의 가장 기본적이고 핵심적인 기능입니다. 이번 글에서는 사칙연산을 넘어선 '오칙연산'에 대해 소개합니다.
왜 5칙연산인가?
우리가 흔히 아는 사칙연산(+, -, *, /) 외에 프로그래밍에서는 아주 중요한 연산자가 하나 더 있습니다.
- 나머지 연산자 (%): 나눗셈을 하고 남은 '나머지' 값을 구합니다. 홀수/짝수 판별이나 특정 범위 내의 숫자를 순환시킬 때 필수적입니다.
= (대입 연산자)
수학에서 =은 좌변과 우변이 같다는 뜻이지만, 프로그래밍에서는 '연산자'입니다.
- 의미: "우변에 있는 값을 계산해서 좌변에 있는 메모리(변수)에 집어넣어라!"라는 동작을 수행합니다.
- 그래서 프로그래밍에서는 이를 대입 연산자(Assignment Operator)라고 부릅니다.
연산자 우선순위
연산자 사이에는 서열이 있습니다.
- 수학과 마찬가지로 곱셈, 나눗셈, 나머지가 덧셈, 뺄셈보다 먼저 계산됩니다.
- 주의할 점: 대입 연산자(=)는 우선순위가 매우 낮습니다. 우변의 모든 계산(사칙연산 등)이 다 끝나고 나서야 마지막에 변수에 값이 담기게 됩니다.
Exercise 1-3
위 코드를 컴파일하고 실행하면 화씨 -> 섭씨 변환 테이블 형태로 나옵니다.
이번 장에서 주석, 변수, 연산자, 반복문, printf 함수에서 사용할 수 있는 포맷 스트링에 대한 방대한 설명이 갑자기 나옵니다.
이렇게 짧은 구간에 방대한 내용이 압축되어 소개되는 것은 기존에 언어를 사용했다는 전제가 깔려 있는 것 같습니다.
/* (생략) */
int main(int argc, char** argv)
{
/* (생략) */
printf("Fahrenheit-Celsius Table\n");
while (fahr <= upper)
/* (생략) */
}
위 코드에서 while문 위 printf("..."); 만 추가하면 끝나는 문제입니다.
그래서 최종적으로 아래와 같이 코드를 작성하였습니다.
#include <stdio.h>
/**
* print Fahrenheit-Celsius table
* for fahr = 0, 20, ..., 300
*/
int main(int argc, char** argv)
{
int lower = 0; /* lower limit of temperature scale */
int upper = 300; /* upper limit */
int step = 20; /* step size */
int fahr = lower;
int celsius = 0;
printf("Fahrenheit-Celsius Table\n");
while (fahr <= upper)
{
celsius = 5 * (fahr-32) / 9;
printf("%d\t%d\n", fahr, celsius);
fahr = fahr + step;
}
return 0;
}
위 코드를 컴파일한 후 실행 결과는 아래와 같습니다.
$ ./a.out
Fahrenheit-Celsius Table
0 -17
20 -6
40 4
60 15
80 26
100 37
120 48
140 60
160 71
180 82
200 93
220 104
240 115
260 126
280 137
300 148
최종적으로 서식 문자열과 Escape Character을 활용하여 아래와 같이 소스코드를 작성하였습니다.
#include <stdio.h>
/**
* print Fahrenheit-Celsius table
* for fahr = 0, 20, ..., 300
*/
int main(int argc, char** argv)
{
int fahr, celsius;
int lower, upper, step;
lower = 0; /* lower limit of temperature scale */
upper = 300; /* upper limit */
step = 20; /* step size */
fahr = lower;
printf("============================\n");
printf("| Fahrenheit-Celsius Table |\n"); // 제목 추가
printf("============================\n");
printf("\n");
printf("----------------------------\n");
printf("| Fahrenheit | Celsius |\n");
printf("----------------------------\n");
while (fahr <= upper) {
celsius = 5 * (fahr-32) / 9;
printf("| %10d | %11d |\n", fahr, celsius);
fahr = fahr + step;
}
printf("----------------------------\n");
return 0;
}
실행 결과가 조금 더 이쁘게 꾸며봤습니다.
$ ./a.out
============================
| Fahrenheit-Celsius Table |
============================
----------------------------
| Fahrenheit | Celsius |
----------------------------
| 0 | -17 |
| 20 | -6 |
| 40 | 4 |
| 60 | 15 |
| 80 | 26 |
| 100 | 37 |
| 120 | 48 |
| 140 | 60 |
| 160 | 71 |
| 180 | 82 |
| 200 | 93 |
| 220 | 104 |
| 240 | 115 |
| 260 | 126 |
| 280 | 137 |
| 300 | 148 |
----------------------------
마무리
갑자기 이것저것 많은 내용이 한꺼번에 나오는데, 설명이 너무 압축적으로 되어 있어 당황했네요.
이래서 불친절하다고 했던 것 같네요.
다음은 "The C Programming Language: Exercise 1-4" 문제 풀어보겠습니다.
'개발기 > The C Programming Language' 카테고리의 다른 글
| 문제풀이 | The C Programming Language (K&R): Exercise 1-6 (0) | 2026.05.23 |
|---|---|
| 문제풀이 | The C Programming Language (K&R): Exercise 1-5 (0) | 2026.05.04 |
| 문제풀이 | The C Programming Language (K&R): Exercise 1-4 (0) | 2026.05.04 |
| 문제풀이 | The C Programming Language (K&R): Exercise 1-2 (0) | 2026.04.28 |
| 문제풀이 | The C Programming Language (K&R): Exercise 1-1 (0) | 2026.04.25 |