97 – 기타 수학 함수

수학 함수는 몇몇 특정한 성질이 있는 함수가 아닌 경우에는 그냥 직접 보고 실행해 보면 되는 함수들이 많이 있다. 게다가 기초적인 수학을 할 줄 안다는 전재로 있기 때문에 별도로 수학에 대한 설명은 더 이상 필요가 없다. 따라서 수학 함수 중에서도 좀 자주 이용되는 몇 가지 함수들에 대해서 이름과 기능만 좀 적어보겠다.

  • 함수 이름  | 기능
  • sin | 사인 값을 구한다.
  • cos | 코사인 값을 구한다.
  • tan | 탄젠트 값을 구한다.
  • exp | e^x를 구한다.
  • log | 로그(자연 대수)를 구한다.
  • log10 | 상용 로그(상용 대수)를 구한다.
  • frexp | double형 데이터를 가수부와 지수부로 나눈다.
  • ldexp | 가수부와 지수부로부터 double형 데이터를 구한다.

95 – 난수 함수

난수 함수에 대해서는 여러곳에서 말들이 많아서 그런지 다들 그냥 들어봤다라고 해서 유명하다. rand 함수에 대해서 주로 그렇게 이야기를 하는데, 난수 함수를 쓰는데 있어서 주의해야 할 점이 있다.

기본적으로 난수를 만들기 위해서는 rand와 srand 함수를 사용하면 된다. rand함수는 0과 RAND_MAX 사이의 난수를 생성하고 srand는 해당되는 seed를 초기화 하기 때문에 rand함수가 생성하는 난수가 달라지게 된다.

  • 함수 이름 | 기능
  • rand | 난수를 생성한다.
  • srand | rand를 초기화한다.

가장 기본적인 예시부터 살펴보겠다. srand로 처음 seed를 정해서 생성한 다음, 난수를 생성해서 100으로 나눈 나머지를 출력해서 0~99까지 출력한다.

여기서 보면 프로그램을 여러 번 실행해도 똑같은 난수를 계속 생성하는 것을 볼 수 있다. 즉, seed가 고정된 상태에서는 동일한 난수밖에 생성되지 않는다.

이를 해결하기 위해서는 시간과 연동을 해야 한다. 시스템 타이머는 클락 단위로 세세하게 처리되기 때문에 프로그램 실행 때마다 항상 다른 seed로 만들어 낼 수 있다. 그래서 seed값을 유용하게 만들어서 이용할 수 있고, 이렇게 하면 실행할 때마다 rand 함수가 전부 다른 난수를 생성하게 된다.

94 – 나머지 함수

나머지를 구하는 함수 역시 구하고자 하는 유형에 따라 여러모로 다양하게 구성되어 있다. 나머지 함수이지만 몫 또한 같이 구해지는 함수들도 존재한다.

  • 함수 이름 | 기능
  • div | int형 나눗셈의 몫과 나머지를 구한다.
  • ldiv | long int 형 나눗셈의 몫과 나머지를 구한다.
  • fmod | double형 나눗셈의 나머지를 구한다.

예시를 보고 주어진 수의 몫과 나머지를 구하는 과정을 보면 함수 사용법을 알 수 있다.

또한 올림 및 버림 함수와 정수부 소수부를 나누는 함수 또한 존재한다. 이런 함수들은 암호학에서 이용하는 경우가 많다.

  • 함수 이름 | 기능
  • cell | double형 데이터의 소수점 이하를 올림한다.
  • floor | double형 데이터의 소수점 이하를 버린다.
  • modf | double형 데이터를 정수부와 소수부로 분할한다.

이 함수 또한 예제로 보면 이해하기 어려운 것은 없을 것이다.

93 – 절대값 함수

