[Modern C] Chapter 03. 결국은 제어 (Exercise)

문연수·2023년 1월 24일
0

Modern C

목록 보기
2/2

03. 결국은 제어

- 1. if 제어 표현식 수정

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	double A[5] = {
		[0] = 9.0,
		[1] = 2.9,
		[4] = 3.E+25,
		[3] = .00007,
	};

	for (size_t i = 0; i < 5; i++) {
		if (A[i] > 5.0) {
			printf("element %zu is %g, \tits square is %g\n",
				i,
				A[i],
				A[i] * A[i]
			);
		}
	}

	return EXIT_SUCCESS;
}

- 2. size_t i = 0; 일때 i--; 를 수행하면?

#include <stdio.h>
#include <stdint.h>

int calc_bits(size_t value)
{
	int nbits = 0;

	while (value > 0)
		nbits++, value >>= 1;

	return nbits;
}

int main(void)
{
	printf("calc_bits(SIZE_MAX): %d\n", calc_bits(SIZE_MAX));
	printf("(size_t) 0 - 1: %zu\n", (size_t) 0 - 1);

	return 0;
}

size_tunsigned 자료형이므로 그 값이 0 이하가 되면 integer overflow 가 발생하게 된다. 더 정확하게 표준에 의거하면 unsigned integer 에 대한 overflow 는 존재하지 않고 well-defined behavior 인 rules of modular arithmetic modulo 2n2^n 이 수행된다.

따라서 그 결과는 2n12^n - 1 (nn 은 오브젝트를 표현하기 위해 사용된 비트 수) 이 된다. 필자의 컴퓨터는 n 이 64 이므로 결과는 2n12^n - 1 인 (18,446,744,073,709,551,61518,446,744,073,709,551,615) 가 된다.

- 3. printf 문을 추가하여 분석

#include <stdio.h>
#include <stdlib.h>

static double const eps1m01 = 1.0 - 0x1P-01;
static double const eps1p01 = 1.0 + 0x1P-01;
static double const eps1m24 = 1.0 - 0x1P-24;
static double const eps1p24 = 1.0 + 0x1P-24;

int main(int argc, char *argv[argc + 1])
{
	for (int i = 1; i < argc; ++i) {
		double const a = strtod(argv[i], 0);
		double x = 1.0;

		printf("target number: %g\n", a);
		for (;;) {
			double prod = a * x;
			if (prod < eps1m01) {
				x *= 2.0;
			} else if (eps1p01 < prod) {
				x *= 0.5;
			} else {
				break;
			}
            
			printf("x = %.12f\n", x);
		}

		for (;;) {
			double prod = a * x;
			if ((prod < eps1m24) || (eps1p24 < prod))
				x *= (2.0 - prod);
			else
				break;

			printf("x = %.12f\n", x);
		}

		printf("heron: a=%.5e,\tx=%.5e,\ta*x=%.12f\n\n",
			a, x, a*x);
	}

	return EXIT_SUCCESS;
}

- 4. argcargv 의 사용 방법

argc 는 프로그램 실행 시 전달된 인자의 개수를 의미하며 argv 는 각각의 인자들을 가리키는 문자열이다. 예제 3-1 프로그램에서는 프로그램의 인자(argv)로 실수를 전달받고 이를 헤론의 근사 공식에 대입하여 사용한다. 반복 횟수는 argc 를 통해 결정한다.

- 5. eps1m01 의 값을 화면에 출력하고 값을 바꿔보기

#include <stdio.h>
#include <stdlib.h>

static double const eps1m05 = 1.0 - 0x1P-05;
static double const eps1p05 = 1.0 + 0x1P-05;
static double const eps1m24 = 1.0 - 0x1P-24;
static double const eps1p24 = 1.0 + 0x1P-24;

int main(int argc, char *argv[argc + 1])
{
	printf("eps1m05: %f\n", eps1m05);
	printf("eps1p05: %f\n", eps1m05);

	for (int i = 1; i < argc; ++i) {
		double const a = strtod(argv[i], 0);
		double x = 1.0;

		printf("target number: %g\n", a);
		for (;;) {
			double prod = a * x;
			if (prod < eps1m05) {
				x *= 2.0;
			} else if (eps1p05 < prod) {
				x *= 0.5;
			} else {
				break;
			}

			printf("x = %.12f\n", x);
		}

		for (;;) {
			double prod = a * x;
			if ((prod < eps1m24) || (eps1p24 < prod))
				x *= (2.0 - prod);
			else
				break;

			printf("x = %.12f\n", x);
		}

		printf("heron: a=%.5e,\tx=%.5e,\ta*x=%.12f\n\n",
			a, x, a*x);
	}

	return EXIT_SUCCESS;
}

- 6. switch 문과 break 문 테스트

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[argc + 1])
{
	char arg;

	if (argc != 2) {
		fprintf(stderr, "usage: %s <character>\n", argv[0]);
		exit(EXIT_FAILURE);
	} else {
		arg = argv[1][0];
	}

	switch (arg) {
	case 'm':
		puts("this is a magpie");
		break;

	case 'r':
		puts("this is a raven");
		// break;

	case 'j':
		puts("this is a jay");
		break;

	case 'c':
		puts("this is a chough");
		break;

	default:
		puts("this is an unknown corvid");
	}

	return 0;
}

출처

[책] 모던 C: 전문가를 위한 C 작성법! (옌스 구스테드 지음; 남기혁 옮김)

profile
2000.11.30

0개의 댓글