절대값을 구하는 함수는 각각의 형태에 따라서 각각의 함수가 따로 존재한다. 단, floating point를 이용하여 구해야 하는 double형의 경우에는 math.h에 구현되어 있다. (소수점 계산 작업 자체가 상당히 복잡한 구조라서 쉽게 할 수 없다.)

  • 함수 이름 | 기능
  • abs | int형 데이터의 절대값을 구한다.
  • labs | long int형 데이터의 절대값을 구한다.
  • fabs | double형 데이터의 절대값을 구한다.

예시를 보면 쉽게 알 수 있다.

92 – 수학 함수

수학 함수는 여러곳에서 사용되는 함수들이다. 기본적으로 컴퓨터의 존재가 계산을 위해 존재하는 함수이고, 비즈니스의 관점에서 또한 기본적인 수학 작업에 대한 요구는 끊임없이 요구되고 있다. POS, 전산관리 프로그램, 재정 관리 프로그램 등 비즈니스를 위해 기본적으로 이용되는 도구들 또한 컴퓨터에서 중요한 기능이기 때문에 절대로 빠질 수 없는 기능이 수학 관련된 함수이다.

전자상거래, 인터넷 뱅킹 등이 보편화됨녀서 서비스를 안전하게 제공하기 위해 암호화 기술들이 개발되는데, 이 또한 수학으로 이루어진 것이기 때문에 수학 함수는 중요하다. 게임 제작에서도 빠질 수 없다.

이렇게 보면 수학 관련된 함수에 대해서는 상당히 중요하다는 것을 알 수 있다. 그 중에서도 여러모로 많이 쓰는 수학 함수에 대해서 한번 쭉 짚고 넘어가자.

91 – 기타 입출력 함수

이 외에도 입출력에 관한 여러 함수들이 존재한다. 그 중에서도 좀 알아두면 유용할 것 같은 함수들을 정리해보겠다.

파일의 경우에는 읽고 쓰는 도중에 오류가 발생할 수 있는데, 이런 오류 함수들을 알아두면 좋을 거 같다. 파일로부터 더 이상 읽을 데이터가 없는지 또는 파일에 대한 동작이 제대로 이루어졌는지에 대한 점검을 쉽게 해주는 파일 오류 관련된 함수들이 존재한다.

파일 오류와 관련된 함수들로는 eof(end of file)인지, 파일 자체 오류인지, 오류 정보와 끝 정보를 초기화하는 그런 작업이 필요하다.

  • 함수 이름 | 기능
  • feof | 파일의 끝인지 확인한다.
  • ferror | 파일이 오류인지를 확인한다.
  • clearerr | 파일의 끝과 오류 정보를 초기화한다.

이런 함수 사용의 예시를 한번에 몰아서 작성해봤다. 읽기 전용 파일에 데이터를 쓰려고 하면 오류가 발생, 그 다음에 오류가 확인되고, 오류 정보를 clearerr를 사용해서 해제하는 예시를 작성하였다. 전체적인 흐름을 확인할 수 있어야 한다.

또한 파일을 읽고 쓰는 데 있어서도 처음부터 줄줄이 다 읽을 수는 없다. 주문형 비디오 서비스(VOD)를 예로 들어보자. 사용자가 원하는 부분 혹은 이전에 보던 부분에서 이어보기를 제공해 주는데, 이를 위해서는 특정 위치에서 읽을 수 있도록 해주기 때문이다. 파일 입출력에는 이런 기능들이 들어있고, 오래전부터 사용하던 C언어 또한 이런 입출력 함수를 가지고 있다.

  • 함수 이름 | 기능
  • ftell | 파일의 읽기/쓰기 포인터 값을 구한다.
  • rewind | 파일의 읽기/쓰기 포인터를 처음으로 되돌린다.

source 파일에 “ABCDEF”라는 데이터가 있다고 할 때, 파일을 읽은 다음에 한 문자씩 읽어서 읽은 값의 포인터 위치를 출력하는 예제를 작성하였다. 두번의 과정을 거쳐서 첫번째로 읽은 값은 포인터의 배열 위치가 2가 되었고, 그 다음에 원래대로 되돌려서 0번(처음) 위치를 가리키고 있다.

그리고 함수의 읽기/쓰기 포인터를 임의의 위치로 설정하는 함수 또한 존재한다. 어디를 기준으로 할 지에 대해서 특정 offset만큼 이동해서 처리할 수 있도록 해주는 것이다.

  • 함수 이름 | 기능
  • fseek | 파일의 읽기/쓰기 포인터를 임의의 위치로 설정한다.

이 함수의 두 번째 인수값이 offset 값인데, 의미가 있다.

  • whence | 의미
  • SEEK_SET | 파일의 시작
  • SEEK_CUR | 현재 읽기/쓰기 포인터 위치
  • SEEK_END | 파일의 끝

사용 예시를 보면 이 함수가 어떻게 이용되는지 알 수 있을 것이다. 시작 위치에서 우측으로 10칸 이동시킨 다음, 파일의 끝에서 읽어서 화면에 출력하는 예시이다.

90 – 파일 입출력 함수

표준 입출력을 통한 방식 이외에도 파일을 통한 데이터의 입력 및 출력이 있을 수 있다. 파일을 통해 입출력을 하기 위해서는 사용하고자 하는 파일을 열어야 하는데 이 때 사용하는 함수가 fopen, 사용이 끝난 파일은 닫아줘야 하는데 이 때 사용하는 함수가 fclose이다.

  • 함수 이름 | 의미
  • fopen | 파일을 연다
  • fclose | 파일을 닫는다

파일을 열 때에는 여는 파일에 대해서 어떠한 형태로 사용할지를 나타내줘야 한다. 그래서 fopen 함수는 두 번째 인수로 어떤 형태로 사용할지를 적어줘야 하는데, 적어주는 인수값과 의미가 다음과 같다.

  • 인수값 | 의미
  • r | 읽기 전용. 파일 존재해야 함.
  • w | 쓰기 전용. 파일이 없어도 되며, 만약 이미 존재한다면 기존 내용이 지워짐.
  • a | 추가용. 파일이 없어도 되며, 만약 임미 존재한다면 기존 내용 뒤에 추가됨.
  • rb | 바이너리 파일의 읽기 전용.
  • wb | 바이너리 파일의 쓰기 전용.
  • ab | 파이너리 파일의 추가용.
  • r+ | 읽기와 쓰기용.
  • w+ | 쓰기와 읽기용.
  • kyuling이라는 파일을 읽기 전용으로 사용하기 위해서는 다음과 같이 작성하면 된다. 대신 쓰기 작업을 할 수 없게 된다.

fopen(“kyuling”, “r”);

게다가 한 프로그램에서 동시에 열어서 사용할 수 있는 파일의 수는 제한적이다. 따라서 사용이 끝난 파일은 닫아주는 것이 바람직하다. fclose를 이용하여 닫으면 된다.

FILE *file;
file = fopen(“kyuling”, “w”);
fclose(file);

예제를 만들어서 진행해 보았다. 예제를 따라할 때, 파일이 없을 경우에는 리눅스의 touch 명령어를 이용하여 빈 파일을 만들어서 실습을 진행하면 된다. 소스 코드 밑에 실행하던 예시 명령어를 그대로 순차적으로 찍었다. 파일이 없으면 어떻게 되는지 보여주기 위해서이다.

이제는 파일을 통해 한 문자를 입출력하는 함수를 살펴보겠다. getchar와 putchar와 같이 한 문자만을 받아오는 함수가 존재했다. 파일 입출력에도 그와 마찬가지인 파일 입출력이 존재한다.

  • 함수 이름 | 기능
  • fgetc | 파일을 통해 한 문자를 입력받는다.
  • fputc | 파일에 한 문자를 출력한다.

이 함수의 사용법 또한 예제를 확인해보자. touch로 만든 파일을 vi를 이용해서 안에 내용을 입력하면 이미 데이터가 있는 파일을 만들 수 있다. 파일 내용을 확인 하기 위해 cat 명령어를 이용하여 직접 결과 파일을 확인해보았다.

서식을 갖춘 데이터의 입출력 또한 파일 입출력 함수에도 존재한다.

함수 이름 | 기능

fscanf | 파일을 통해 서식을 갖춘 데이터를 입력받는다.

fprintf | 데이터를 서식화하여 파일로 출력한다.

예시 코드로 확인하면 쉽게 확인할 수 있다. 전체적인 구조는 비슷한 편이다. 문자열을 저장했다가 단순히 읽어오는 프로그램이다.

파일의 데이터를 대용량으로 처리해야 할 일이 생길 수 있다. fread와 fwrite 함수를 통해 데이터를 한꺼번에 입출력을 하면 많은 데이터를 한번에 처리할 수 있다.

함수 이름 | 기능

fread | 파일을 통해 데이터를 한꺼번에 입력받는다.

fwrite  | 데이터를 한꺼번에 파일로 출력한다.

단순 예제라서 데이터는 얼마 없지만, buffer로 데이터를 읽고 나서 그대로 파일로 출력하는 예제를 만들어보았다.

마지막으로 읽어들인 문자를 파일로 되돌리는 함수가 있다. 문자열을 저장하고 있는 파일에서 특정 문자를 추출하고자 한다고 하면, 파일로부터 한 문자씩 읽다가 특정 문자를 읽으면 읽은 파일로부터 그대로 되돌리고 읽어야 한다. 그런 경우에 쓰는 함수가 ungetc 함수이다. (이건 왜 쓰는지 필자는 아직 잘 모르겠다. 옛날에 쓰는 사람들이 필요해서 만들었나보다 생각중임.)

함수 이름 | 기능

ungetc | 방금 읽은 문자를 파일로 되돌린다.

위에서 살짝 설명한 상황을 예시 코드로 작성해보았다. l 혹은 L을 만남녀 그 뒤부터 되돌려서 반환한다.

89 – 기본 입출력 함수

우선은 표준 입출력 장치를 통한 입출력에 대해 정리를 할 것이다. 표준 입출력에서 말하는 표준 입력은 키보드, 표준 출력은 모니터를 의미한다.

표준 입력을 통해 한 문자를 입력하고 출력하는 함수는 다음과 같다.

  • 함수이름 | 기능
  • getchar | 표준 입력을 통해 한 문자를 입력받는다.
  • putchar | 표준 출력을 통해 한 문자를 출력한다.

문자 하나를 입력받는 작업을 계속 이어서 진행하면 문자열을 입력받는 작업으로도 진행할 수 있다. 이를 통한 예제는 다음과 같은데, 입력받은 대문자를 소문자로 전환하는 프로그램이다. 마지막 입력으로 엔터를 치면 EOF로 인식해서 입력이 끝나는 것이다.

이제 여러 문자를 입력받아 문자열 단위로 입력받는 함수를 알아보겠다.

  • 함수 이름 | 기능
  • gets | 표준 입력을 통해 한 행의 문자열을 입력받는다.
  • puts | 표준 출력에 한 행의 문자열을 출력하고 개행한다.

입력 받은 내용을 그대로 출력하는 예제를 만들어서 진행해 보았다. gets에서 입력받은 경우, 끝이라는 것을 입력받으면 NULL을 반환한다. 그래서 마지막에 입력받은 부분이 NULL인지 아닌지를 체크하는 것이다.

이 다음으로 살펴볼 함수는 우리한테 익숙한 printf와 scanf이다. 이 함수들을 이용하면 ‘서식’이 지정된 문자열을 입력 및 출력할 수 있게 된다. 서식화된 입력을 통해서는 변수에 지정할 지정 타입을 서식화 할 수 있는 것이 되고, 서식화된 출력을 통해서는 서식화된 구조 및 서식에 맞는 변수 출력을 서식화하여 출력할 수 있게 된다. 서식으로 변환되는 데 이용되는 문자열을 서식 문자열이라고 하고,  흔히 %d, %s, %f 등으로 도중 도중에 사용하던 것이다.

우선은 scanf 함수에 대해서 살펴보도록 하겠다.

  • 함수 이름 | 기능
  • scanf | 표준 입력을 통해 서식을 갖춘 데이터를 입력받는다.

그리고 scanf의 변환 문자열은 다음과 같다.

  • 변환 문자열 | 의미
  • %o | 8진수 정수 형식으로 입력
  • %d | 10진수 정수 형식으로 입력
  • %ld | long형 10진 정수 형식으로 입력
  • %x | 16진수 정수 형식으로 입력
  • %f | float형 형식으로 입력
  • %lf | double형 형식으로 입력
  • %c | 문자 형식으로 입력
  • %s | 문자열 형식으로 입력

다음으로 우리에게 친숙한 printf형을 살펴보겠다.

  • 함수 이름 | 기능
  • printf | 데이터를 서식화하여 표준 출력으로 출력한다.

그리고 printf의 변환 문자열은 다음과 같다.

  • 변환 문자열 | 의미
  • %o | 8진수 정수 형식으로 출력
  • %d | 10진수 정수 형식으로 출력
  • %ld | long형 10진수 정수 형식으로 출력
  • %x | 16진수 정수 형식으로 출력
  • %u | 부호 없는 10진 정수 형식으로 출력
  • %f | 소수점 형식으로 출력
  • %e %E | 지수 형식으로 출력
  • %g %G | %e, %f 중 짧은 쪽, 소수점에 이어지는 0은 생략
  • %c |  문자 형식으로 출력
  • %s | 문자열 형식으로 출력

printf의 출력 변환 문자열에는 출력하는 폭, 자릿수 등을 지정할 수 있다. 옵션의 지정 형식은 다음과 같다.

%폭 자릿수 변환문자

예를 들어, 숫자 123을 출력할 때, %d, %5d, %-5d에 따라서 출력이 달라지게 된다.

%d: [123]
%5d: [  123]
%-5d: [123  ]

이런 식으로 총 자릿수를 5로 지정해서 5자리의 출력 공간에 123을 출력하는 것이 두 번째 예시이고, 세 번째 예시처럼 마이너스 부호를 붙이면 뒤로 5개의 자리를 만들기 때문에 뒤에 공백이 생기게 된다.

예시는 이전까지 하면서도 많이 했지만 예의상 작성해본다.

마지막으로 메모리를 통해 입출력을 진행하는 함수를 알아보도록 하겠다. sscanf와 sprintf 함수인데,  이 함수들은 키보드를 통한 표준 입출력이 아니라 메모리 영역을 통해서 데이터를 입력받고 출력하는 함수들이다. 메모리 자체에는 그냥 값이 들어있지만 이 두 함수를 이용하면 서식화된 메모리 데이터의 입출력이 가능하다.

함수 이름 | 기능

sscanf | 메모리 영역을 통해 서식을 갖춘 데이터를 입력받는다.

sprintf | 데이터를 서식화하여 메모리 영역으로 출력한다.

이것도 예시를 보자. 데이터를 10진수와 소수점 형태로 메모리에 저장한 후, 이를 8진수와 지수 형태로 읽여들이는 예시 프로그램을 작성하였다.

88 – 입출력 함수

대부분의 프로그램이 키보드를 통해 데이터를 입력받거나 파일로부터 데이터를 읽어 이를 처리하여 처리한 결과를 화면으로 출력하거나 디스크에 파일로 저장하는 일을 한다. 입출력은 프로그램에서 자주 일어나는 동작이기 때문에 라이브러리에서는 다양한 형태의 입출력 함수를 기본으로 제공하고 있다. 이를 이용하면 큰 부담 없이 데이터를 다양한 형식으로 입력하고 출력받는 프로그램을 구현할 수 있다.

우리가 일반적으로 입력받을 때 쓰던 scanf 함수 또한 입출력 함수에 해당된다.